diff --git a/CLI/venv/lib/python3.12/site-packages/ArgumentParser/__init__.py b/CLI/venv/lib/python3.12/site-packages/ArgumentParser/__init__.py new file mode 100644 index 0000000..47cd1ae --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/ArgumentParser/__init__.py @@ -0,0 +1,193 @@ +# Copyright 2015 (c) Tim Savannah +# LGPL v3 (see LICENSE file). Feel free to contact me with any questions! + +import sys + +class ArgumentParser(object): + ''' + A utility class for parsing command-line arguments. + + @param names list - This is a list of "names" which should reflect each argument. + @param shortOptions list - This is a list of short (-x val) options. Length should match names. If no short option is available, use 'None'. Omit the leading - + @param longOptions list - This is a list of long (--xyz val or --xyz= val) options. If no long option is available, use 'None'. Omit the leading -- + @param staticOptions list - This is a list of static options (arguments that have meaning just being present, without taking an additional value). + Any members of this list will be present in the results of #parse, set to True is present, otherwise False. + + @param multipleStaticOptions - A dictionary for multiple static arguments that resolve to one value. Key is the "name", values are all potential values. Ex: {'cheese' : ['--cheddar', 'gouda'] } presence of either 'gouda' or '--cheddar' in results would set cheese to True, otherwise False. + @param allowOtherArguments default False - if False, consider non-specified arguments as errors. + + @example +In [1]: from ArgumentParser import ArgumentParser + +In [2]: parser = ArgumentParser(['firstName', 'lastName', 'birthday'], + ...: ['f', 'l', 'b'], + ...: ['first-name', 'last-name', 'birthday'], + ...: ['--citizen'] + ...: ) + +In [3]: parser.parse('-f Tim --last-name=savannah --birthday 6/28'.split(' ')) +Out[3]: +{'errors': [], + 'result': {'--citizen': False, + 'birthday': '6/28', + 'firstName': 'Tim', + 'lastName': 'savannah'}, + 'warnings': []} + +In [4]: parser.parse('-f Tim --last-name=savannah --citizen'.split(' ')) +Out[4]: +{'errors': [], + 'result': {'--citizen': True, 'firstName': 'Tim', 'lastName': 'savannah'}, + 'warnings': []} + +>>> import ArgumentParser +>>> parser = ArgumentParser.ArgumentParser( ('one', 'two'), ('o', 't'), ('uno', 'dos'), ('x'), {'cheese' : ['cheddar', 'gouda'], 'baby' : {'child', 'infant'}} ) +>>> parser.parse(['-o', '1', 'cheddar']) +{'errors': [], 'result': {'baby': False, 'cheese': True, 'x': False, 'one': '1'}, 'unmatched': [], 'warnings': []} + + ''' + + def __init__(self, names, shortOptions, longOptions, staticOptions=None, multipleStaticOptions=None, allowOtherArguments=False): + namesLen = len(names) + if namesLen != len(shortOptions) or namesLen != len(longOptions): + raise ValueError('names, shortOptions, longOptions must all have the same length. use None of there is no equivlant.') + + self.names = names + self.shortOptions = shortOptions + self.longOptions = longOptions + self.staticOptions = set(staticOptions or []) + self.multipleStaticOptions = multipleStaticOptions + self.allowOtherArguments = allowOtherArguments + + + def parse(self, args=None): + ''' + parse - Parses provided arguments and returns information on them. If using sys.argv, omit the first argument. + If dealing with a string of arguments (custom shell or something?), `shlex.parse('args "as expected" k')` is your friend. + + @param args list - parse these arguments. If None (default), sys.argv[1:] is used. + + @return - dict keys are + 'result' => dictionary of result name->value + 'errors' => list of strings of errors or empty list + 'warnings' => list of strings of warnings, or empty list + 'unmatched' => all unmatched params, in order + ''' + if args is None: + args = sys.argv[1:] + result = {} + errors = [] + warnings = [] + unmatched = [] + + argsLen = len(args) + i = 0 + while i < argsLen: + arg = args[i] + + if self.multipleStaticOptions is not None: + foundIt = False + for optionName, possibleValues in self.multipleStaticOptions.items(): + if arg in possibleValues: + if optionName in result: + warnings.append("Argument '%s' specified more than once (at position %d)" %(arg, i)) + else: + result[optionName] = True + foundIt = True + break + if foundIt is True: + i += 1 + continue + + if arg in self.staticOptions: + if arg in result: + warnings.append("Argument '%s' specified more than once (at position %d)" %(arg, i)) + else: + result[arg] = True + i += 1 + continue + + if arg.startswith('--'): + try: + equalSignIdx = arg.index('=') + argName = arg[2:equalSignIdx] + except ValueError: + equalSignIdx = False + argName = arg[2:] + try: + argIdx = self.longOptions.index(argName) + except ValueError: + errors.append("Unknown argument '%s' (at position %d)" %(arg, i,)) + i += 1 + continue + + name = self.names[argIdx] + if name in result: + warnings.append("Option '%s' specified more than once. Using latter value (at position %d)" %(name, i)) + + if equalSignIdx is not False: + val = arg[equalSignIdx+1:] + if len(val) == 0: + errors.append('Equal sign used and no value on \'%s\' (at position %d)' %(arg, i)) + i += 1 + continue + result[name] = val + i += 1 + continue + else: + if i+1 >= argsLen: + errors.append('No equal sign provided on assignment option, and no more arguments to try with \'%s\' (at position %d)' %(arg, i)) + i += 2 + continue + val = args[i+1] + result[name] = val + i += 2 + continue + + elif arg.startswith('-'): + argName = arg[1:] + if i+1 >= argsLen: + errors.append('No assignment on short option %s (at position %d)' %(arg, i)) + i += 2 + continue + + try: + argIdx = self.shortOptions.index(argName) + except ValueError: + errors.append("Unknown option '%s' (at position %d)" %(arg, i)) + i += 1 + continue + + name = self.names[argIdx] + if name in result: + warnings.append("Argument \'%s\' specified more than once, using latter value (at position %d)" %(name, i)) + + result[name] = args[i+1] + i += 2 + continue + + else: + if self.allowOtherArguments is False: + errors.append('Unknown argument \'%s\' (at position %d)' %(arg, i)) + + unmatched.append(arg) + + i += 1 + continue + + for staticOption in self.staticOptions: + if staticOption not in result: + result[staticOption] = False + + if self.multipleStaticOptions is not None: + foundItems = set(result.keys()) + multipleOptions = set(self.multipleStaticOptions.keys()) + + for optionName in multipleOptions.difference(foundItems): + result[optionName] = False + + return { 'result' : result, 'errors' : errors, 'warnings' : warnings, 'unmatched' : unmatched } + + + +# vim: sw=4 ts=4 noexpandtab diff --git a/CLI/venv/lib/python3.12/site-packages/ArgumentParser/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/ArgumentParser/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..364ec09 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/ArgumentParser/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/X.py b/CLI/venv/lib/python3.12/site-packages/Xlib/X.py new file mode 100644 index 0000000..826854f --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/X.py @@ -0,0 +1,424 @@ +# Xlib.X -- basic X constants +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +# Avoid overwriting None if doing "from Xlib.X import *" +NONE = 0 + +ParentRelative = 1 # background pixmap in CreateWindow + # and ChangeWindowAttributes + +CopyFromParent = 0 # border pixmap in CreateWindow + # and ChangeWindowAttributes + # special VisualID and special window + # class passed to CreateWindow + +PointerWindow = 0 # destination window in SendEvent +InputFocus = 1 # destination window in SendEvent +PointerRoot = 1 # focus window in SetInputFocus +AnyPropertyType = 0 # special Atom, passed to GetProperty +AnyKey = 0 # special Key Code, passed to GrabKey +AnyButton = 0 # special Button Code, passed to GrabButton +AllTemporary = 0 # special Resource ID passed to KillClient +CurrentTime = 0 # special Time +NoSymbol = 0 # special KeySym + + +#----------------------------------------------------------------------- +# Event masks: +# +NoEventMask = 0 +KeyPressMask = (1<<0) +KeyReleaseMask = (1<<1) +ButtonPressMask = (1<<2) +ButtonReleaseMask = (1<<3) +EnterWindowMask = (1<<4) +LeaveWindowMask = (1<<5) +PointerMotionMask = (1<<6) +PointerMotionHintMask = (1<<7) +Button1MotionMask = (1<<8) +Button2MotionMask = (1<<9) +Button3MotionMask = (1<<10) +Button4MotionMask = (1<<11) +Button5MotionMask = (1<<12) +ButtonMotionMask = (1<<13) +KeymapStateMask = (1<<14) +ExposureMask = (1<<15) +VisibilityChangeMask = (1<<16) +StructureNotifyMask = (1<<17) +ResizeRedirectMask = (1<<18) +SubstructureNotifyMask = (1<<19) +SubstructureRedirectMask = (1<<20) +FocusChangeMask = (1<<21) +PropertyChangeMask = (1<<22) +ColormapChangeMask = (1<<23) +OwnerGrabButtonMask = (1<<24) + +#----------------------------------------------------------------------- +# Event names: +# +# Used in "type" field in XEvent structures. Not to be confused with event +# masks above. They start from 2 because 0 and 1 are reserved in the +# protocol for errors and replies. +# +KeyPress = 2 +KeyRelease = 3 +ButtonPress = 4 +ButtonRelease = 5 +MotionNotify = 6 +EnterNotify = 7 +LeaveNotify = 8 +FocusIn = 9 +FocusOut = 10 +KeymapNotify = 11 +Expose = 12 +GraphicsExpose = 13 +NoExpose = 14 +VisibilityNotify = 15 +CreateNotify = 16 +DestroyNotify = 17 +UnmapNotify = 18 +MapNotify = 19 +MapRequest = 20 +ReparentNotify = 21 +ConfigureNotify = 22 +ConfigureRequest = 23 +GravityNotify = 24 +ResizeRequest = 25 +CirculateNotify = 26 +CirculateRequest = 27 +PropertyNotify = 28 +SelectionClear = 29 +SelectionRequest = 30 +SelectionNotify = 31 +ColormapNotify = 32 +ClientMessage = 33 +MappingNotify = 34 +LASTEvent = 35 # must be bigger than any event + + +#----------------------------------------------------------------------- +# Key masks: +# +# Used as modifiers to GrabButton and GrabKey, results of QueryPointer, +# state in various key-, mouse-, and button-related events. +# +ShiftMask = (1<<0) +LockMask = (1<<1) +ControlMask = (1<<2) +Mod1Mask = (1<<3) +Mod2Mask = (1<<4) +Mod3Mask = (1<<5) +Mod4Mask = (1<<6) +Mod5Mask = (1<<7) + + +#----------------------------------------------------------------------- +# Modifier names: +# +# Used to build a SetModifierMapping request or to read a +# GetModifierMapping request. These correspond to the masks defined above. +# +ShiftMapIndex = 0 +LockMapIndex = 1 +ControlMapIndex = 2 +Mod1MapIndex = 3 +Mod2MapIndex = 4 +Mod3MapIndex = 5 +Mod4MapIndex = 6 +Mod5MapIndex = 7 + +#----------------------------------------------------------------------- +# Button masks: +# +# Used in same manner as Key masks above. Not to be confused with button +# names below. Note that 0 is already defined above as "AnyButton". +# +Button1Mask = (1<<8) +Button2Mask = (1<<9) +Button3Mask = (1<<10) +Button4Mask = (1<<11) +Button5Mask = (1<<12) + +AnyModifier = (1<<15) # used in GrabButton, GrabKey + +#----------------------------------------------------------------------- +# Button names: +# +# Used as arguments to GrabButton and as detail in ButtonPress and +# ButtonRelease events. Not to be confused with button masks above. +# Note that 0 is already defined above as "AnyButton". +# +Button1 = 1 +Button2 = 2 +Button3 = 3 +Button4 = 4 +Button5 = 5 + + +#----------------------------------------------------------------------- +# XXX These still need documentation -- for now, read +# +NotifyNormal = 0 +NotifyGrab = 1 +NotifyUngrab = 2 +NotifyWhileGrabbed = 3 +NotifyHint = 1 +NotifyAncestor = 0 +NotifyVirtual = 1 +NotifyInferior = 2 +NotifyNonlinear = 3 +NotifyNonlinearVirtual = 4 +NotifyPointer = 5 +NotifyPointerRoot = 6 +NotifyDetailNone = 7 +VisibilityUnobscured = 0 +VisibilityPartiallyObscured = 1 +VisibilityFullyObscured = 2 +PlaceOnTop = 0 +PlaceOnBottom = 1 +FamilyInternet = 0 +FamilyDECnet = 1 +FamilyChaos = 2 +FamilyServerInterpreted = 5 +FamilyInternetV6 = 6 +PropertyNewValue = 0 +PropertyDelete = 1 +ColormapUninstalled = 0 +ColormapInstalled = 1 +GrabModeSync = 0 +GrabModeAsync = 1 +GrabSuccess = 0 +AlreadyGrabbed = 1 +GrabInvalidTime = 2 +GrabNotViewable = 3 +GrabFrozen = 4 +AsyncPointer = 0 +SyncPointer = 1 +ReplayPointer = 2 +AsyncKeyboard = 3 +SyncKeyboard = 4 +ReplayKeyboard = 5 +AsyncBoth = 6 +SyncBoth = 7 +RevertToNone = 0 +RevertToPointerRoot = PointerRoot +RevertToParent = 2 +Success = 0 +BadRequest = 1 +BadValue = 2 +BadWindow = 3 +BadPixmap = 4 +BadAtom = 5 +BadCursor = 6 +BadFont = 7 +BadMatch = 8 +BadDrawable = 9 +BadAccess = 10 +BadAlloc = 11 +BadColor = 12 +BadGC = 13 +BadIDChoice = 14 +BadName = 15 +BadLength = 16 +BadImplementation = 17 +FirstExtensionError = 128 +LastExtensionError = 255 +InputOutput = 1 +InputOnly = 2 +CWBackPixmap = (1<<0) +CWBackPixel = (1<<1) +CWBorderPixmap = (1<<2) +CWBorderPixel = (1<<3) +CWBitGravity = (1<<4) +CWWinGravity = (1<<5) +CWBackingStore = (1<<6) +CWBackingPlanes = (1<<7) +CWBackingPixel = (1<<8) +CWOverrideRedirect = (1<<9) +CWSaveUnder = (1<<10) +CWEventMask = (1<<11) +CWDontPropagate = (1<<12) +CWColormap = (1<<13) +CWCursor = (1<<14) +CWX = (1<<0) +CWY = (1<<1) +CWWidth = (1<<2) +CWHeight = (1<<3) +CWBorderWidth = (1<<4) +CWSibling = (1<<5) +CWStackMode = (1<<6) +ForgetGravity = 0 +NorthWestGravity = 1 +NorthGravity = 2 +NorthEastGravity = 3 +WestGravity = 4 +CenterGravity = 5 +EastGravity = 6 +SouthWestGravity = 7 +SouthGravity = 8 +SouthEastGravity = 9 +StaticGravity = 10 +UnmapGravity = 0 +NotUseful = 0 +WhenMapped = 1 +Always = 2 +IsUnmapped = 0 +IsUnviewable = 1 +IsViewable = 2 +SetModeInsert = 0 +SetModeDelete = 1 +DestroyAll = 0 +RetainPermanent = 1 +RetainTemporary = 2 +Above = 0 +Below = 1 +TopIf = 2 +BottomIf = 3 +Opposite = 4 +RaiseLowest = 0 +LowerHighest = 1 +PropModeReplace = 0 +PropModePrepend = 1 +PropModeAppend = 2 +GXclear = 0x0 +GXand = 0x1 +GXandReverse = 0x2 +GXcopy = 0x3 +GXandInverted = 0x4 +GXnoop = 0x5 +GXxor = 0x6 +GXor = 0x7 +GXnor = 0x8 +GXequiv = 0x9 +GXinvert = 0xa +GXorReverse = 0xb +GXcopyInverted = 0xc +GXorInverted = 0xd +GXnand = 0xe +GXset = 0xf +LineSolid = 0 +LineOnOffDash = 1 +LineDoubleDash = 2 +CapNotLast = 0 +CapButt = 1 +CapRound = 2 +CapProjecting = 3 +JoinMiter = 0 +JoinRound = 1 +JoinBevel = 2 +FillSolid = 0 +FillTiled = 1 +FillStippled = 2 +FillOpaqueStippled = 3 +EvenOddRule = 0 +WindingRule = 1 +ClipByChildren = 0 +IncludeInferiors = 1 +Unsorted = 0 +YSorted = 1 +YXSorted = 2 +YXBanded = 3 +CoordModeOrigin = 0 +CoordModePrevious = 1 +Complex = 0 +Nonconvex = 1 +Convex = 2 +ArcChord = 0 +ArcPieSlice = 1 +GCFunction = (1<<0) +GCPlaneMask = (1<<1) +GCForeground = (1<<2) +GCBackground = (1<<3) +GCLineWidth = (1<<4) +GCLineStyle = (1<<5) +GCCapStyle = (1<<6) +GCJoinStyle = (1<<7) +GCFillStyle = (1<<8) +GCFillRule = (1<<9) +GCTile = (1<<10) +GCStipple = (1<<11) +GCTileStipXOrigin = (1<<12) +GCTileStipYOrigin = (1<<13) +GCFont = (1<<14) +GCSubwindowMode = (1<<15) +GCGraphicsExposures = (1<<16) +GCClipXOrigin = (1<<17) +GCClipYOrigin = (1<<18) +GCClipMask = (1<<19) +GCDashOffset = (1<<20) +GCDashList = (1<<21) +GCArcMode = (1<<22) +GCLastBit = 22 +FontLeftToRight = 0 +FontRightToLeft = 1 +FontChange = 255 +XYBitmap = 0 +XYPixmap = 1 +ZPixmap = 2 +AllocNone = 0 +AllocAll = 1 +DoRed = (1<<0) +DoGreen = (1<<1) +DoBlue = (1<<2) +CursorShape = 0 +TileShape = 1 +StippleShape = 2 +AutoRepeatModeOff = 0 +AutoRepeatModeOn = 1 +AutoRepeatModeDefault = 2 +LedModeOff = 0 +LedModeOn = 1 +KBKeyClickPercent = (1<<0) +KBBellPercent = (1<<1) +KBBellPitch = (1<<2) +KBBellDuration = (1<<3) +KBLed = (1<<4) +KBLedMode = (1<<5) +KBKey = (1<<6) +KBAutoRepeatMode = (1<<7) +MappingSuccess = 0 +MappingBusy = 1 +MappingFailed = 2 +MappingModifier = 0 +MappingKeyboard = 1 +MappingPointer = 2 +DontPreferBlanking = 0 +PreferBlanking = 1 +DefaultBlanking = 2 +DisableScreenSaver = 0 +DisableScreenInterval = 0 +DontAllowExposures = 0 +AllowExposures = 1 +DefaultExposures = 2 +ScreenSaverReset = 0 +ScreenSaverActive = 1 +HostInsert = 0 +HostDelete = 1 +EnableAccess = 1 +DisableAccess = 0 +StaticGray = 0 +GrayScale = 1 +StaticColor = 2 +PseudoColor = 3 +TrueColor = 4 +DirectColor = 5 +LSBFirst = 0 +MSBFirst = 1 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/XK.py b/CLI/venv/lib/python3.12/site-packages/Xlib/XK.py new file mode 100644 index 0000000..4b8bf8c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/XK.py @@ -0,0 +1,89 @@ +# Xlib.XK -- X keysym defs +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA +# +# This module defines some functions for working with X keysyms as well +# as a modular keysym definition and loading mechanism. See the keysym +# definition modules in the Xlib/keysymdef directory. + +from Xlib.X import NoSymbol + +def string_to_keysym(keysym): + '''Return the (16 bit) numeric code of keysym. + + Given the name of a keysym as a string, return its numeric code. + Don't include the 'XK_' prefix, just use the base, i.e. 'Delete' + instead of 'XK_Delete'.''' + return globals().get('XK_' + keysym, NoSymbol) + +def load_keysym_group(group): + '''Load all the keysyms in group. + + Given a group name such as 'latin1' or 'katakana' load the keysyms + defined in module 'Xlib.keysymdef.group-name' into this XK module.''' + if '.' in group: + raise ValueError('invalid keysym group name: %s' % group) + + G = globals() #Get a reference to XK.__dict__ a.k.a. globals + + #Import just the keysyms module. + mod = __import__('Xlib.keysymdef.%s' % group, G, locals(), [group]) + + #Extract names of just the keysyms. + keysyms = [n for n in dir(mod) if n.startswith('XK_')] + + #Copy the named keysyms into XK.__dict__ + for keysym in keysyms: + ## k = mod.__dict__[keysym]; assert k == int(k) #probably too much. + G[keysym] = mod.__dict__[keysym] + + #And get rid of the keysym module. + del mod + +def _load_keysyms_into_XK(mod): + '''keysym definition modules need no longer call Xlib.XK._load_keysyms_into_XK(). + You should remove any calls to that function from your keysym modules.''' + pass + +# Always import miscellany and latin1 keysyms +load_keysym_group('miscellany') +load_keysym_group('latin1') + + +def keysym_to_string(keysym): + '''Translate a keysym (16 bit number) into a python string. + + This will pass 0 to 0xff as well as XK_BackSpace, XK_Tab, XK_Clear, + XK_Return, XK_Pause, XK_Scroll_Lock, XK_Escape, XK_Delete. For other + values it returns None.''' + + # ISO latin 1, LSB is the code + if keysym & 0xff00 == 0: + return chr(keysym & 0xff) + + if keysym in [XK_BackSpace, XK_Tab, XK_Clear, XK_Return, + XK_Pause, XK_Scroll_Lock, XK_Escape, XK_Delete]: + return chr(keysym & 0xff) + + # We should be able to do these things quite automatically + # for latin2, latin3, etc, in Python 2.0 using the Unicode, + # but that will have to wait. + + return None diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/Xatom.py b/CLI/venv/lib/python3.12/site-packages/Xlib/Xatom.py new file mode 100644 index 0000000..6fedaaf --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/Xatom.py @@ -0,0 +1,90 @@ +# Xlib.Xatom -- Standard X atoms +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +PRIMARY = 1 +SECONDARY = 2 +ARC = 3 +ATOM = 4 +BITMAP = 5 +CARDINAL = 6 +COLORMAP = 7 +CURSOR = 8 +CUT_BUFFER0 = 9 +CUT_BUFFER1 = 10 +CUT_BUFFER2 = 11 +CUT_BUFFER3 = 12 +CUT_BUFFER4 = 13 +CUT_BUFFER5 = 14 +CUT_BUFFER6 = 15 +CUT_BUFFER7 = 16 +DRAWABLE = 17 +FONT = 18 +INTEGER = 19 +PIXMAP = 20 +POINT = 21 +RECTANGLE = 22 +RESOURCE_MANAGER = 23 +RGB_COLOR_MAP = 24 +RGB_BEST_MAP = 25 +RGB_BLUE_MAP = 26 +RGB_DEFAULT_MAP = 27 +RGB_GRAY_MAP = 28 +RGB_GREEN_MAP = 29 +RGB_RED_MAP = 30 +STRING = 31 +VISUALID = 32 +WINDOW = 33 +WM_COMMAND = 34 +WM_HINTS = 35 +WM_CLIENT_MACHINE = 36 +WM_ICON_NAME = 37 +WM_ICON_SIZE = 38 +WM_NAME = 39 +WM_NORMAL_HINTS = 40 +WM_SIZE_HINTS = 41 +WM_ZOOM_HINTS = 42 +MIN_SPACE = 43 +NORM_SPACE = 44 +MAX_SPACE = 45 +END_SPACE = 46 +SUPERSCRIPT_X = 47 +SUPERSCRIPT_Y = 48 +SUBSCRIPT_X = 49 +SUBSCRIPT_Y = 50 +UNDERLINE_POSITION = 51 +UNDERLINE_THICKNESS = 52 +STRIKEOUT_ASCENT = 53 +STRIKEOUT_DESCENT = 54 +ITALIC_ANGLE = 55 +X_HEIGHT = 56 +QUAD_WIDTH = 57 +WEIGHT = 58 +POINT_SIZE = 59 +RESOLUTION = 60 +COPYRIGHT = 61 +NOTICE = 62 +FONT_NAME = 63 +FAMILY_NAME = 64 +FULL_NAME = 65 +CAP_HEIGHT = 66 +WM_CLASS = 67 +WM_TRANSIENT_FOR = 68 +LAST_PREDEFINED = 68 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/Xcursorfont.py b/CLI/venv/lib/python3.12/site-packages/Xlib/Xcursorfont.py new file mode 100644 index 0000000..e7d0815 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/Xcursorfont.py @@ -0,0 +1,99 @@ +# Xlib.Xcursorfont -- standard cursors +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +num_glyphs = 154 +X_cursor = 0 +arrow = 2 +based_arrow_down = 4 +based_arrow_up = 6 +boat = 8 +bogosity = 10 +bottom_left_corner = 12 +bottom_right_corner = 14 +bottom_side = 16 +bottom_tee = 18 +box_spiral = 20 +center_ptr = 22 +circle = 24 +clock = 26 +coffee_mug = 28 +cross = 30 +cross_reverse = 32 +crosshair = 34 +diamond_cross = 36 +dot = 38 +dotbox = 40 +double_arrow = 42 +draft_large = 44 +draft_small = 46 +draped_box = 48 +exchange = 50 +fleur = 52 +gobbler = 54 +gumby = 56 +hand1 = 58 +hand2 = 60 +heart = 62 +icon = 64 +iron_cross = 66 +left_ptr = 68 +left_side = 70 +left_tee = 72 +leftbutton = 74 +ll_angle = 76 +lr_angle = 78 +man = 80 +middlebutton = 82 +mouse = 84 +pencil = 86 +pirate = 88 +plus = 90 +question_arrow = 92 +right_ptr = 94 +right_side = 96 +right_tee = 98 +rightbutton = 100 +rtl_logo = 102 +sailboat = 104 +sb_down_arrow = 106 +sb_h_double_arrow = 108 +sb_left_arrow = 110 +sb_right_arrow = 112 +sb_up_arrow = 114 +sb_v_double_arrow = 116 +shuttle = 118 +sizing = 120 +spider = 122 +spraycan = 124 +star = 126 +target = 128 +tcross = 130 +top_left_arrow = 132 +top_left_corner = 134 +top_right_corner = 136 +top_side = 138 +top_tee = 140 +trek = 142 +ul_angle = 144 +umbrella = 146 +ur_angle = 148 +watch = 150 +xterm = 152 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/Xutil.py b/CLI/venv/lib/python3.12/site-packages/Xlib/Xutil.py new file mode 100644 index 0000000..b691561 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/Xutil.py @@ -0,0 +1,81 @@ +# Xlib.Xutil -- ICCCM definitions and similar stuff +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +NoValue = 0x0000 +XValue = 0x0001 +YValue = 0x0002 +WidthValue = 0x0004 +HeightValue = 0x0008 +AllValues = 0x000F +XNegative = 0x0010 +YNegative = 0x0020 +USPosition = (1 << 0) +USSize = (1 << 1) +PPosition = (1 << 2) +PSize = (1 << 3) +PMinSize = (1 << 4) +PMaxSize = (1 << 5) +PResizeInc = (1 << 6) +PAspect = (1 << 7) +PBaseSize = (1 << 8) +PWinGravity = (1 << 9) +PAllHints = (PPosition|PSize|PMinSize|PMaxSize|PResizeInc|PAspect) +InputHint = (1 << 0) +StateHint = (1 << 1) +IconPixmapHint = (1 << 2) +IconWindowHint = (1 << 3) +IconPositionHint = (1 << 4) +IconMaskHint = (1 << 5) +WindowGroupHint = (1 << 6) +MessageHint = (1 << 7) +UrgencyHint = (1 << 8) +AllHints = (InputHint|StateHint|IconPixmapHint|IconWindowHint| + IconPositionHint|IconMaskHint|WindowGroupHint|MessageHint| + UrgencyHint) +WithdrawnState = 0 +NormalState = 1 +IconicState = 3 +DontCareState = 0 +ZoomState = 2 +InactiveState = 4 +RectangleOut = 0 +RectangleIn = 1 +RectanglePart = 2 +VisualNoMask = 0x0 +VisualIDMask = 0x1 +VisualScreenMask = 0x2 +VisualDepthMask = 0x4 +VisualClassMask = 0x8 +VisualRedMaskMask = 0x10 +VisualGreenMaskMask = 0x20 +VisualBlueMaskMask = 0x40 +VisualColormapSizeMask = 0x80 +VisualBitsPerRGBMask = 0x100 +VisualAllMask = 0x1FF +ReleaseByFreeingColormap = 1 +BitmapSuccess = 0 +BitmapOpenFailed = 1 +BitmapFileInvalid = 2 +BitmapNoMemory = 3 +XCSUCCESS = 0 +XCNOMEM = 1 +XCNOENT = 2 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__init__.py b/CLI/venv/lib/python3.12/site-packages/Xlib/__init__.py new file mode 100644 index 0000000..f164c43 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/__init__.py @@ -0,0 +1,39 @@ +# Xlib.__init__ -- glue for Xlib package +# +# Copyright (C) 2000-2002 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +__version__ = (0, 33) + +__version_extra__ = '' + +__version_string__ = '.'.join(map(str, __version__)) + __version_extra__ + +__all__ = [ + 'X', + 'XK', + 'Xatom', + 'Xcursorfont', + 'Xutil', + 'display', + 'error', + 'rdb', + # Explicitly exclude threaded, so that it isn't imported by + # from Xlib import * + ] diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/X.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/X.cpython-312.pyc new file mode 100644 index 0000000..bfd7cb7 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/X.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/XK.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/XK.cpython-312.pyc new file mode 100644 index 0000000..55bf42f Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/XK.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xatom.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xatom.cpython-312.pyc new file mode 100644 index 0000000..d1ac213 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xatom.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xcursorfont.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xcursorfont.cpython-312.pyc new file mode 100644 index 0000000..295ba2b Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xcursorfont.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xutil.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xutil.cpython-312.pyc new file mode 100644 index 0000000..339f729 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/Xutil.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..dc1e630 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/display.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/display.cpython-312.pyc new file mode 100644 index 0000000..78c6da8 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/display.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/error.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/error.cpython-312.pyc new file mode 100644 index 0000000..f0c02b0 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/error.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/rdb.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/rdb.cpython-312.pyc new file mode 100644 index 0000000..39fb251 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/rdb.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/threaded.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/threaded.cpython-312.pyc new file mode 100644 index 0000000..781df4c Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/threaded.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/xauth.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/xauth.cpython-312.pyc new file mode 100644 index 0000000..e3ebb5d Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/__pycache__/xauth.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/display.py b/CLI/venv/lib/python3.12/site-packages/Xlib/display.py new file mode 100644 index 0000000..bbda44b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/display.py @@ -0,0 +1,951 @@ +# Xlib.display -- high level display object +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +# Python modules +import types + +# Python 2/3 compatibility. +from six import create_unbound_method + +# Xlib modules +from . import error +from . import ext +from . import X + +# Xlib.protocol modules +from .protocol import display as protocol_display +from .protocol import request, event, rq + +# Xlib.xobjects modules +from .xobject import resource +from .xobject import drawable +from .xobject import fontable +from .xobject import colormap +from .xobject import cursor + +_resource_baseclasses = { + 'resource': resource.Resource, + 'drawable': drawable.Drawable, + 'window': drawable.Window, + 'pixmap': drawable.Pixmap, + 'fontable': fontable.Fontable, + 'font': fontable.Font, + 'gc': fontable.GC, + 'colormap': colormap.Colormap, + 'cursor': cursor.Cursor, + } + +_resource_hierarchy = { + 'resource': ('drawable', 'window', 'pixmap', + 'fontable', 'font', 'gc', + 'colormap', 'cursor'), + 'drawable': ('window', 'pixmap'), + 'fontable': ('font', 'gc') + } + +class _BaseDisplay(protocol_display.Display): + + # Implement a cache of atom names, used by Window objects when + # dealing with some ICCCM properties not defined in Xlib.Xatom + + def __init__(self, *args, **keys): + self.resource_classes = _resource_baseclasses.copy() + protocol_display.Display.__init__(self, *args, **keys) + self._atom_cache = {} + + def get_atom(self, atomname, only_if_exists=False): + if atomname in self._atom_cache: + return self._atom_cache[atomname] + + r = request.InternAtom(display = self, name = atomname, only_if_exists = only_if_exists) + + # don't cache NONE responses in case someone creates this later + if r.atom != X.NONE: + self._atom_cache[atomname] = r.atom + + return r.atom + + +class Display(object): + def __init__(self, display = None): + self.display = _BaseDisplay(display) + + # Create the keymap cache + self._keymap_codes = [()] * 256 + self._keymap_syms = {} + self._update_keymap(self.display.info.min_keycode, + (self.display.info.max_keycode + - self.display.info.min_keycode + 1)) + + # Translations for keysyms to strings. + self.keysym_translations = {} + + # Find all supported extensions + self.extensions = [] + self.class_extension_dicts = {} + self.display_extension_methods = {} + + # a dict that maps the event name to the code + # or, when it's an event with a subcode, to a tuple of (event,subcode) + # note this wraps the dict so you address it as + # extension_event.EXTENSION_EVENT_NAME rather than + # extension_event["EXTENSION_EVENT_NAME"] + self.extension_event = rq.DictWrapper({}) + + exts = self.list_extensions() + + # Go through all extension modules + for extname, modname in ext.__extensions__: + if extname in exts: + + # Import the module and fetch it + __import__('Xlib.ext.' + modname) + mod = getattr(ext, modname) + + info = self.query_extension(extname) + self.display.set_extension_major(extname, info.major_opcode) + + # Call initialiasation function + mod.init(self, info) + + self.extensions.append(extname) + + + # Finalize extensions by creating new classes + for class_name, dictionary in self.class_extension_dicts.items(): + origcls = self.display.resource_classes[class_name] + self.display.resource_classes[class_name] = type(origcls.__name__, + (origcls,), + dictionary) + + # Problem: we have already created some objects without the + # extensions: the screen roots and default colormaps. + # Fix that by reinstantiating them. + for screen in self.display.info.roots: + screen.root = self.display.resource_classes['window'](self.display, screen.root.id) + screen.default_colormap = self.display.resource_classes['colormap'](self.display, screen.default_colormap.id) + + + def get_display_name(self): + """Returns the name used to connect to the server, either + provided when creating the Display object, or fetched from the + environmental variable $DISPLAY.""" + return self.display.get_display_name() + + def fileno(self): + """Returns the file descriptor number of the underlying socket. + This method is provided to allow Display objects to be passed + select.select().""" + return self.display.fileno() + + def close(self): + """Close the display, freeing the resources that it holds.""" + self.display.close() + + def set_error_handler(self, handler): + """Set the default error handler which will be called for all + unhandled errors. handler should take two arguments as a normal + request error handler, but the second argument (the request) will + be None. See section Error Handling.""" + self.display.set_error_handler(handler) + + def flush(self): + """Flush the request queue, building and sending the queued + requests. This can be necessary in applications that never wait + for events, and in threaded applications.""" + self.display.flush() + + def sync(self): + """Flush the queue and wait until the server has processed all + the queued requests. Use this e.g. when it is important that + errors caused by a certain request is trapped.""" + # Do a light-weight replyrequest to sync. There must + # be a better way to do it... + self.get_pointer_control() + + def next_event(self): + """Return the next event. If there are no events queued, it will + block until the next event is fetched from the server.""" + return self.display.next_event() + + def pending_events(self): + """Return the number of events queued, i.e. the number of times + that Display.next_event() can be called without blocking.""" + return self.display.pending_events() + + def has_extension(self, extension): + """Check if both the server and the client library support the X + extension named extension.""" + return extension in self.extensions + + def create_resource_object(self, type, id): + """Create a resource object of type for the integer id. type + should be one of the following strings: + + resource + drawable + window + pixmap + fontable + font + gc + colormap + cursor + + This function can be used when a resource ID has been fetched + e.g. from an resource or a command line argument. Resource + objects should never be created by instantiating the appropriate + class directly, since any X extensions dynamically added by the + library will not be available. + """ + return self.display.resource_classes[type](self.display, id) + + # We need this to handle display extension methods + def __getattr__(self, attr): + try: + function = self.display_extension_methods[attr] + return types.MethodType(function, self) + except KeyError: + raise AttributeError(attr) + + ### + ### display information retrieval + ### + + def screen(self, sno = None): + if sno is None: + return self.display.info.roots[self.display.default_screen] + else: + return self.display.info.roots[sno] + + def screen_count(self): + """Return the total number of screens on the display.""" + return len(self.display.info.roots) + + def get_default_screen(self): + """Return the number of the default screen, extracted from the + display name.""" + return self.display.get_default_screen() + + ### + ### Extension module interface + ### + + def extension_add_method(self, object, name, function): + """extension_add_method(object, name, function) + + Add an X extension module method. OBJECT is the type of + object to add the function to, a string from this list: + + display + resource + drawable + window + pixmap + fontable + font + gc + colormap + cursor + + NAME is the name of the method, a string. FUNCTION is a + normal function whose first argument is a 'self'. + """ + + if object == 'display': + if hasattr(self, name): + raise AssertionError('attempting to replace display method: %s' % name) + + self.display_extension_methods[name] = function + + else: + class_list = (object, ) + _resource_hierarchy.get(object, ()) + for class_name in class_list: + cls = _resource_baseclasses[class_name] + if hasattr(cls, name): + raise AssertionError('attempting to replace %s method: %s' % (class_name, name)) + + method = create_unbound_method(function, cls) + + # Maybe should check extension overrides too + try: + self.class_extension_dicts[class_name][name] = method + except KeyError: + self.class_extension_dicts[class_name] = { name: method } + + def extension_add_event(self, code, evt, name = None): + """extension_add_event(code, evt, [name]) + + Add an extension event. CODE is the numeric code, and EVT is + the event class. EVT will be cloned, and the attribute _code + of the new event class will be set to CODE. + + If NAME is omitted, it will be set to the name of EVT. This + name is used to insert an entry in the DictWrapper + extension_event. + """ + + newevt = type(evt.__name__, evt.__bases__, + evt.__dict__.copy()) + newevt._code = code + + self.display.add_extension_event(code, newevt) + + if name is None: + name = evt.__name__ + + setattr(self.extension_event, name, code) + + def extension_add_subevent(self, code, subcode, evt, name = None): + """extension_add_subevent(code, evt, [name]) + + Add an extension subevent. CODE is the numeric code, subcode + is the sub-ID of this event that shares the code ID with other + sub-events and EVT is the event class. EVT will be cloned, and + the attribute _code of the new event class will be set to CODE. + + If NAME is omitted, it will be set to the name of EVT. This + name is used to insert an entry in the DictWrapper + extension_event. + """ + + newevt = type(evt.__name__, evt.__bases__, + evt.__dict__.copy()) + newevt._code = code + + self.display.add_extension_event(code, newevt, subcode) + + if name is None: + name = evt.__name__ + + # store subcodes as a tuple of (event code, subcode) in the + # extension dict maintained in the display object + setattr(self.extension_event, name, (code,subcode)) + + def extension_add_error(self, code, err): + """extension_add_error(code, err) + + Add an extension error. CODE is the numeric code, and ERR is + the error class. + """ + + self.display.add_extension_error(code, err) + + ### + ### keymap cache implementation + ### + + # The keycode->keysym map is stored in a list with 256 elements. + # Each element represents a keycode, and the tuple elements are + # the keysyms bound to the key. + + # The keysym->keycode map is stored in a mapping, where the keys + # are keysyms. The values are a sorted list of tuples with two + # elements each: (index, keycode) + # keycode is the code for a key to which this keysym is bound, and + # index is the keysyms index in the map for that keycode. + + def keycode_to_keysym(self, keycode, index): + """Convert a keycode to a keysym, looking in entry index. + Normally index 0 is unshifted, 1 is shifted, 2 is alt grid, and 3 + is shift+alt grid. If that key entry is not bound, X.NoSymbol is + returned.""" + try: + return self._keymap_codes[keycode][index] + except IndexError: + return X.NoSymbol + + def keysym_to_keycode(self, keysym): + """Look up the primary keycode that is bound to keysym. If + several keycodes are found, the one with the lowest index and + lowest code is returned. If keysym is not bound to any key, 0 is + returned.""" + try: + return self._keymap_syms[keysym][0][1] + except (KeyError, IndexError): + return 0 + + def keysym_to_keycodes(self, keysym): + """Look up all the keycodes that is bound to keysym. A list of + tuples (keycode, index) is returned, sorted primarily on the + lowest index and secondarily on the lowest keycode.""" + try: + # Copy the map list, reversing the arguments + return map(lambda x: (x[1], x[0]), self._keymap_syms[keysym]) + except KeyError: + return [] + + def refresh_keyboard_mapping(self, evt): + """This method should be called once when a MappingNotify event + is received, to update the keymap cache. evt should be the event + object.""" + if isinstance(evt, event.MappingNotify): + if evt.request == X.MappingKeyboard: + self._update_keymap(evt.first_keycode, evt.count) + else: + raise TypeError('expected a MappingNotify event') + + def _update_keymap(self, first_keycode, count): + """Internal function, called to refresh the keymap cache. + """ + + # Delete all sym->code maps for the changed codes + + lastcode = first_keycode + count + for keysym, codes in self._keymap_syms.items(): + i = 0 + while i < len(codes): + code = codes[i][1] + if code >= first_keycode and code < lastcode: + del codes[i] + else: + i = i + 1 + + # Get the new keyboard mapping + keysyms = self.get_keyboard_mapping(first_keycode, count) + + # Replace code->sym map with the new map + self._keymap_codes[first_keycode:lastcode] = keysyms + + # Update sym->code map + code = first_keycode + for syms in keysyms: + index = 0 + for sym in syms: + if sym != X.NoSymbol: + if sym in self._keymap_syms: + symcodes = self._keymap_syms[sym] + symcodes.append((index, code)) + symcodes.sort() + else: + self._keymap_syms[sym] = [(index, code)] + + index = index + 1 + code = code + 1 + + ### + ### client-internal keysym to string translations + ### + + def lookup_string(self, keysym): + """Return a string corresponding to KEYSYM, or None if no + reasonable translation is found. + """ + s = self.keysym_translations.get(keysym) + if s is not None: + return s + + import Xlib.XK + return Xlib.XK.keysym_to_string(keysym) + + def rebind_string(self, keysym, newstring): + """Change the translation of KEYSYM to NEWSTRING. + If NEWSTRING is None, remove old translation if any. + """ + if newstring is None: + try: + del self.keysym_translations[keysym] + except KeyError: + pass + else: + self.keysym_translations[keysym] = newstring + + + ### + ### X requests + ### + + def intern_atom(self, name, only_if_exists = False): + """Intern the string name, returning its atom number. If + only_if_exists is true and the atom does not already exist, it + will not be created and X.NONE is returned.""" + r = request.InternAtom(display = self.display, + name = name, + only_if_exists = only_if_exists) + return r.atom + + def get_atom(self, atom, only_if_exists = False): + """Alias for intern_atom, using internal cache""" + return self.display.get_atom(atom, only_if_exists) + + + def get_atom_name(self, atom): + """Look up the name of atom, returning it as a string. Will raise + BadAtom if atom does not exist.""" + r = request.GetAtomName(display = self.display, + atom = atom) + return r.name + + def get_selection_owner(self, selection): + """Return the window that owns selection (an atom), or X.NONE if + there is no owner for the selection. Can raise BadAtom.""" + r = request.GetSelectionOwner(display = self.display, + selection = selection) + return r.owner + + def send_event(self, destination, event, event_mask = 0, propagate = False, + onerror = None): + """Send a synthetic event to the window destination which can be + a window object, or X.PointerWindow or X.InputFocus. event is the + event object to send, instantiated from one of the classes in + protocol.events. See XSendEvent(3X11) for details. + + There is also a Window.send_event() method.""" + request.SendEvent(display = self.display, + onerror = onerror, + propagate = propagate, + destination = destination, + event_mask = event_mask, + event = event) + + def ungrab_pointer(self, time, onerror = None): + """Release a grabbed pointer and any queued events. See + XUngrabPointer(3X11).""" + request.UngrabPointer(display = self.display, + onerror = onerror, + time = time) + + def change_active_pointer_grab(self, event_mask, cursor, time, onerror = None): + """Change the dynamic parameters of a pointer grab. See + XChangeActivePointerGrab(3X11).""" + request.ChangeActivePointerGrab(display = self.display, + onerror = onerror, + cursor = cursor, + time = time, + event_mask = event_mask) + + def ungrab_keyboard(self, time, onerror = None): + """Ungrab a grabbed keyboard and any queued events. See + XUngrabKeyboard(3X11).""" + request.UngrabKeyboard(display = self.display, + onerror = onerror, + time = time) + + def allow_events(self, mode, time, onerror = None): + """Release some queued events. mode should be one of + X.AsyncPointer, X.SyncPointer, X.AsyncKeyboard, X.SyncKeyboard, + X.ReplayPointer, X.ReplayKeyboard, X.AsyncBoth, or X.SyncBoth. + time should be a timestamp or X.CurrentTime.""" + request.AllowEvents(display = self.display, + onerror = onerror, + mode = mode, + time = time) + + def grab_server(self, onerror = None): + """Disable processing of requests on all other client connections + until the server is ungrabbed. Server grabbing should be avoided + as much as possible.""" + request.GrabServer(display = self.display, + onerror = onerror) + + def ungrab_server(self, onerror = None): + """Release the server if it was previously grabbed by this client.""" + request.UngrabServer(display = self.display, + onerror = onerror) + + def warp_pointer(self, x, y, src_window = X.NONE, src_x = 0, src_y = 0, + src_width = 0, src_height = 0, onerror = None): + """Move the pointer relative its current position by the offsets + (x, y). However, if src_window is a window the pointer is only + moved if the specified rectangle in src_window contains it. If + src_width is 0 it will be replaced with the width of src_window - + src_x. src_height is treated in a similar way. + + To move the pointer to absolute coordinates, use Window.warp_pointer().""" + request.WarpPointer(display = self.display, + onerror = onerror, + src_window = src_window, + dst_window = X.NONE, + src_x = src_x, + src_y = src_y, + src_width = src_width, + src_height = src_height, + dst_x = x, + dst_y = y) + + def set_input_focus(self, focus, revert_to, time, onerror = None): + """Set input focus to focus, which should be a window, + X.PointerRoot or X.NONE. revert_to specifies where the focus + reverts to if the focused window becomes not visible, and should + be X.RevertToParent, RevertToPointerRoot, or RevertToNone. See + XSetInputFocus(3X11) for details. + + There is also a Window.set_input_focus().""" + request.SetInputFocus(display = self.display, + onerror = onerror, + revert_to = revert_to, + focus = focus, + time = time) + + def get_input_focus(self): + """Return an object with the following attributes: + + focus + The window which currently holds the input + focus, X.NONE or X.PointerRoot. + revert_to + Where the focus will revert, one of X.RevertToParent, + RevertToPointerRoot, or RevertToNone. """ + return request.GetInputFocus(display = self.display) + + def query_keymap(self): + """Return a bit vector for the logical state of the keyboard, + where each bit set to 1 indicates that the corresponding key is + currently pressed down. The vector is represented as a list of 32 + integers. List item N contains the bits for keys 8N to 8N + 7 + with the least significant bit in the byte representing key 8N.""" + r = request.QueryKeymap(display = self.display) + return r.map + + def open_font(self, name): + """Open the font identifed by the pattern name and return its + font object. If name does not match any font, None is returned.""" + fid = self.display.allocate_resource_id() + ec = error.CatchError(error.BadName) + + request.OpenFont(display = self.display, + onerror = ec, + fid = fid, + name = name) + self.sync() + + if ec.get_error(): + self.display.free_resource_id(fid) + return None + else: + cls = self.display.get_resource_class('font', fontable.Font) + return cls(self.display, fid, owner = 1) + + def list_fonts(self, pattern, max_names): + """Return a list of font names matching pattern. No more than + max_names will be returned.""" + r = request.ListFonts(display = self.display, + max_names = max_names, + pattern = pattern) + return r.fonts + + def list_fonts_with_info(self, pattern, max_names): + """Return a list of fonts matching pattern. No more than + max_names will be returned. Each list item represents one font + and has the following properties: + + name + The name of the font. + min_bounds + max_bounds + min_char_or_byte2 + max_char_or_byte2 + default_char + draw_direction + min_byte1 + max_byte1 + all_chars_exist + font_ascent + font_descent + replies_hint + See the description of XFontStruct in XGetFontProperty(3X11) + for details on these values. + properties + A list of properties. Each entry has two attributes: + + name + The atom identifying this property. + value + A 32-bit unsigned value. + """ + return request.ListFontsWithInfo(display = self.display, + max_names = max_names, + pattern = pattern) + + def set_font_path(self, path, onerror = None): + """Set the font path to path, which should be a list of strings. + If path is empty, the default font path of the server will be + restored.""" + request.SetFontPath(display = self.display, + onerror = onerror, + path = path) + + def get_font_path(self): + """Return the current font path as a list of strings.""" + r = request.GetFontPath(display = self.display) + return r.paths + + def query_extension(self, name): + """Ask the server if it supports the extension name. If it is + supported an object with the following attributes is returned: + + major_opcode + The major opcode that the requests of this extension uses. + first_event + The base event code if the extension have additional events, or 0. + first_error + The base error code if the extension have additional errors, or 0. + + If the extension is not supported, None is returned.""" + r = request.QueryExtension(display = self.display, + name = name) + if r.present: + return r + else: + return None + + def list_extensions(self): + """Return a list of all the extensions provided by the server.""" + r = request.ListExtensions(display = self.display) + return r.names + + def change_keyboard_mapping(self, first_keycode, keysyms, onerror = None): + """Modify the keyboard mapping, starting with first_keycode. + keysyms is a list of tuples of keysyms. keysyms[n][i] will be + assigned to keycode first_keycode+n at index i.""" + request.ChangeKeyboardMapping(display = self.display, + onerror = onerror, + first_keycode = first_keycode, + keysyms = keysyms) + + def get_keyboard_mapping(self, first_keycode, count): + """Return the current keyboard mapping as a list of tuples, + starting at first_keycount and no more than count.""" + r = request.GetKeyboardMapping(display = self.display, + first_keycode = first_keycode, + count = count) + return r.keysyms + + def change_keyboard_control(self, onerror = None, **keys): + """Change the parameters provided as keyword arguments: + + key_click_percent + The volume of key clicks between 0 (off) and 100 (load). + -1 will restore default setting. + bell_percent + The base volume of the bell, coded as above. + bell_pitch + The pitch of the bell in Hz, -1 restores the default. + bell_duration + The duration of the bell in milliseconds, -1 restores + the default. + led + + led_mode + led_mode should be X.LedModeOff or X.LedModeOn. If led is + provided, it should be a 32-bit mask listing the LEDs that + should change. If led is not provided, all LEDs are changed. + key + + auto_repeat_mode + auto_repeat_mode should be one of X.AutoRepeatModeOff, + X.AutoRepeatModeOn, or X.AutoRepeatModeDefault. If key is + provided, that key will be modified, otherwise the global + state for the entire keyboard will be modified.""" + request.ChangeKeyboardControl(display = self.display, + onerror = onerror, + attrs = keys) + + def get_keyboard_control(self): + """Return an object with the following attributes: + + global_auto_repeat + X.AutoRepeatModeOn or X.AutoRepeatModeOff. + + auto_repeats + A list of 32 integers. List item N contains the bits for keys + 8N to 8N + 7 with the least significant bit in the byte + representing key 8N. If a bit is on, autorepeat is enabled + for the corresponding key. + + led_mask + A 32-bit mask indicating which LEDs are on. + + key_click_percent + The volume of key click, from 0 to 100. + + bell_percent + + bell_pitch + + bell_duration + The volume, pitch and duration of the bell. """ + return request.GetKeyboardControl(display = self.display) + + def bell(self, percent = 0, onerror = None): + """Ring the bell at the volume percent which is relative the base + volume. See XBell(3X11).""" + request.Bell(display = self.display, + onerror = onerror, + percent = percent) + + def change_pointer_control(self, accel = None, threshold = None, onerror = None): + """To change the pointer acceleration, set accel to a tuple (num, + denum). The pointer will then move num/denum times the normal + speed if it moves beyond the threshold number of pixels at once. + To change the threshold, set it to the number of pixels. -1 + restores the default.""" + if accel is None: + do_accel = 0 + accel_num = 0 + accel_denum = 0 + else: + do_accel = 1 + accel_num, accel_denum = accel + + if threshold is None: + do_threshold = 0 + else: + do_threshold = 1 + + request.ChangePointerControl(display = self.display, + onerror = onerror, + do_accel = do_accel, + do_thresh = do_threshold, + accel_num = accel_num, + accel_denum = accel_denum, + threshold = threshold) + + def get_pointer_control(self): + """Return an object with the following attributes: + + accel_num + + accel_denom + The acceleration as numerator/denumerator. + + threshold + The number of pixels the pointer must move before the + acceleration kicks in.""" + return request.GetPointerControl(display = self.display) + + def set_screen_saver(self, timeout, interval, prefer_blank, allow_exposures, onerror = None): + """See XSetScreenSaver(3X11).""" + request.SetScreenSaver(display = self.display, + onerror = onerror, + timeout = timeout, + interval = interval, + prefer_blank = prefer_blank, + allow_exposures = allow_exposures) + + def get_screen_saver(self): + """Return an object with the attributes timeout, interval, + prefer_blanking, allow_exposures. See XGetScreenSaver(3X11) for + details.""" + return request.GetScreenSaver(display = self.display) + + def change_hosts(self, mode, host_family, host, onerror = None): + """mode is either X.HostInsert or X.HostDelete. host_family is + one of X.FamilyInternet, X.FamilyDECnet, X.FamilyChaos, + X.FamilyServerInterpreted or X.FamilyInternetV6. + + host is a list of bytes. For the Internet family, it should be the + four bytes of an IPv4 address.""" + request.ChangeHosts(display = self.display, + onerror = onerror, + mode = mode, + host_family = host_family, + host = host) + + def list_hosts(self): + """Return an object with the following attributes: + +mode + X.EnableAccess if the access control list is used, X.DisableAccess otherwise. +hosts + The hosts on the access list. Each entry has the following attributes: + + family + X.FamilyInternet, X.FamilyDECnet, X.FamilyChaos, X.FamilyServerInterpreted or X.FamilyInternetV6. + name + A list of byte values, the coding depends on family. For the Internet family, it is the 4 bytes of an IPv4 address. + +""" + return request.ListHosts(display = self.display) + + def set_access_control(self, mode, onerror = None): + """Enable use of access control lists at connection setup if mode + is X.EnableAccess, disable if it is X.DisableAccess.""" + request.SetAccessControl(display = self.display, + onerror = onerror, + mode = mode) + + def set_close_down_mode(self, mode, onerror = None): + """Control what will happen with the client's resources at + connection close. The default is X.DestroyAll, the other values + are X.RetainPermanent and X.RetainTemporary.""" + request.SetCloseDownMode(display = self.display, + onerror = onerror, + mode = mode) + + def force_screen_saver(self, mode, onerror = None): + """If mode is X.ScreenSaverActive the screen saver is activated. + If it is X.ScreenSaverReset, the screen saver is deactivated as + if device input had been received.""" + request.ForceScreenSaver(display = self.display, + onerror = onerror, + mode = mode) + + def set_pointer_mapping(self, map): + """Set the mapping of the pointer buttons. map is a list of + logical button numbers. map must be of the same length as the + list returned by Display.get_pointer_mapping(). + + map[n] sets the + logical number for the physical button n+1. Logical number 0 + disables the button. Two physical buttons cannot be mapped to the + same logical number. + + If one of the buttons to be altered are + logically in the down state, X.MappingBusy is returned and the + mapping is not changed. Otherwise the mapping is changed and + X.MappingSuccess is returned.""" + r = request.SetPointerMapping(display = self.display, + map = map) + return r.status + + def get_pointer_mapping(self): + """Return a list of the pointer button mappings. Entry N in the + list sets the logical button number for the physical button N+1.""" + r = request.GetPointerMapping(display = self.display) + return r.map + + def set_modifier_mapping(self, keycodes): + """Set the keycodes for the eight modifiers X.Shift, X.Lock, + X.Control, X.Mod1, X.Mod2, X.Mod3, X.Mod4 and X.Mod5. keycodes + should be a eight-element list where each entry is a list of the + keycodes that should be bound to that modifier. + + If any changed + key is logically in the down state, X.MappingBusy is returned and + the mapping is not changed. If the mapping violates some server + restriction, X.MappingFailed is returned. Otherwise the mapping + is changed and X.MappingSuccess is returned.""" + r = request.SetModifierMapping(display = self.display, + keycodes = keycodes) + return r.status + + def get_modifier_mapping(self): + """Return a list of eight lists, one for each modifier. The list + can be indexed using X.ShiftMapIndex, X.Mod1MapIndex, and so on. + The sublists list the keycodes bound to that modifier.""" + r = request.GetModifierMapping(display = self.display) + return r.keycodes + + def no_operation(self, onerror = None): + """Do nothing but send a request to the server.""" + request.NoOperation(display = self.display, + onerror = onerror) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/error.py b/CLI/venv/lib/python3.12/site-packages/Xlib/error.py new file mode 100644 index 0000000..2d27722 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/error.py @@ -0,0 +1,160 @@ +# Xlib.error -- basic error classes +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +# Xlib modules +from . import X + +# Xlib.protocol modules +from .protocol import rq + + +class DisplayError(Exception): + def __init__(self, display): + self.display = display + + def __str__(self): + return 'Display error "%s"' % self.display + +class DisplayNameError(DisplayError): + def __str__(self): + return 'Bad display name "%s"' % self.display + +class DisplayConnectionError(DisplayError): + def __init__(self, display, msg): + self.display = display + self.msg = msg + + def __str__(self): + return 'Can\'t connect to display "%s": %s' % (self.display, self.msg) + +class ConnectionClosedError(Exception): + def __init__(self, whom): + self.whom = whom + + def __str__(self): + return 'Display connection closed by %s' % self.whom + + +class XauthError(Exception): pass +class XNoAuthError(Exception): pass + +class ResourceIDError(Exception): pass + + +class XError(rq.GetAttrData, Exception): + _fields = rq.Struct( rq.Card8('type'), # Always 0 + rq.Card8('code'), + rq.Card16('sequence_number'), + rq.Card32('resource_id'), + rq.Card16('minor_opcode'), + rq.Card8('major_opcode'), + rq.Pad(21) + ) + + def __init__(self, display, data): + self._data, _ = self._fields.parse_binary(data, display, rawdict = True) + + def __str__(self): + s = [] + for f in ('code', 'resource_id', 'sequence_number', + 'major_opcode', 'minor_opcode'): + s.append('{0} = {1}'.format(f, self._data[f])) + + return '{0}: {1}'.format(self.__class__, ', '.join(s)) + +class XResourceError(XError): + _fields = rq.Struct( rq.Card8('type'), # Always 0 + rq.Card8('code'), + rq.Card16('sequence_number'), + rq.Resource('resource_id'), + rq.Card16('minor_opcode'), + rq.Card8('major_opcode'), + rq.Pad(21) + ) + +class BadRequest(XError): pass +class BadValue(XError): pass +class BadWindow(XResourceError): pass +class BadPixmap(XResourceError): pass +class BadAtom(XError): pass +class BadCursor(XResourceError): pass +class BadFont(XResourceError): pass +class BadMatch(XError): pass +class BadDrawable(XResourceError): pass +class BadAccess(XError): pass +class BadAlloc(XError): pass +class BadColor(XResourceError): pass +class BadGC(XResourceError): pass +class BadIDChoice(XResourceError): pass +class BadName(XError): pass +class BadLength(XError): pass +class BadImplementation(XError): pass + +xerror_class = { + X.BadRequest: BadRequest, + X.BadValue: BadValue, + X.BadWindow: BadWindow, + X.BadPixmap: BadPixmap, + X.BadAtom: BadAtom, + X.BadCursor: BadCursor, + X.BadFont: BadFont, + X.BadMatch: BadMatch, + X.BadDrawable: BadDrawable, + X.BadAccess: BadAccess, + X.BadAlloc: BadAlloc, + X.BadColor: BadColor, + X.BadGC: BadGC, + X.BadIDChoice: BadIDChoice, + X.BadName: BadName, + X.BadLength: BadLength, + X.BadImplementation: BadImplementation, + } + + +class CatchError(object): + def __init__(self, *errors): + self.error_types = errors + self.error = None + self.request = None + + def __call__(self, error, request): + if self.error_types: + for etype in self.error_types: + if isinstance(error, etype): + self.error = error + self.request = request + return 1 + + return 0 + else: + self.error = error + self.request = request + return 1 + + def get_error(self): + return self.error + + def get_request(self): + return self.request + + def reset(self): + self.error = None + self.request = None diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__init__.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__init__.py new file mode 100644 index 0000000..394c92c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__init__.py @@ -0,0 +1,46 @@ +# Xlib.ext.__init__ -- X extension modules +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +# __extensions__ is a list of tuples: (extname, extmod) +# extname is the name of the extension according to the X +# protocol. extmod is the name of the module in this package. + +__extensions__ = [ + # We load this first so other extensions can register generic event data + # structures. + ('Generic Event Extension', 'ge'), + ('XTEST', 'xtest'), + ('SHAPE', 'shape'), + ('XINERAMA', 'xinerama'), + ('RECORD', 'record'), + ('Composite', 'composite'), + ('RANDR', 'randr'), + ('XFIXES', 'xfixes'), + ('SECURITY', 'security'), + ('XInputExtension', 'xinput'), + ('NV-CONTROL', 'nvcontrol'), + ('DAMAGE', 'damage'), + ('DPMS', 'dpms'), + ('X-Resource', 'res'), + ('MIT-SCREEN-SAVER', 'screensaver'), + ] + +__all__ = map(lambda x: x[1], __extensions__) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..cd33468 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/composite.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/composite.cpython-312.pyc new file mode 100644 index 0000000..4239b14 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/composite.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/damage.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/damage.cpython-312.pyc new file mode 100644 index 0000000..d2a1d2a Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/damage.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/dpms.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/dpms.cpython-312.pyc new file mode 100644 index 0000000..0ff278d Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/dpms.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/ge.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/ge.cpython-312.pyc new file mode 100644 index 0000000..a7ba247 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/ge.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/nvcontrol.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/nvcontrol.cpython-312.pyc new file mode 100644 index 0000000..42b34fa Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/nvcontrol.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/randr.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/randr.cpython-312.pyc new file mode 100644 index 0000000..d12258f Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/randr.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/record.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/record.cpython-312.pyc new file mode 100644 index 0000000..49ed8d7 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/record.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/res.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/res.cpython-312.pyc new file mode 100644 index 0000000..cef269c Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/res.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/screensaver.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/screensaver.cpython-312.pyc new file mode 100644 index 0000000..d15440d Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/screensaver.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/security.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/security.cpython-312.pyc new file mode 100644 index 0000000..a8845ee Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/security.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/shape.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/shape.cpython-312.pyc new file mode 100644 index 0000000..9484fb9 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/shape.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xfixes.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xfixes.cpython-312.pyc new file mode 100644 index 0000000..908b25c Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xfixes.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xinerama.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xinerama.cpython-312.pyc new file mode 100644 index 0000000..5ee750d Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xinerama.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xinput.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xinput.cpython-312.pyc new file mode 100644 index 0000000..0634e4d Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xinput.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xtest.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xtest.cpython-312.pyc new file mode 100644 index 0000000..1132dff Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/__pycache__/xtest.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/composite.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/composite.py new file mode 100644 index 0000000..f956c62 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/composite.py @@ -0,0 +1,271 @@ +# $Id: xtest.py,v 1.1 2000/08/21 10:03:45 petli Exp $ +# +# Xlib.ext.composite -- Composite extension module +# +# Copyright (C) 2007 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +"""Composite extension, allowing windows to be rendered to off-screen +storage. + +For detailed description, see the protocol specification at +http://freedesktop.org/wiki/Software/CompositeExt + +By itself this extension is not very useful, it is intended to be used +together with the DAMAGE and XFIXES extensions. Typically you would +also need RENDER or glX or some similar method of creating fancy +graphics. +""" + +from Xlib.protocol import rq +from Xlib.xobject import drawable + +extname = 'Composite' + +RedirectAutomatic = 0 +RedirectManual = 1 + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card32('major_version'), + rq.Card32('minor_version') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + rq.Pad(16), + ) + +def query_version(self): + return QueryVersion( + display = self.display, + opcode = self.display.get_extension_major(extname), + major_version=0, + minor_version=4 + ) + + +class RedirectWindow(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + rq.Window('window'), + rq.Set('update', 1, (RedirectAutomatic, RedirectManual)), + rq.Pad(3), + ) + +def redirect_window(self, update, onerror = None): + """Redirect the hierarchy starting at this window to off-screen + storage. + """ + RedirectWindow(display = self.display, + onerror = onerror, + opcode = self.display.get_extension_major(extname), + window = self, + update = update, + ) + + +class RedirectSubwindows(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Window('window'), + rq.Set('update', 1, (RedirectAutomatic, RedirectManual)), + rq.Pad(3), + ) + +def redirect_subwindows(self, update, onerror = None): + """Redirect the hierarchies starting at all current and future + children to this window to off-screen storage. + """ + RedirectSubwindows(display = self.display, + onerror = onerror, + opcode = self.display.get_extension_major(extname), + window = self, + update = update, + ) + + +class UnredirectWindow(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + rq.Window('window'), + rq.Set('update', 1, (RedirectAutomatic, RedirectManual)), + rq.Pad(3), + ) + +def unredirect_window(self, update, onerror = None): + """Stop redirecting this window hierarchy. + """ + UnredirectWindow(display = self.display, + onerror = onerror, + opcode = self.display.get_extension_major(extname), + window = self, + update = update, + ) + + +class UnredirectSubindows(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + rq.Window('window'), + rq.Set('update', 1, (RedirectAutomatic, RedirectManual)), + rq.Pad(3), + ) + +def unredirect_subwindows(self, update, onerror = None): + """Stop redirecting the hierarchies of children to this window. + """ + RedirectWindow(display = self.display, + onerror = onerror, + opcode = self.display.get_extension_major(extname), + window = self, + update = update, + ) + + +class CreateRegionFromBorderClip(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(5), + rq.RequestLength(), + rq.Card32('region'), # FIXME: this should be a Region from XFIXES extension + rq.Window('window'), + ) + +def create_region_from_border_clip(self, onerror = None): + """Create a region of the border clip of the window, i.e. the area + that is not clipped by the parent and any sibling windows. + """ + + rid = self.display.allocate_resource_id() + CreateRegionFromBorderClip( + display = self.display, + onerror = onerror, + opcode = self.display.get_extension_major(extname), + region = rid, + window = self, + ) + + # FIXME: create Region object and return it + return rid + + +class NameWindowPixmap(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(6), + rq.RequestLength(), + rq.Window('window'), + rq.Pixmap('pixmap'), + ) + +def name_window_pixmap(self, onerror = None): + """Create a new pixmap that refers to the off-screen storage of + the window, including its border. + + This pixmap will remain allocated until freed whatever happens + with the window. However, the window will get a new off-screen + pixmap every time it is mapped or resized, so to keep track of the + contents you must listen for these events and get a new pixmap + after them. + """ + + pid = self.display.allocate_resource_id() + NameWindowPixmap(display = self.display, + onerror = onerror, + opcode = self.display.get_extension_major(extname), + window = self, + pixmap = pid, + ) + + cls = self.display.get_resource_class('pixmap', drawable.Pixmap) + return cls(self.display, pid, owner = 1) + +class GetOverlayWindow(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(7), + rq.RequestLength(), + rq.Window('window') + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('overlay_window'), + rq.Pad(20), + ) + +def get_overlay_window(self): + """Return the overlay window of the root window. + """ + + return GetOverlayWindow(display = self.display, + opcode = self.display.get_extension_major(extname), + window = self) + +def init(disp, info): + disp.extension_add_method('display', + 'composite_query_version', + query_version) + + disp.extension_add_method('window', + 'composite_redirect_window', + redirect_window) + + disp.extension_add_method('window', + 'composite_redirect_subwindows', + redirect_subwindows) + + disp.extension_add_method('window', + 'composite_unredirect_window', + unredirect_window) + + disp.extension_add_method('window', + 'composite_unredirect_subwindows', + unredirect_subwindows) + + disp.extension_add_method('window', + 'composite_create_region_from_border_clip', + create_region_from_border_clip) + + disp.extension_add_method('window', + 'composite_name_window_pixmap', + name_window_pixmap) + + disp.extension_add_method('window', + 'composite_get_overlay_window', + get_overlay_window) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/damage.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/damage.py new file mode 100644 index 0000000..614c808 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/damage.py @@ -0,0 +1,181 @@ +# Xlib.ext.damage -- DAMAGE extension module +# +# Copyright (C) 2018 Joseph Kogut +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +from Xlib import X +from Xlib.protocol import rq, structs +from Xlib.error import XError + +extname = 'DAMAGE' + +# Event codes # +DamageNotifyCode = 0 + +# Error codes # +BadDamageCode = 0 + +class BadDamageError(XError): + pass + +# DamageReportLevel options +DamageReportRawRectangles = 0 +DamageReportDeltaRectangles = 1 +DamageReportBoundingBox = 2 +DamageReportNonEmpty = 3 + +DamageReportLevel = ( + DamageReportRawRectangles, + DamageReportDeltaRectangles, + DamageReportBoundingBox, + DamageReportNonEmpty, +) + +DAMAGE = rq.Card32 + +# Methods + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + ) + + _reply = rq.Struct(rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + rq.Pad(16), + ) + +def query_version(self): + return QueryVersion(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + +class DamageCreate(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + DAMAGE('damage'), + rq.Drawable('drawable'), + rq.Set('level', 1, DamageReportLevel), + rq.Pad(3), + ) + +def damage_create(self, level): + did = self.display.allocate_resource_id() + DamageCreate(display=self.display, + opcode=self.display.get_extension_major(extname), + damage=did, + drawable=self.id, + level=level, + ) + return did + +class DamageDestroy(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + DAMAGE('damage') + ) + +def damage_destroy(self, damage): + DamageDestroy(display=self.display, + opcode=self.display.get_extension_major(extname), + damage=damage, + ) + + self.display.free_resource_id(damage) + +class DamageSubtract(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + DAMAGE('damage'), + rq.Card32('repair'), + rq.Card32('parts') + ) + +def damage_subtract(self, damage, repair=X.NONE, parts=X.NONE): + DamageSubtract(display=self.display, + opcode=self.display.get_extension_major(extname), + damage=damage, + repair=repair, + parts=parts) + +class DamageAdd(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + rq.Card32('repair'), + rq.Card32('parts'), + ) + +def damage_add(self, repair, parts): + DamageAdd(display=self.display, + opcode=self.display.get_extension_major(extname), + repair=repair, + parts=parts) + +# Events # + +class DamageNotify(rq.Event): + _code = None + _fields = rq.Struct( + rq.Card8('type'), + rq.Card8('level'), + rq.Card16('sequence_number'), + rq.Drawable('drawable'), + DAMAGE('damage'), + rq.Card32('timestamp'), + rq.Object('area', structs.Rectangle), + rq.Object('drawable_geometry', structs.Rectangle) + ) + +def init(disp, info): + disp.extension_add_method('display', + 'damage_query_version', + query_version) + + disp.extension_add_method('drawable', + 'damage_create', + damage_create) + + disp.extension_add_method('display', + 'damage_destroy', + damage_destroy) + + disp.extension_add_method('display', + 'damage_subtract', + damage_subtract) + + disp.extension_add_method('drawable', + 'damage_add', + damage_add) + + disp.extension_add_event(info.first_event + DamageNotifyCode, DamageNotify) + + disp.extension_add_error(code=BadDamageCode, err=BadDamageError) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/dpms.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/dpms.py new file mode 100644 index 0000000..5804169 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/dpms.py @@ -0,0 +1,232 @@ +# Xlib.ext.dpms -- X Display Power Management Signaling +# +# Copyright (C) 2020 Thiago Kenji Okada +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +''' +This extension provides X Protocol control over the VESA Display +Power Management Signaling (DPMS) characteristics of video boards +under control of the X Window System. + +Documentation: https://www.x.org/releases/X11R7.7/doc/xextproto/dpms.html +''' + +from Xlib.protocol import rq + +extname = 'DPMS' + + +# DPMS Extension Power Levels +# 0 DPMSModeOn In use +# 1 DPMSModeStandby Blanked, low power +# 2 DPMSModeSuspend Blanked, lower power +# 3 DPMSModeOff Shut off, awaiting activity +DPMSModeOn = 0 +DPMSModeStandby = 1 +DPMSModeSuspend = 2 +DPMSModeOff = 3 + +DPMSPowerLevel = ( + DPMSModeOn, + DPMSModeStandby, + DPMSModeSuspend, + DPMSModeOff, +) + + +class DPMSGetVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + rq.Pad(20), + ) + + +def get_version(self): + return DPMSGetVersion(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + + +class DPMSCapable(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Bool('capable'), + rq.Pad(23), + ) + + +def capable(self): + return DPMSCapable(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + + +class DPMSGetTimeouts(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('standby_timeout'), + rq.Card16('suspend_timeout'), + rq.Card16('off_timeout'), + rq.Pad(18), + ) + + +def get_timeouts(self): + return DPMSGetTimeouts(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + + +class DPMSSetTimeouts(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + rq.Card16('standby_timeout'), + rq.Card16('suspend_timeout'), + rq.Card16('off_timeout'), + rq.Pad(2) + ) + + +def set_timeouts(self, standby_timeout, suspend_timeout, off_timeout): + return DPMSSetTimeouts(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1, + standby_timeout=standby_timeout, + suspend_timeout=suspend_timeout, + off_timeout=off_timeout) + + +class DPMSEnable(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + ) + + +def enable(self): + return DPMSEnable(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + + +class DPMSDisable(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(5), + rq.RequestLength(), + ) + + +def disable(self): + return DPMSDisable(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + + +class DPMSForceLevel(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(6), + rq.RequestLength(), + rq.Resource('power_level', DPMSPowerLevel), + ) + + +def force_level(self, power_level): + return DPMSForceLevel(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1, + power_level=power_level) + + +class DPMSInfo(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(7), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('power_level'), + rq.Bool('state'), + rq.Pad(21), + ) + + +def info(self): + return DPMSInfo(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + + +def init(disp, _info): + disp.extension_add_method('display', 'dpms_get_version', get_version) + disp.extension_add_method('display', 'dpms_capable', capable) + disp.extension_add_method('display', 'dpms_get_timeouts', get_timeouts) + disp.extension_add_method('display', 'dpms_set_timeouts', set_timeouts) + disp.extension_add_method('display', 'dpms_enable', enable) + disp.extension_add_method('display', 'dpms_disable', disable) + disp.extension_add_method('display', 'dpms_force_level', force_level) + disp.extension_add_method('display', 'dpms_info', info) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/ge.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/ge.py new file mode 100644 index 0000000..85d2d01 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/ge.py @@ -0,0 +1,112 @@ +# Xlib.ext.ge -- Generic Event extension module +# +# Copyright (C) 2012 Outpost Embedded, LLC +# Forest Bond +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +''' +ge - Generic Event Extension +''' + +from Xlib.protocol import rq + +extname = 'Generic Event Extension' + + +GenericEventCode = 35 + + +class GEQueryVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + rq.Pad(16), + ) + + +def query_version(self): + return GEQueryVersion( + display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=0, + ) + + +class GenericEvent(rq.Event): + _code = GenericEventCode + _fields = rq.Struct( + rq.Card8('type'), + rq.Card8('extension'), + rq.Card16('sequence_number'), + rq.Card32('length'), + rq.Card16('evtype'), + # Some generic events make use of this space, but with + # others the data is simply discarded. In any case we + # don't need to explicitly pad this out as we are + # always given at least 32 bytes and we save + # everything after the first ten as the "data" field. + #rq.Pad(22), + ) + + def __init__(self, binarydata = None, display = None, **keys): + if binarydata: + data = binarydata[10:] + binarydata = binarydata[:10] + else: + data = '' + + rq.Event.__init__( + self, + binarydata=binarydata, + display=display, + **keys + ) + + if display: + ge_event_data = getattr(display, 'ge_event_data', None) + if ge_event_data: + estruct = ge_event_data.get((self.extension, self.evtype), None) + if estruct: + data, _ = estruct.parse_binary(data, display) + + self._data['data'] = data + + +def add_event_data(self, extension, evtype, estruct): + if not hasattr(self.display, 'ge_event_data'): + self.display.ge_event_data = {} + self.display.ge_event_data[(extension, evtype)] = estruct + + +def init(disp, info): + disp.extension_add_method('display', 'ge_query_version', query_version) + disp.extension_add_method('display', 'ge_add_event_data', add_event_data) + disp.extension_add_event(GenericEventCode, GenericEvent) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/nvcontrol.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/nvcontrol.py new file mode 100644 index 0000000..3b0bfb6 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/nvcontrol.py @@ -0,0 +1,5393 @@ +# Xlib.ext.nvcontrol -- NV-CONTROL extension module +# +# Copyright (C) 2019 Roberto Leinardi +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +"""NV-CONTROL - provide access to the NV-CONTROL extension information.""" + +from Xlib.protocol import rq + +extname = 'NV-CONTROL' + + +def query_target_count(self, target): + """Return the target count""" + reply = NVCtrlQueryTargetCountReplyRequest(display=self.display, + opcode=self.display.get_extension_major(extname), + target_type=target.type()) + return int(reply._data.get('count')) + + +def query_int_attribute(self, target, display_mask, attr): + """Return the value of an integer attribute""" + reply = NVCtrlQueryAttributeReplyRequest(display=self.display, + opcode=self.display.get_extension_major(extname), + target_id=target.id(), + target_type=target.type(), + display_mask=display_mask, + attr=attr) + if not reply._data.get('flags'): + return None + return int(reply._data.get('value')) + + +def set_int_attribute(self, target, display_mask, attr, value): + """Set the value of an integer attribute""" + reply = NVCtrlSetAttributeAndGetStatusReplyRequest(display=self.display, + opcode=self.display.get_extension_major(extname), + target_id=target.id(), + target_type=target.type(), + display_mask=display_mask, + attr=attr, + value=value) + return reply._data.get('flags') != 0 + + +def query_string_attribute(self, target, display_mask, attr): + """Return the value of a string attribute""" + reply = NVCtrlQueryStringAttributeReplyRequest(display=self.display, + opcode=self.display.get_extension_major(extname), + target_id=target.id(), + target_type=target.type(), + display_mask=display_mask, + attr=attr) + if not reply._data.get('flags'): + return None + return str(reply._data.get('string')).strip('\0') + + +def query_valid_attr_values(self, target, display_mask, attr): + """Return the value of an integer attribute""" + reply = NVCtrlQueryValidAttributeValuesReplyRequest(display=self.display, + opcode=self.display.get_extension_major(extname), + target_id=target.id(), + target_type=target.type(), + display_mask=display_mask, + attr=attr) + if not reply._data.get('flags'): + return None + return int(reply._data.get('min')), int(reply._data.get('max')) + + +def query_binary_data(self, target, display_mask, attr): + """Return binary data""" + reply = NVCtrlQueryBinaryDataReplyRequest(display=self.display, + opcode=self.display.get_extension_major(extname), + target_id=target.id(), + target_type=target.type(), + display_mask=display_mask, + attr=attr) + if not reply._data.get('flags'): + return None + return reply._data.get('data') + + +def get_coolers_used_by_gpu(self, target): + reply = NVCtrlQueryListCard32ReplyRequest(display=self.display, + opcode=self.display.get_extension_major(extname), + target_id=target.id(), + target_type=target.type(), + display_mask=0, + attr=NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU) + if not reply._data.get('flags'): + return None + fans = reply._data.get('list') + if len(fans) > 1: + return fans[1:] + else: + return None + + +def get_gpu_count(self): + """Return the number of GPU's present in the system.""" + return int(query_target_count(self, Gpu())) + + +def get_name(self, target): + """Return the GPU product name on which the specified X screen is running""" + return query_string_attribute(self, target, 0, NV_CTRL_STRING_PRODUCT_NAME) + + +def get_driver_version(self, target): + """Return the NVIDIA (kernel level) driver version for the specified screen or GPU""" + return query_string_attribute(self, target, 0, NV_CTRL_STRING_NVIDIA_DRIVER_VERSION) + + +def get_vbios_version(self, target): + """Return the version of the VBIOS for the specified screen or GPU""" + return query_string_attribute(self, target, 0, NV_CTRL_STRING_VBIOS_VERSION) + + +def get_gpu_uuid(self, target): + return query_string_attribute(self, target, 0, NV_CTRL_STRING_GPU_UUID) + + +def get_utilization_rates(self, target): + string = query_string_attribute(self, target, 0, NV_CTRL_STRING_GPU_UTILIZATION) + result = {} + if string is not None and string != '': + for line in string.split(','): + [key, value] = line.split('=')[:2] + result[key.strip()] = int(value) if value.isdigit() else value + return result + + +def get_performance_modes(self, target): + string = query_string_attribute(self, target, 0, NV_CTRL_STRING_PERFORMANCE_MODES) + result = [] + if string is not None and string != '': + for perf in string.split(';'): + perf_dict = {} + for line in perf.split(','): + [key, value] = line.split('=')[:2] + perf_dict[key.strip()] = int(value) if value.isdigit() else value + result.append(perf_dict) + return result + + +def get_clock_info(self, target): + string = query_string_attribute(self, target, 0, NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS) + result = {} + if string is not None and string != '': + for line in string.split(','): + [key, value] = line.split('=')[:2] + result[key.strip()] = int(value) if value.isdigit() else value + return result + + +def get_vram(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_VIDEO_RAM) + + +def get_irq(self, target): + """Return the interrupt request line used by the GPU driving the screen""" + return query_int_attribute(self, target, 0, NV_CTRL_IRQ) + + +def supports_framelock(self, target): + """Return whether the underlying GPU supports Frame Lock. + + All of the other frame lock attributes are only applicable if this returns True. + """ + return query_int_attribute(self, target, 0, NV_CTRL_FRAMELOCK) == 1 + + +def gvo_supported(self, screen): + """Return whether this X screen supports GVO + + If this screen does not support GVO output, then all other GVO attributes are unavailable. + """ + return query_int_attribute(self, screen, [], NV_CTRL_GVO_SUPPORTED) + + +def get_core_temp(self, target): + """Return the current core temperature of the GPU driving the X screen.""" + return query_int_attribute(self, target, 0, NV_CTRL_GPU_CORE_TEMPERATURE) + + +def get_core_threshold(self, target): + """Return the current GPU core slowdown threshold temperature. + + It reflects the temperature at which the GPU is throttled to prevent overheating. + """ + return query_int_attribute(self, target, 0, NV_CTRL_GPU_CORE_THRESHOLD) + + +def get_default_core_threshold(self, target): + """Return the default core threshold temperature.""" + return query_int_attribute(self, target, 0, NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD) + + +def get_max_core_threshold(self, target): + """Return the maximum core threshold temperature.""" + return query_int_attribute(self, target, 0, NV_CTRL_GPU_MAX_CORE_THRESHOLD) + + +def get_ambient_temp(self, target): + """Return the current temperature in the immediate neighbourhood of the GPU driving the X screen.""" + return query_int_attribute(self, target, 0, NV_CTRL_AMBIENT_TEMPERATURE) + + +def get_cuda_cores(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_GPU_CORES) + + +def get_memory_bus_width(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_GPU_MEMORY_BUS_WIDTH) + + +def get_total_dedicated_gpu_memory(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY) + + +def get_used_dedicated_gpu_memory(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_USED_DEDICATED_GPU_MEMORY) + + +def get_curr_pcie_link_width(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH) + + +def get_max_pcie_link_width(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH) + + +def get_curr_pcie_link_generation(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_GPU_PCIE_GENERATION) + + +def get_encoder_utilization(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_VIDEO_ENCODER_UTILIZATION) + + +def get_decoder_utilization(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_VIDEO_DECODER_UTILIZATION) + + +def get_current_performance_level(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL) + + +def get_gpu_nvclock_offset(self, target, perf_level): + return query_int_attribute(self, target, perf_level, NV_CTRL_GPU_NVCLOCK_OFFSET) + + +def set_gpu_nvclock_offset(self, target, perf_level, offset): + return set_int_attribute(self, target, perf_level, NV_CTRL_GPU_NVCLOCK_OFFSET, offset) + + +def set_gpu_nvclock_offset_all_levels(self, target, offset): + return set_int_attribute(self, target, 0, NV_CTRL_GPU_NVCLOCK_OFFSET_ALL_PERFORMANCE_LEVELS, offset) + + +def get_gpu_nvclock_offset_range(self, target, perf_level): + return query_valid_attr_values(self, target, perf_level, NV_CTRL_GPU_NVCLOCK_OFFSET) + + +def get_mem_transfer_rate_offset(self, target, perf_level): + return query_int_attribute(self, target, perf_level, NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET) + + +def set_mem_transfer_rate_offset(self, target, perf_level, offset): + return set_int_attribute(self, target, perf_level, NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET, offset) + + +def set_mem_transfer_rate_offset_all_levels(self, target, offset): + return set_int_attribute(self, target, 0, NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS, offset) + + +def get_mem_transfer_rate_offset_range(self, target, perf_level): + return query_valid_attr_values(self, target, perf_level, NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET) + + +def get_cooler_manual_control_enabled(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_GPU_COOLER_MANUAL_CONTROL) + + +def set_cooler_manual_control_enabled(self, target, enabled): + return set_int_attribute(self, target, 0, NV_CTRL_GPU_COOLER_MANUAL_CONTROL, 1 if enabled else 0) == 1 + + +def get_fan_duty(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL) + + +def set_fan_duty(self, cooler, speed): + return set_int_attribute(self, cooler, 0, NV_CTRL_THERMAL_COOLER_LEVEL, speed) + + +def get_fan_rpm(self, target): + return query_int_attribute(self, target, 0, NV_CTRL_THERMAL_COOLER_SPEED) + + +def get_max_displays(self, target): + """Return the maximum number of display devices that can be driven simultaneously on a GPU. + + Note that this does not indicate the maximum number of bits that can be set in + NV_CTRL_CONNECTED_DISPLAYS, because more display devices can be connected than are actively + in use. + """ + return query_int_attribute(self, target, 0, NV_CTRL_MAX_DISPLAYS) + + +def _displaystr2num(st): + """Return a display number from a string""" + num = None + for s, n in [('DFP-', 16), ('TV-', 8), ('CRT-', 0)]: + if st.startswith(s): + try: + curnum = int(st[len(s):]) + if 0 <= curnum <= 7: + num = n + curnum + break + except Exception: + pass + if num is not None: + return num + else: + raise ValueError('Unrecognised display name: ' + st) + + +def _displays2mask(displays): + """Return a display mask from an array of display numbers.""" + mask = 0 + for d in displays: + mask += (1 << _displaystr2num(d)) + return mask + + +def init(disp, info): + disp.extension_add_method('display', 'nvcontrol_query_target_count', query_target_count) + disp.extension_add_method('display', 'nvcontrol_query_int_attribute', query_int_attribute) + disp.extension_add_method('display', 'nvcontrol_query_string_attribute', query_string_attribute) + disp.extension_add_method('display', 'nvcontrol_query_valid_attr_values', query_valid_attr_values) + disp.extension_add_method('display', 'nvcontrol_query_binary_data', query_binary_data) + disp.extension_add_method('display', 'nvcontrol_get_gpu_count', get_gpu_count) + disp.extension_add_method('display', 'nvcontrol_get_vram', get_vram) + disp.extension_add_method('display', 'nvcontrol_get_irq', get_irq) + disp.extension_add_method('display', 'nvcontrol_supports_framelock', supports_framelock) + disp.extension_add_method('display', 'nvcontrol_get_core_temp', get_core_temp) + disp.extension_add_method('display', 'nvcontrol_get_core_threshold', get_core_threshold) + disp.extension_add_method('display', 'nvcontrol_get_default_core_threshold', get_default_core_threshold) + disp.extension_add_method('display', 'nvcontrol_get_max_core_threshold', get_max_core_threshold) + disp.extension_add_method('display', 'nvcontrol_get_ambient_temp', get_ambient_temp) + disp.extension_add_method('display', 'nvcontrol_get_cuda_cores', get_cuda_cores) + disp.extension_add_method('display', 'nvcontrol_get_memory_bus_width', get_memory_bus_width) + disp.extension_add_method('display', 'nvcontrol_get_total_dedicated_gpu_memory', get_total_dedicated_gpu_memory) + disp.extension_add_method('display', 'nvcontrol_get_used_dedicated_gpu_memory', get_used_dedicated_gpu_memory) + disp.extension_add_method('display', 'nvcontrol_get_curr_pcie_link_width', get_curr_pcie_link_width) + disp.extension_add_method('display', 'nvcontrol_get_max_pcie_link_width', get_max_pcie_link_width) + disp.extension_add_method('display', 'nvcontrol_get_curr_pcie_link_generation', get_curr_pcie_link_generation) + disp.extension_add_method('display', 'nvcontrol_get_encoder_utilization', get_encoder_utilization) + disp.extension_add_method('display', 'nvcontrol_get_decoder_utilization', get_decoder_utilization) + disp.extension_add_method('display', 'nvcontrol_get_current_performance_level', get_current_performance_level) + disp.extension_add_method('display', 'nvcontrol_get_gpu_nvclock_offset', get_gpu_nvclock_offset) + disp.extension_add_method('display', 'nvcontrol_set_gpu_nvclock_offset', set_gpu_nvclock_offset) + disp.extension_add_method('display', 'nvcontrol_set_gpu_nvclock_offset_all_levels', set_gpu_nvclock_offset_all_levels) + disp.extension_add_method('display', 'nvcontrol_get_mem_transfer_rate_offset', get_mem_transfer_rate_offset) + disp.extension_add_method('display', 'nvcontrol_set_mem_transfer_rate_offset', set_mem_transfer_rate_offset) + disp.extension_add_method('display', 'nvcontrol_set_mem_transfer_rate_offset_all_levels', set_mem_transfer_rate_offset_all_levels) + disp.extension_add_method('display', 'nvcontrol_get_cooler_manual_control_enabled', + get_cooler_manual_control_enabled) + disp.extension_add_method('display', 'nvcontrol_get_fan_duty', get_fan_duty) + disp.extension_add_method('display', 'nvcontrol_set_fan_duty', set_fan_duty) + disp.extension_add_method('display', 'nvcontrol_get_fan_rpm', get_fan_rpm) + disp.extension_add_method('display', 'nvcontrol_get_coolers_used_by_gpu', get_coolers_used_by_gpu) + disp.extension_add_method('display', 'nvcontrol_get_max_displays', get_max_displays) + disp.extension_add_method('display', 'nvcontrol_get_name', get_name) + disp.extension_add_method('display', 'nvcontrol_get_driver_version', get_driver_version) + disp.extension_add_method('display', 'nvcontrol_get_vbios_version', get_vbios_version) + disp.extension_add_method('display', 'nvcontrol_get_gpu_uuid', get_gpu_uuid) + disp.extension_add_method('display', 'nvcontrol_get_utilization_rates', get_utilization_rates) + disp.extension_add_method('display', 'nvcontrol_get_performance_modes', get_performance_modes) + disp.extension_add_method('display', 'nvcontrol_get_clock_info', get_clock_info) + disp.extension_add_method('display', 'nvcontrol_set_cooler_manual_control_enabled', + set_cooler_manual_control_enabled) + disp.extension_add_method('display', 'nvcontrol_get_gpu_nvclock_offset_range', + get_gpu_nvclock_offset_range) + disp.extension_add_method('display', 'nvcontrol_get_mem_transfer_rate_offset_range', + get_mem_transfer_rate_offset_range) + + +############################################################################ +# +# Attributes +# +# Some attributes may only be read; some may require a display_mask +# argument and others may be valid only for specific target types. +# This information is encoded in the "permission" comment after each +# attribute #define, and can be queried at run time with +# XNVCTRLQueryValidAttributeValues() and/or +# XNVCTRLQueryValidTargetAttributeValues() +# +# Key to Integer Attribute "Permissions": +# +# R: The attribute is readable (in general, all attributes will be +# readable) +# +# W: The attribute is writable (attributes may not be writable for +# various reasons: they represent static system information, they +# can only be changed by changing an XF86Config option, etc). +# +# D: The attribute requires the display mask argument. The +# attributes NV_CTRL_CONNECTED_DISPLAYS and NV_CTRL_ENABLED_DISPLAYS +# will be a bitmask of what display devices are connected and what +# display devices are enabled for use in X, respectively. Each bit +# in the bitmask represents a display device; it is these bits which +# should be used as the display_mask when dealing with attributes +# designated with "D" below. For attributes that do not require the +# display mask, the argument is ignored. +# +# Alternatively, NV-CONTROL versions 1.27 and greater allow these +# attributes to be accessed via display target types, in which case +# the display_mask is ignored. +# +# G: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GPU +# target type via XNVCTRLQueryTargetAttribute(). +# +# F: The attribute may be queried using an NV_CTRL_TARGET_TYPE_FRAMELOCK +# target type via XNVCTRLQueryTargetAttribute(). +# +# X: When Xinerama is enabled, this attribute is kept consistent across +# all Physical X Screens; assignment of this attribute will be +# broadcast by the NVIDIA X Driver to all X Screens. +# +# V: The attribute may be queried using an NV_CTRL_TARGET_TYPE_VCSC +# target type via XNVCTRLQueryTargetAttribute(). +# +# I: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GVI target type +# via XNVCTRLQueryTargetAttribute(). +# +# Q: The attribute is a 64-bit integer attribute; use the 64-bit versions +# of the appropriate query interfaces. +# +# C: The attribute may be queried using an NV_CTRL_TARGET_TYPE_COOLER target +# type via XNVCTRLQueryTargetAttribute(). +# +# S: The attribute may be queried using an NV_CTRL_TARGET_TYPE_THERMAL_SENSOR +# target type via XNVCTRLQueryTargetAttribute(). +# +# T: The attribute may be queried using an +# NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target type +# via XNVCTRLQueryTargetAttribute(). +# +# NOTE: Unless mentioned otherwise, all attributes may be queried using +# an NV_CTRL_TARGET_TYPE_X_SCREEN target type via +# XNVCTRLQueryTargetAttribute(). +# + + +############################################################################ + +# +# Integer attributes: +# +# Integer attributes can be queried through the XNVCTRLQueryAttribute() and +# XNVCTRLQueryTargetAttribute() function calls. +# +# Integer attributes can be set through the XNVCTRLSetAttribute() and +# XNVCTRLSetTargetAttribute() function calls. +# +# Unless otherwise noted, all integer attributes can be queried/set +# using an NV_CTRL_TARGET_TYPE_X_SCREEN target. Attributes that cannot +# take an NV_CTRL_TARGET_TYPE_X_SCREEN also cannot be queried/set through +# XNVCTRLQueryAttribute()/XNVCTRLSetAttribute() (Since these assume +# an X Screen target). +# + + +# +# NV_CTRL_FLATPANEL_SCALING - not supported +# + +NV_CTRL_FLATPANEL_SCALING = 2 # not supported +NV_CTRL_FLATPANEL_SCALING_DEFAULT = 0 # not supported +NV_CTRL_FLATPANEL_SCALING_NATIVE = 1 # not supported +NV_CTRL_FLATPANEL_SCALING_SCALED = 2 # not supported +NV_CTRL_FLATPANEL_SCALING_CENTERED = 3 # not supported +NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED = 4 # not supported + +# +# NV_CTRL_FLATPANEL_DITHERING - not supported +# +# NV_CTRL_DITHERING should be used instead. +# + +NV_CTRL_FLATPANEL_DITHERING = 3 # not supported +NV_CTRL_FLATPANEL_DITHERING_DEFAULT = 0 # not supported +NV_CTRL_FLATPANEL_DITHERING_ENABLED = 1 # not supported +NV_CTRL_FLATPANEL_DITHERING_DISABLED = 2 # not supported + +# +# NV_CTRL_DITHERING - the requested dithering configuration; +# possible values are: +# +# 0: auto (the driver will decide when to dither) +# 1: enabled (the driver will always dither when possible) +# 2: disabled (the driver will never dither) +# + +NV_CTRL_DITHERING = 3 # RWDG +NV_CTRL_DITHERING_AUTO = 0 +NV_CTRL_DITHERING_ENABLED = 1 +NV_CTRL_DITHERING_DISABLED = 2 + +# +# NV_CTRL_DIGITAL_VIBRANCE - sets the digital vibrance level for the +# specified display device. +# + +NV_CTRL_DIGITAL_VIBRANCE = 4 # RWDG + +# +# NV_CTRL_BUS_TYPE - returns the bus type through which the specified device +# is connected to the computer. +# When this attribute is queried on an X screen target, the bus type of the +# GPU driving the X screen is returned. +# + +NV_CTRL_BUS_TYPE = 5 # R--GI +NV_CTRL_BUS_TYPE_AGP = 0 +NV_CTRL_BUS_TYPE_PCI = 1 +NV_CTRL_BUS_TYPE_PCI_EXPRESS = 2 +NV_CTRL_BUS_TYPE_INTEGRATED = 3 + +# +# NV_CTRL_TOTAL_GPU_MEMORY - returns the total amount of memory available +# to the specified GPU (or the GPU driving the specified X +# screen). Note: if the GPU supports TurboCache(TM), the value +# reported may exceed the amount of video memory installed on the +# GPU. The value reported for integrated GPUs may likewise exceed +# the amount of dedicated system memory set aside by the system +# BIOS for use by the integrated GPU. +# + +NV_CTRL_TOTAL_GPU_MEMORY = 6 # R--G +NV_CTRL_VIDEO_RAM = NV_CTRL_TOTAL_GPU_MEMORY + +# +# NV_CTRL_IRQ - returns the interrupt request line used by the specified +# device. +# When this attribute is queried on an X screen target, the IRQ of the GPU +# driving the X screen is returned. +# + +NV_CTRL_IRQ = 7 # R--GI + +# +# NV_CTRL_OPERATING_SYSTEM - returns the operating system on which +# the X server is running. +# + +NV_CTRL_OPERATING_SYSTEM = 8 # R--G +NV_CTRL_OPERATING_SYSTEM_LINUX = 0 +NV_CTRL_OPERATING_SYSTEM_FREEBSD = 1 +NV_CTRL_OPERATING_SYSTEM_SUNOS = 2 + +# +# NV_CTRL_SYNC_TO_VBLANK - enables sync to vblank for OpenGL clients. +# This setting is only applied to OpenGL clients that are started +# after this setting is applied. +# + +NV_CTRL_SYNC_TO_VBLANK = 9 # RW-X +NV_CTRL_SYNC_TO_VBLANK_OFF = 0 +NV_CTRL_SYNC_TO_VBLANK_ON = 1 + +# +# NV_CTRL_LOG_ANISO - enables anisotropic filtering for OpenGL +# clients; on some NVIDIA hardware, this can only be enabled or +# disabled; on other hardware different levels of anisotropic +# filtering can be specified. This setting is only applied to OpenGL +# clients that are started after this setting is applied. +# + +NV_CTRL_LOG_ANISO = 10 # RW-X + +# +# NV_CTRL_FSAA_MODE - the FSAA setting for OpenGL clients; possible +# FSAA modes: +# +# NV_CTRL_FSAA_MODE_2x "2x Bilinear Multisampling" +# NV_CTRL_FSAA_MODE_2x_5t "2x Quincunx Multisampling" +# NV_CTRL_FSAA_MODE_15x15 "1.5 x 1.5 Supersampling" +# NV_CTRL_FSAA_MODE_2x2 "2 x 2 Supersampling" +# NV_CTRL_FSAA_MODE_4x "4x Bilinear Multisampling" +# NV_CTRL_FSAA_MODE_4x_9t "4x Gaussian Multisampling" +# NV_CTRL_FSAA_MODE_8x "2x Bilinear Multisampling by 4x Supersampling" +# NV_CTRL_FSAA_MODE_16x "4x Bilinear Multisampling by 4x Supersampling" +# NV_CTRL_FSAA_MODE_8xS "4x Multisampling by 2x Supersampling" +# +# This setting is only applied to OpenGL clients that are started +# after this setting is applied. +# + +NV_CTRL_FSAA_MODE = 11 # RW-X +NV_CTRL_FSAA_MODE_NONE = 0 +NV_CTRL_FSAA_MODE_2x = 1 +NV_CTRL_FSAA_MODE_2x_5t = 2 +NV_CTRL_FSAA_MODE_15x15 = 3 +NV_CTRL_FSAA_MODE_2x2 = 4 +NV_CTRL_FSAA_MODE_4x = 5 +NV_CTRL_FSAA_MODE_4x_9t = 6 +NV_CTRL_FSAA_MODE_8x = 7 +NV_CTRL_FSAA_MODE_16x = 8 +NV_CTRL_FSAA_MODE_8xS = 9 +NV_CTRL_FSAA_MODE_8xQ = 10 +NV_CTRL_FSAA_MODE_16xS = 11 +NV_CTRL_FSAA_MODE_16xQ = 12 +NV_CTRL_FSAA_MODE_32xS = 13 +NV_CTRL_FSAA_MODE_32x = 14 +NV_CTRL_FSAA_MODE_64xS = 15 +NV_CTRL_FSAA_MODE_MAX = NV_CTRL_FSAA_MODE_64xS + +# +# NV_CTRL_UBB - returns whether UBB is enabled for the specified X +# screen. +# + +NV_CTRL_UBB = 13 # R-- +NV_CTRL_UBB_OFF = 0 +NV_CTRL_UBB_ON = 1 + +# +# NV_CTRL_OVERLAY - returns whether the RGB overlay is enabled for +# the specified X screen. +# + +NV_CTRL_OVERLAY = 14 # R-- +NV_CTRL_OVERLAY_OFF = 0 +NV_CTRL_OVERLAY_ON = 1 + +# +# NV_CTRL_STEREO - returns whether stereo (and what type) is enabled +# for the specified X screen. +# + +NV_CTRL_STEREO = 16 # R-- +NV_CTRL_STEREO_OFF = 0 +NV_CTRL_STEREO_DDC = 1 +NV_CTRL_STEREO_BLUELINE = 2 +NV_CTRL_STEREO_DIN = 3 +NV_CTRL_STEREO_PASSIVE_EYE_PER_DPY = 4 +NV_CTRL_STEREO_VERTICAL_INTERLACED = 5 +NV_CTRL_STEREO_COLOR_INTERLACED = 6 +NV_CTRL_STEREO_HORIZONTAL_INTERLACED = 7 +NV_CTRL_STEREO_CHECKERBOARD_PATTERN = 8 +NV_CTRL_STEREO_INVERSE_CHECKERBOARD_PATTERN = 9 +NV_CTRL_STEREO_3D_VISION = 10 +NV_CTRL_STEREO_3D_VISION_PRO = 11 +NV_CTRL_STEREO_HDMI_3D = 12 +NV_CTRL_STEREO_TRIDELITY_SL = 13 +NV_CTRL_STEREO_INBAND_STEREO_SIGNALING = 14 +NV_CTRL_STEREO_MAX = NV_CTRL_STEREO_INBAND_STEREO_SIGNALING + +# +# NV_CTRL_EMULATE - not supported +# + +NV_CTRL_EMULATE = 17 # not supported +NV_CTRL_EMULATE_NONE = 0 # not supported + +# +# NV_CTRL_TWINVIEW - returns whether TwinView is enabled for the +# specified X screen. +# + +NV_CTRL_TWINVIEW = 18 # R-- +NV_CTRL_TWINVIEW_NOT_ENABLED = 0 +NV_CTRL_TWINVIEW_ENABLED = 1 + +# +# NV_CTRL_CONNECTED_DISPLAYS - deprecated +# +# NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU and +# NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN should be used instead. +# + +NV_CTRL_CONNECTED_DISPLAYS = 19 # deprecated + +# +# NV_CTRL_ENABLED_DISPLAYS - Event that notifies when one or more display +# devices are enabled or disabled on a GPU and/or X screen. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# +# Note: Querying this value has been deprecated. +# NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU, +# NV_CTRL_DISPLAY_ENABLED, and +# NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN should be used +# instead to obtain the list of enabled displays. +# + +NV_CTRL_ENABLED_DISPLAYS = 20 # ---G + +############################################################################ +# +# Integer attributes specific to configuring Frame Lock on boards that +# support it. +# + + +# +# NV_CTRL_FRAMELOCK - returns whether the underlying GPU supports +# Frame Lock. All of the other frame lock attributes are only +# applicable if NV_CTRL_FRAMELOCK is _SUPPORTED. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_FRAMELOCK = 21 # R--G +NV_CTRL_FRAMELOCK_NOT_SUPPORTED = 0 +NV_CTRL_FRAMELOCK_SUPPORTED = 1 + +# +# NV_CTRL_FRAMELOCK_MASTER - deprecated +# +# NV_CTRL_FRAMELOCK_DISPLAY_CONFIG should be used instead. +# + +NV_CTRL_FRAMELOCK_MASTER = 22 # deprecated +NV_CTRL_FRAMELOCK_MASTER_FALSE = 0 # deprecated +NV_CTRL_FRAMELOCK_MASTER_TRUE = 1 # deprecated + +# +# NV_CTRL_FRAMELOCK_POLARITY - sync either to the rising edge of the +# frame lock pulse, the falling edge of the frame lock pulse or both. +# +# On Quadro Sync II, this attribute is ignored when +# NV_CTRL_USE_HOUSE_SYNC is OUTPUT. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_POLARITY = 23 # RW-F +NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE = 0x1 +NV_CTRL_FRAMELOCK_POLARITY_FALLING_EDGE = 0x2 +NV_CTRL_FRAMELOCK_POLARITY_BOTH_EDGES = 0x3 + +# +# NV_CTRL_FRAMELOCK_SYNC_DELAY - delay between the frame lock pulse +# and the GPU sync. This value must be multiplied by +# NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION to determine the sync delay in +# nanoseconds. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# +# USAGE NOTE: NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX and +# NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR are deprecated. +# The Sync Delay _MAX and _FACTOR are different for different +# Quadro Sync products and so, to be correct, the valid values for +# NV_CTRL_FRAMELOCK_SYNC_DELAY must be queried to get the range +# of acceptable sync delay values, and +# NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION must be queried to +# obtain the correct factor. +# + +NV_CTRL_FRAMELOCK_SYNC_DELAY = 24 # RW-F +NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX = 2047 # deprecated +NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR = 7.81 # deprecated + +# +# NV_CTRL_FRAMELOCK_SYNC_INTERVAL - how many house sync pulses +# between the frame lock sync generation (0 == sync every house sync); +# this only applies to the master when receiving house sync. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_SYNC_INTERVAL = 25 # RW-F + +# +# NV_CTRL_FRAMELOCK_PORT0_STATUS - status of the rj45 port0. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_PORT0_STATUS = 26 # R--F +NV_CTRL_FRAMELOCK_PORT0_STATUS_INPUT = 0 +NV_CTRL_FRAMELOCK_PORT0_STATUS_OUTPUT = 1 + +# +# NV_CTRL_FRAMELOCK_PORT1_STATUS - status of the rj45 port1. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_PORT1_STATUS = 27 # R--F +NV_CTRL_FRAMELOCK_PORT1_STATUS_INPUT = 0 +NV_CTRL_FRAMELOCK_PORT1_STATUS_OUTPUT = 1 + +# +# NV_CTRL_FRAMELOCK_HOUSE_STATUS - returns whether or not the house +# sync input signal was detected on the BNC connector of the frame lock +# board. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_HOUSE_STATUS = 28 # R--F +NV_CTRL_FRAMELOCK_HOUSE_STATUS_NOT_DETECTED = 0 +NV_CTRL_FRAMELOCK_HOUSE_STATUS_DETECTED = 1 + +# +# NV_CTRL_FRAMELOCK_SYNC - enable/disable the syncing of display +# devices to the frame lock pulse as specified by previous calls to +# NV_CTRL_FRAMELOCK_DISPLAY_CONFIG. +# +# This attribute can only be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN. +# + +NV_CTRL_FRAMELOCK_SYNC = 29 # RW-G +NV_CTRL_FRAMELOCK_SYNC_DISABLE = 0 +NV_CTRL_FRAMELOCK_SYNC_ENABLE = 1 + +# +# NV_CTRL_FRAMELOCK_SYNC_READY - reports whether a frame lock +# board is receiving sync (regardless of whether or not any display +# devices are using the sync). +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_SYNC_READY = 30 # R--F +NV_CTRL_FRAMELOCK_SYNC_READY_FALSE = 0 +NV_CTRL_FRAMELOCK_SYNC_READY_TRUE = 1 + +# +# NV_CTRL_FRAMELOCK_STEREO_SYNC - this indicates that the GPU stereo +# signal is in sync with the frame lock stereo signal. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_STEREO_SYNC = 31 # R--G +NV_CTRL_FRAMELOCK_STEREO_SYNC_FALSE = 0 +NV_CTRL_FRAMELOCK_STEREO_SYNC_TRUE = 1 + +# +# NV_CTRL_FRAMELOCK_TEST_SIGNAL - to test the connections in the sync +# group, tell the master to enable a test signal, then query port[01] +# status and sync_ready on all slaves. When done, tell the master to +# disable the test signal. Test signal should only be manipulated +# while NV_CTRL_FRAMELOCK_SYNC is enabled. +# +# The TEST_SIGNAL is also used to reset the Universal Frame Count (as +# returned by the glXQueryFrameCountNV() function in the +# GLX_NV_swap_group extension). Note: for best accuracy of the +# Universal Frame Count, it is recommended to toggle the TEST_SIGNAL +# on and off after enabling frame lock. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_FRAMELOCK_TEST_SIGNAL = 32 # RW-G +NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE = 0 +NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE = 1 + +# +# NV_CTRL_FRAMELOCK_ETHERNET_DETECTED - The frame lock boards are +# cabled together using regular cat5 cable, connecting to rj45 ports +# on the backplane of the card. There is some concern that users may +# think these are ethernet ports and connect them to a +# router/hub/etc. The hardware can detect this and will shut off to +# prevent damage (either to itself or to the router). +# NV_CTRL_FRAMELOCK_ETHERNET_DETECTED may be called to find out if +# ethernet is connected to one of the rj45 ports. An appropriate +# error message should then be displayed. The _PORT0 and _PORT1 +# values may be or'ed together. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_ETHERNET_DETECTED = 33 # R--F +NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_NONE = 0 +NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT0 = 0x1 +NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT1 = 0x2 + +# +# NV_CTRL_FRAMELOCK_VIDEO_MODE - get/set what video mode is used +# to interperate the house sync signal. This should only be set +# on the master. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_VIDEO_MODE = 34 # RW-F +NV_CTRL_FRAMELOCK_VIDEO_MODE_NONE = 0 +NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL = 1 +NV_CTRL_FRAMELOCK_VIDEO_MODE_NTSCPALSECAM = 2 +NV_CTRL_FRAMELOCK_VIDEO_MODE_HDTV = 3 + +# +# During FRAMELOCK bring-up, the above values were redefined to +# these: +# + +NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO = 0 +NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_BI_LEVEL = 2 +NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_TRI_LEVEL = 3 + +# +# NV_CTRL_FRAMELOCK_SYNC_RATE - this is the refresh rate that the +# frame lock board is sending to the GPU, in milliHz. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_FRAMELOCK_SYNC_RATE = 35 # R--F + +############################################################################ + +# +# NV_CTRL_FORCE_GENERIC_CPU - not supported +# + +NV_CTRL_FORCE_GENERIC_CPU = 37 # not supported +NV_CTRL_FORCE_GENERIC_CPU_DISABLE = 0 # not supported +NV_CTRL_FORCE_GENERIC_CPU_ENABLE = 1 # not supported + +# +# NV_CTRL_OPENGL_AA_LINE_GAMMA - for OpenGL clients, allow +# Gamma-corrected antialiased lines to consider variances in the +# color display capabilities of output devices when rendering smooth +# lines. Only available on recent Quadro GPUs. This setting is only +# applied to OpenGL clients that are started after this setting is +# applied. +# + +NV_CTRL_OPENGL_AA_LINE_GAMMA = 38 # RW-X +NV_CTRL_OPENGL_AA_LINE_GAMMA_DISABLE = 0 +NV_CTRL_OPENGL_AA_LINE_GAMMA_ENABLE = 1 + +# +# NV_CTRL_FRAMELOCK_TIMING - this is TRUE when the gpu is both receiving +# and locked to an input timing signal. Timing information may come from +# the following places: Another frame lock device that is set to master, +# the house sync signal, or the GPU's internal timing from a display +# device. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_FRAMELOCK_TIMING = 39 # R--G +NV_CTRL_FRAMELOCK_TIMING_FALSE = 0 +NV_CTRL_FRAMELOCK_TIMING_TRUE = 1 + +# +# NV_CTRL_FLIPPING_ALLOWED - when TRUE, OpenGL will swap by flipping +# when possible; when FALSE, OpenGL will always swap by blitting. +# + +NV_CTRL_FLIPPING_ALLOWED = 40 # RW-X +NV_CTRL_FLIPPING_ALLOWED_FALSE = 0 +NV_CTRL_FLIPPING_ALLOWED_TRUE = 1 + +# +# NV_CTRL_ARCHITECTURE - returns the architecture on which the X server is +# running. +# + +NV_CTRL_ARCHITECTURE = 41 # R-- +NV_CTRL_ARCHITECTURE_X86 = 0 +NV_CTRL_ARCHITECTURE_X86_64 = 1 +NV_CTRL_ARCHITECTURE_IA64 = 2 +NV_CTRL_ARCHITECTURE_ARM = 3 +NV_CTRL_ARCHITECTURE_AARCH64 = 4 +NV_CTRL_ARCHITECTURE_PPC64LE = 5 + +# +# NV_CTRL_TEXTURE_CLAMPING - texture clamping mode in OpenGL. By +# default, _SPEC is used, which forces OpenGL texture clamping to +# conform with the OpenGL specification. _EDGE forces NVIDIA's +# OpenGL implementation to remap GL_CLAMP to GL_CLAMP_TO_EDGE, +# which is not strictly conformant, but some applications rely on +# the non-conformant behavior. +# + +NV_CTRL_TEXTURE_CLAMPING = 42 # RW-X +NV_CTRL_TEXTURE_CLAMPING_EDGE = 0 +NV_CTRL_TEXTURE_CLAMPING_SPEC = 1 + +# +# The NV_CTRL_CURSOR_SHADOW - not supported +# +# use an ARGB cursor instead. +# + +NV_CTRL_CURSOR_SHADOW = 43 # not supported +NV_CTRL_CURSOR_SHADOW_DISABLE = 0 # not supported +NV_CTRL_CURSOR_SHADOW_ENABLE = 1 # not supported + +NV_CTRL_CURSOR_SHADOW_ALPHA = 44 # not supported +NV_CTRL_CURSOR_SHADOW_RED = 45 # not supported +NV_CTRL_CURSOR_SHADOW_GREEN = 46 # not supported +NV_CTRL_CURSOR_SHADOW_BLUE = 47 # not supported + +NV_CTRL_CURSOR_SHADOW_X_OFFSET = 48 # not supported +NV_CTRL_CURSOR_SHADOW_Y_OFFSET = 49 # not supported + +# +# When Application Control for FSAA is enabled, then what the +# application requests is used, and NV_CTRL_FSAA_MODE is ignored. If +# this is disabled, then any application setting is overridden with +# NV_CTRL_FSAA_MODE +# + +NV_CTRL_FSAA_APPLICATION_CONTROLLED = 50 # RW-X +NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED = 1 +NV_CTRL_FSAA_APPLICATION_CONTROLLED_DISABLED = 0 + +# +# When Application Control for LogAniso is enabled, then what the +# application requests is used, and NV_CTRL_LOG_ANISO is ignored. If +# this is disabled, then any application setting is overridden with +# NV_CTRL_LOG_ANISO +# + +NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED = 51 # RW-X +NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_ENABLED = 1 +NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_DISABLED = 0 + +# +# IMAGE_SHARPENING adjusts the sharpness of the display's image +# quality by amplifying high frequency content. Valid values will +# normally be in the range [0,32). Only available on GeForceFX or +# newer. +# + +NV_CTRL_IMAGE_SHARPENING = 52 # RWDG + +# +# NV_CTRL_TV_OVERSCAN - not supported +# + +NV_CTRL_TV_OVERSCAN = 53 # not supported + +# +# NV_CTRL_TV_FLICKER_FILTER - not supported +# + +NV_CTRL_TV_FLICKER_FILTER = 54 # not supported + +# +# NV_CTRL_TV_BRIGHTNESS - not supported +# + +NV_CTRL_TV_BRIGHTNESS = 55 # not supported + +# +# NV_CTRL_TV_HUE - not supported +# + +NV_CTRL_TV_HUE = 56 # not supported + +# +# NV_CTRL_TV_CONTRAST - not suppoerted +# + +NV_CTRL_TV_CONTRAST = 57 # not supported + +# +# NV_CTRL_TV_SATURATION - not supported +# + +NV_CTRL_TV_SATURATION = 58 # not supported + +# +# NV_CTRL_TV_RESET_SETTINGS - not supported +# + +NV_CTRL_TV_RESET_SETTINGS = 59 # not supported + +# +# NV_CTRL_GPU_CORE_TEMPERATURE reports the current core temperature +# of the GPU driving the X screen. +# + +NV_CTRL_GPU_CORE_TEMPERATURE = 60 # R--G + +# +# NV_CTRL_GPU_CORE_THRESHOLD reports the current GPU core slowdown +# threshold temperature, NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD and +# NV_CTRL_GPU_MAX_CORE_THRESHOLD report the default and MAX core +# slowdown threshold temperatures. +# +# NV_CTRL_GPU_CORE_THRESHOLD reflects the temperature at which the +# GPU is throttled to prevent overheating. +# + +NV_CTRL_GPU_CORE_THRESHOLD = 61 # R--G +NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD = 62 # R--G +NV_CTRL_GPU_MAX_CORE_THRESHOLD = 63 # R--G + +# +# NV_CTRL_AMBIENT_TEMPERATURE reports the current temperature in the +# immediate neighbourhood of the GPU driving the X screen. +# + +NV_CTRL_AMBIENT_TEMPERATURE = 64 # R--G + +# +# NV_CTRL_PBUFFER_SCANOUT_SUPPORTED - returns whether this X screen +# supports scanout of FP pbuffers; +# +# if this screen does not support PBUFFER_SCANOUT, then all other +# PBUFFER_SCANOUT attributes are unavailable. +# +# PBUFFER_SCANOUT is supported if and only if: +# - Twinview is configured with clone mode. The secondary screen is used to +# scanout the pbuffer. +# - The desktop is running in with 16 bits per pixel. +# +NV_CTRL_PBUFFER_SCANOUT_SUPPORTED = 65 # not supported +NV_CTRL_PBUFFER_SCANOUT_FALSE = 0 +NV_CTRL_PBUFFER_SCANOUT_TRUE = 1 + +# +# NV_CTRL_PBUFFER_SCANOUT_XID indicates the XID of the pbuffer used for +# scanout. +# +NV_CTRL_PBUFFER_SCANOUT_XID = 66 # not supported + +############################################################################ +# +# The NV_CTRL_GVO_* integer attributes are used to configure GVO +# (Graphics to Video Out). This functionality is available, for +# example, on the Quadro SDI Output card. +# +# The following is a typical usage pattern for the GVO attributes: +# +# - query NV_CTRL_GVO_SUPPORTED to determine if the X screen supports GV0. +# +# - specify NV_CTRL_GVO_SYNC_MODE (one of FREE_RUNNING, GENLOCK, or +# FRAMELOCK); if you specify GENLOCK or FRAMELOCK, you should also +# specify NV_CTRL_GVO_SYNC_SOURCE. +# +# - Use NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED and +# NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED to detect what input syncs are +# present. +# +# (If no analog sync is detected but it is known that a valid +# bi-level or tri-level sync is connected set +# NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE appropriately and +# retest with NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED). +# +# - if syncing to input sync, query the +# NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT attribute; note that Input video +# format can only be queried after SYNC_SOURCE is specified. +# +# - specify the NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT +# +# - specify the NV_CTRL_GVO_DATA_FORMAT +# +# - specify any custom Color Space Conversion (CSC) matrix, offset, +# and scale with XNVCTRLSetGvoColorConversion(). +# +# - if using the GLX_NV_video_out extension to display one or more +# pbuffers, call glXGetVideoDeviceNV() to lock the GVO output for use +# by the GLX client; then bind the pbuffer(s) to the GVO output with +# glXBindVideoImageNV() and send pbuffers to the GVO output with +# glXSendPbufferToVideoNV(); see the GLX_NV_video_out spec for more +# details. +# +# - if using the GLX_NV_present_video extension, call +# glXBindVideoDeviceNV() to bind the GVO video device to current +# OpenGL context. +# +# Note that setting most GVO attributes only causes the value to be +# cached in the X server. The values will be flushed to the hardware +# either when the next MetaMode is set that uses the GVO display +# device, or when a GLX pbuffer is bound to the GVO output (with +# glXBindVideoImageNV()). +# +# Note that GLX_NV_video_out/GLX_NV_present_video and X screen use +# are mutually exclusive. If a MetaMode is currently using the GVO +# device, then glXGetVideoDeviceNV and glXBindVideoImageNV() will +# fail. Similarly, if a GLX client has locked the GVO output (via +# glXGetVideoDeviceNV or glXBindVideoImageNV), then setting a +# MetaMode that uses the GVO device will fail. The +# NV_CTRL_GVO_GLX_LOCKED event will be sent when a GLX client locks +# the GVO output. +# +# + + +# +# NV_CTRL_GVO_SUPPORTED - returns whether this X screen supports GVO; +# if this screen does not support GVO output, then all other GVO +# attributes are unavailable. +# + +NV_CTRL_GVO_SUPPORTED = 67 # R-- +NV_CTRL_GVO_SUPPORTED_FALSE = 0 +NV_CTRL_GVO_SUPPORTED_TRUE = 1 + +# +# NV_CTRL_GVO_SYNC_MODE - selects the GVO sync mode; possible values +# are: +# +# FREE_RUNNING - GVO does not sync to any external signal +# +# GENLOCK - the GVO output is genlocked to an incoming sync signal; +# genlocking locks at hsync. This requires that the output video +# format exactly match the incoming sync video format. +# +# FRAMELOCK - the GVO output is frame locked to an incoming sync +# signal; frame locking locks at vsync. This requires that the output +# video format have the same refresh rate as the incoming sync video +# format. +# + +NV_CTRL_GVO_SYNC_MODE = 68 # RW- +NV_CTRL_GVO_SYNC_MODE_FREE_RUNNING = 0 +NV_CTRL_GVO_SYNC_MODE_GENLOCK = 1 +NV_CTRL_GVO_SYNC_MODE_FRAMELOCK = 2 + +# +# NV_CTRL_GVO_SYNC_SOURCE - if NV_CTRL_GVO_SYNC_MODE is set to either +# GENLOCK or FRAMELOCK, this controls which sync source is used as +# the incoming sync signal (either Composite or SDI). If +# NV_CTRL_GVO_SYNC_MODE is FREE_RUNNING, this attribute has no +# effect. +# + +NV_CTRL_GVO_SYNC_SOURCE = 69 # RW- +NV_CTRL_GVO_SYNC_SOURCE_COMPOSITE = 0 +NV_CTRL_GVO_SYNC_SOURCE_SDI = 1 + +# +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT - specifies the desired output video +# format for GVO devices or the desired input video format for GVI devices. +# +# Note that for GVO, the valid video formats may vary depending on +# the NV_CTRL_GVO_SYNC_MODE and the incoming sync video format. See +# the definition of NV_CTRL_GVO_SYNC_MODE. +# +# Note that when querying the ValidValues for this data type, the +# values are reported as bits within a bitmask +# (ATTRIBUTE_TYPE_INT_BITS); unfortunately, there are more valid +# value bits than will fit in a single 32-bit value. To solve this, +# query the ValidValues for NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT to +# check which of the first 31 VIDEO_FORMATS are valid, query the +# ValidValues for NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 to check which +# of the 32-63 VIDEO_FORMATS are valid, and query the ValidValues of +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 to check which of the 64-95 +# VIDEO_FORMATS are valid. +# +# Note: Setting this attribute on a GVI device may also result in the +# following NV-CONTROL attributes being reset on that device (to +# ensure the configuration remains valid): +# NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT +# NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING +# + +NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT = 70 # RW--I + +NV_CTRL_GVIO_VIDEO_FORMAT_NONE = 0 +NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC = 1 +NV_CTRL_GVIO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL = 2 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_59_94_SMPTE296 = 3 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296 = 4 +NV_CTRL_GVIO_VIDEO_FORMAT_1035I_59_94_SMPTE260 = 5 +NV_CTRL_GVIO_VIDEO_FORMAT_1035I_60_00_SMPTE260 = 6 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE295 = 7 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE274 = 8 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_SMPTE274 = 9 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_SMPTE274 = 10 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_976_SMPTE274 = 11 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_SMPTE274 = 12 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_SMPTE274 = 13 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_SMPTE274 = 14 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_SMPTE274 = 15 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_50_00_SMPTE296 = 16 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_SMPTE274 = 17 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_SMPTE274 = 18 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_30_00_SMPTE296 = 19 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_29_97_SMPTE296 = 20 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_25_00_SMPTE296 = 21 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_24_00_SMPTE296 = 22 +NV_CTRL_GVIO_VIDEO_FORMAT_720P_23_98_SMPTE296 = 23 +NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274 = 24 +NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274 = 25 +NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 = 26 +NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 = 27 +NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 = 28 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_SMPTE372 = 29 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_SMPTE372 = 30 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_SMPTE372 = 31 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_SMPTE372 = 32 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_SMPTE372 = 33 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_SMPTE372 = 34 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_SMPTE372 = 35 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_SMPTE372 = 36 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_SMPTE372 = 37 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_SMPTE372 = 38 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_50_00_3G_LEVEL_A_SMPTE274 = 39 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_59_94_3G_LEVEL_A_SMPTE274 = 40 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_60_00_3G_LEVEL_A_SMPTE274 = 41 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_60_00_3G_LEVEL_B_SMPTE274 = 42 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_3G_LEVEL_B_SMPTE274 = 43 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_3G_LEVEL_B_SMPTE372 = 44 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_50_00_3G_LEVEL_B_SMPTE274 = 45 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_3G_LEVEL_B_SMPTE274 = 46 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_3G_LEVEL_B_SMPTE372 = 47 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_3G_LEVEL_B_SMPTE274 = 48 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_3G_LEVEL_B_SMPTE372 = 49 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_3G_LEVEL_B_SMPTE274 = 50 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_3G_LEVEL_B_SMPTE372 = 51 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_3G_LEVEL_B_SMPTE274 = 52 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_3G_LEVEL_B_SMPTE372 = 53 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_3G_LEVEL_B_SMPTE274 = 54 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_3G_LEVEL_B_SMPTE372 = 55 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_59_94_3G_LEVEL_B_SMPTE274 = 56 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_3G_LEVEL_B_SMPTE274 = 57 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_3G_LEVEL_B_SMPTE372 = 58 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_3G_LEVEL_B_SMPTE274 = 59 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_3G_LEVEL_B_SMPTE372 = 60 +NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_98_3G_LEVEL_B_SMPTE274 = 61 +NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_3G_LEVEL_B_SMPTE372 = 62 +NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_3G_LEVEL_B_SMPTE274 = 63 +NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_3G_LEVEL_B_SMPTE372 = 64 + +# +# The following have been renamed; NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT and the +# corresponding NV_CTRL_GVIO_* formats should be used instead. +# +NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT = 70 # renamed + +NV_CTRL_GVO_VIDEO_FORMAT_NONE = 0 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC = 1 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL = 2 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296 = 3 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296 = 4 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1035I_59_94_SMPTE260 = 5 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1035I_60_00_SMPTE260 = 6 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE295 = 7 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE274 = 8 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080I_59_94_SMPTE274 = 9 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080I_60_00_SMPTE274 = 10 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_976_SMPTE274 = 11 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE274 = 12 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274 = 13 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274 = 14 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274 = 15 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296 = 16 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080I_48_00_SMPTE274 = 17 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080I_47_96_SMPTE274 = 18 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296 = 19 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296 = 20 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_25_00_SMPTE296 = 21 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_24_00_SMPTE296 = 22 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_720P_23_98_SMPTE296 = 23 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274 = 24 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274 = 25 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 = 26 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 = 27 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 = 28 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372 = 29 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372 = 30 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372 = 31 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372 = 32 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372 = 33 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372 = 34 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372 = 35 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372 = 36 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372 = 37 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372 = 38 # renamed + +# +# NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT - indicates the input video format +# detected for GVO or GVI devices; the possible values are the +# NV_CTRL_GVIO_VIDEO_FORMAT constants. +# +# For GVI devices, the jack number should be specified in the lower +# 16 bits of the "display_mask" parameter, while the channel number should be +# specified in the upper 16 bits. +# + +NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT = 71 # R--I + +# +# NV_CTRL_GVO_INPUT_VIDEO_FORMAT - renamed +# +# NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT should be used instead. +# + +NV_CTRL_GVO_INPUT_VIDEO_FORMAT = 71 # renamed + +# +# NV_CTRL_GVO_DATA_FORMAT - This controls how the data in the source +# (either the X screen or the GLX pbuffer) is interpretted and +# displayed. +# +# Note: some of the below DATA_FORMATS have been renamed. For +# example, R8G8B8_TO_RGB444 has been renamed to X8X8X8_444_PASSTHRU. +# This is to more accurately reflect DATA_FORMATS where the +# per-channel data could be either RGB or YCrCb -- the point is that +# the driver and GVO hardware do not perform any implicit color space +# conversion on the data; it is passed through to the SDI out. +# + +NV_CTRL_GVO_DATA_FORMAT = 72 # RW- +NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB444 = 0 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4444 = 1 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4444 = 2 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB422 = 3 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4224 = 4 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4224 = 5 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_RGB444 = 6 # renamed +NV_CTRL_GVO_DATA_FORMAT_X8X8X8_444_PASSTHRU = 6 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_RGBA4444 = 7 # renamed +NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4444_PASSTHRU = 7 +NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_RGBZ4444 = 8 # renamed +NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4444_PASSTHRU = 8 +NV_CTRL_GVO_DATA_FORMAT_Y10CR10CB10_TO_YCRCB444 = 9 # renamed +NV_CTRL_GVO_DATA_FORMAT_X10X10X10_444_PASSTHRU = 9 +NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8_TO_YCRCB444 = 10 # renamed +NV_CTRL_GVO_DATA_FORMAT_X10X8X8_444_PASSTHRU = 10 +NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8A10_TO_YCRCBA4444 = 11 # renamed +NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4444_PASSTHRU = 11 +NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8Z10_TO_YCRCBZ4444 = 12 # renamed +NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4444_PASSTHRU = 12 +NV_CTRL_GVO_DATA_FORMAT_DUAL_R8G8B8_TO_DUAL_YCRCB422 = 13 +NV_CTRL_GVO_DATA_FORMAT_DUAL_Y8CR8CB8_TO_DUAL_YCRCB422 = 14 # renamed +NV_CTRL_GVO_DATA_FORMAT_DUAL_X8X8X8_TO_DUAL_422_PASSTHRU = 14 +NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB422 = 15 +NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB444 = 16 +NV_CTRL_GVO_DATA_FORMAT_Y12CR12CB12_TO_YCRCB444 = 17 # renamed +NV_CTRL_GVO_DATA_FORMAT_X12X12X12_444_PASSTHRU = 17 +NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB444 = 18 +NV_CTRL_GVO_DATA_FORMAT_X8X8X8_422_PASSTHRU = 19 +NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4224_PASSTHRU = 20 +NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4224_PASSTHRU = 21 +NV_CTRL_GVO_DATA_FORMAT_X10X10X10_422_PASSTHRU = 22 +NV_CTRL_GVO_DATA_FORMAT_X10X8X8_422_PASSTHRU = 23 +NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4224_PASSTHRU = 24 +NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4224_PASSTHRU = 25 +NV_CTRL_GVO_DATA_FORMAT_X12X12X12_422_PASSTHRU = 26 +NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB422 = 27 + +# +# NV_CTRL_GVO_DISPLAY_X_SCREEN - not supported +# + +NV_CTRL_GVO_DISPLAY_X_SCREEN = 73 # not supported +NV_CTRL_GVO_DISPLAY_X_SCREEN_ENABLE = 1 # not supported +NV_CTRL_GVO_DISPLAY_X_SCREEN_DISABLE = 0 # not supported + +# +# NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED - indicates whether +# Composite Sync input is detected. +# + +NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED = 74 # R-- +NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED_FALSE = 0 +NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED_TRUE = 1 + +# +# NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE - get/set the +# Composite Sync input detect mode. +# + +NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE = 75 # RW- +NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_AUTO = 0 +NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_BI_LEVEL = 1 +NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_TRI_LEVEL = 2 + +# +# NV_CTRL_GVO_SYNC_INPUT_DETECTED - indicates whether SDI Sync input +# is detected, and what type. +# + +NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED = 76 # R-- +NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_NONE = 0 +NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_HD = 1 +NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_SD = 2 + +# +# NV_CTRL_GVO_VIDEO_OUTPUTS - indicates which GVO video output +# connectors are currently outputing data. +# + +NV_CTRL_GVO_VIDEO_OUTPUTS = 77 # R-- +NV_CTRL_GVO_VIDEO_OUTPUTS_NONE = 0 +NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO1 = 1 +NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO2 = 2 +NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO_BOTH = 3 + +# +# NV_CTRL_GVO_FIRMWARE_VERSION - deprecated +# +# NV_CTRL_STRING_GVIO_FIRMWARE_VERSION should be used instead. +# + +NV_CTRL_GVO_FIRMWARE_VERSION = 78 # deprecated + +# +# NV_CTRL_GVO_SYNC_DELAY_PIXELS - controls the delay between the +# input sync and the output sync in numbers of pixels from hsync; +# this is a 12 bit value. +# +# If the NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW bit is set, +# then setting this value will set an advance instead of a delay. +# + +NV_CTRL_GVO_SYNC_DELAY_PIXELS = 79 # RW- + +# +# NV_CTRL_GVO_SYNC_DELAY_LINES - controls the delay between the input +# sync and the output sync in numbers of lines from vsync; this is a +# 12 bit value. +# +# If the NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW bit is set, +# then setting this value will set an advance instead of a delay. +# + +NV_CTRL_GVO_SYNC_DELAY_LINES = 80 # RW- + +# +# NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE - must be set for a period +# of about 2 seconds for the new InputVideoFormat to be properly +# locked to. In nvidia-settings, we do a reacquire whenever genlock +# or frame lock mode is entered into, when the user clicks the +# "detect" button. This value can be written, but always reads back +# _FALSE. +# + +NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE = 81 # -W- +NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE_FALSE = 0 +NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE_TRUE = 1 + +# +# NV_CTRL_GVO_GLX_LOCKED - deprecated +# +# NV_CTRL_GVO_LOCK_OWNER should be used instead. +# + +NV_CTRL_GVO_GLX_LOCKED = 82 # deprecated +NV_CTRL_GVO_GLX_LOCKED_FALSE = 0 # deprecated +NV_CTRL_GVO_GLX_LOCKED_TRUE = 1 # deprecated + +# +# NV_CTRL_GVIO_VIDEO_FORMAT_{WIDTH,HEIGHT,REFRESH_RATE} - query the +# width, height, and refresh rate for the specified +# NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be queried with +# existing interfaces, XNVCTRLQueryAttribute() should be used, and +# the video format specified in the display_mask field; eg: +# +# XNVCTRLQueryAttribute (dpy, +# screen, +# NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC, +# NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH, +# &value); +# +# Note that Refresh Rate is in milliHertz values +# + +NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH = 83 # R--I +NV_CTRL_GVIO_VIDEO_FORMAT_HEIGHT = 84 # R--I +NV_CTRL_GVIO_VIDEO_FORMAT_REFRESH_RATE = 85 # R--I + +# The following have been renamed; use the NV_CTRL_GVIO_* versions, instead +NV_CTRL_GVO_VIDEO_FORMAT_WIDTH = 83 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_HEIGHT = 84 # renamed +NV_CTRL_GVO_VIDEO_FORMAT_REFRESH_RATE = 85 # renamed + +# +# NV_CTRL_GVO_X_SCREEN_PAN_[XY] - not supported +# + +NV_CTRL_GVO_X_SCREEN_PAN_X = 86 # not supported +NV_CTRL_GVO_X_SCREEN_PAN_Y = 87 # not supported + +# +# NV_CTRL_GPU_OVERCLOCKING_STATE - not supported +# + +NV_CTRL_GPU_OVERCLOCKING_STATE = 88 # not supported +NV_CTRL_GPU_OVERCLOCKING_STATE_NONE = 0 # not supported +NV_CTRL_GPU_OVERCLOCKING_STATE_MANUAL = 1 # not supported + +# +# NV_CTRL_GPU_{2,3}D_CLOCK_FREQS - not supported +# + +NV_CTRL_GPU_2D_CLOCK_FREQS = 89 # not supported +NV_CTRL_GPU_3D_CLOCK_FREQS = 90 # not supported + +# +# NV_CTRL_GPU_DEFAULT_{2,3}D_CLOCK_FREQS - not supported +# + +NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS = 91 # not supported +NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS = 92 # not supported + +# +# NV_CTRL_GPU_CURRENT_CLOCK_FREQS - query the current GPU and memory +# clocks of the graphics device driving the X screen. +# +# NV_CTRL_GPU_CURRENT_CLOCK_FREQS is a "packed" integer attribute; +# the GPU clock is stored in the upper 16 bits of the integer, and +# the memory clock is stored in the lower 16 bits of the integer. +# All clock values are in MHz. All clock values are in MHz. +# + +NV_CTRL_GPU_CURRENT_CLOCK_FREQS = 93 # R--G + +# +# NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS - not supported +# + +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS = 94 # not supported +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_INVALID = 0 # not supported + +# +# NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION - not supported +# + +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION = 95 # not supported +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_START = 0 # not supported +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_CANCEL = 1 # not supported + +# +# NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE - not supported +# + +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE = 96 # not supported +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_IDLE = 0 # not supported +NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_BUSY = 1 # not supported + +# +# NV_CTRL_FLATPANEL_CHIP_LOCATION - for the specified display device, +# report whether the flat panel is driven by the on-chip controller, +# or a separate controller chip elsewhere on the graphics board. +# This attribute is only available for flat panels. +# + +NV_CTRL_FLATPANEL_CHIP_LOCATION = 215 # R-DG +NV_CTRL_FLATPANEL_CHIP_LOCATION_INTERNAL = 0 +NV_CTRL_FLATPANEL_CHIP_LOCATION_EXTERNAL = 1 + +# +# NV_CTRL_FLATPANEL_LINK - report the number of links for a DVI connection, or +# the main link's active lane count for DisplayPort. +# This attribute is only available for flat panels. +# + +NV_CTRL_FLATPANEL_LINK = 216 # R-DG +NV_CTRL_FLATPANEL_LINK_SINGLE = 0 +NV_CTRL_FLATPANEL_LINK_DUAL = 1 +NV_CTRL_FLATPANEL_LINK_QUAD = 3 + +# +# NV_CTRL_FLATPANEL_SIGNAL - for the specified display device, report +# whether the flat panel is driven by an LVDS, TMDS, or DisplayPort signal. +# This attribute is only available for flat panels. +# + +NV_CTRL_FLATPANEL_SIGNAL = 217 # R-DG +NV_CTRL_FLATPANEL_SIGNAL_LVDS = 0 +NV_CTRL_FLATPANEL_SIGNAL_TMDS = 1 +NV_CTRL_FLATPANEL_SIGNAL_DISPLAYPORT = 2 + +# +# NV_CTRL_USE_HOUSE_SYNC - when INPUT, the server (master) frame lock +# device will propagate the incoming house sync signal as the outgoing +# frame lock sync signal. If the frame lock device cannot detect a +# frame lock sync signal, it will default to using the internal timings +# from the GPU connected to the primary connector. +# +# When set to OUTPUT, the server (master) frame lock device will +# generate a house sync signal from its internal timing and output +# this signal over the BNC connector on the frame lock device. This +# is only allowed on a Quadro Sync II device. If an incoming house +# sync signal is present on the BNC connector, this setting will +# have no effect. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_USE_HOUSE_SYNC = 218 # RW-F +NV_CTRL_USE_HOUSE_SYNC_DISABLED = 0 # aliases with FALSE +NV_CTRL_USE_HOUSE_SYNC_INPUT = 1 # aliases with TRUE +NV_CTRL_USE_HOUSE_SYNC_OUTPUT = 2 +NV_CTRL_USE_HOUSE_SYNC_FALSE = 0 +NV_CTRL_USE_HOUSE_SYNC_TRUE = 1 + +# +# NV_CTRL_EDID_AVAILABLE - report if an EDID is available for the +# specified display device. +# +# This attribute may also be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# + +NV_CTRL_EDID_AVAILABLE = 219 # R-DG +NV_CTRL_EDID_AVAILABLE_FALSE = 0 +NV_CTRL_EDID_AVAILABLE_TRUE = 1 + +# +# NV_CTRL_FORCE_STEREO - when TRUE, OpenGL will force stereo flipping +# even when no stereo drawables are visible (if the device is configured +# to support it, see the "Stereo" X config option). +# When false, fall back to the default behavior of only flipping when a +# stereo drawable is visible. +# + +NV_CTRL_FORCE_STEREO = 220 # RW- +NV_CTRL_FORCE_STEREO_FALSE = 0 +NV_CTRL_FORCE_STEREO_TRUE = 1 + +# +# NV_CTRL_IMAGE_SETTINGS - the image quality setting for OpenGL clients. +# +# This setting is only applied to OpenGL clients that are started +# after this setting is applied. +# + +NV_CTRL_IMAGE_SETTINGS = 221 # RW-X +NV_CTRL_IMAGE_SETTINGS_HIGH_QUALITY = 0 +NV_CTRL_IMAGE_SETTINGS_QUALITY = 1 +NV_CTRL_IMAGE_SETTINGS_PERFORMANCE = 2 +NV_CTRL_IMAGE_SETTINGS_HIGH_PERFORMANCE = 3 + +# +# NV_CTRL_XINERAMA - return whether xinerama is enabled +# + +NV_CTRL_XINERAMA = 222 # R--G +NV_CTRL_XINERAMA_OFF = 0 +NV_CTRL_XINERAMA_ON = 1 + +# +# NV_CTRL_XINERAMA_STEREO - when TRUE, OpenGL will allow stereo flipping +# on multiple X screens configured with Xinerama. +# When FALSE, flipping is allowed only on one X screen at a time. +# + +NV_CTRL_XINERAMA_STEREO = 223 # RW- +NV_CTRL_XINERAMA_STEREO_FALSE = 0 +NV_CTRL_XINERAMA_STEREO_TRUE = 1 + +# +# NV_CTRL_BUS_RATE - if the bus type of the specified device is AGP, then +# NV_CTRL_BUS_RATE returns the configured AGP transfer rate. If the bus type +# is PCI Express, then this attribute returns the maximum link width. +# When this attribute is queried on an X screen target, the bus rate of the +# GPU driving the X screen is returned. +# + +NV_CTRL_BUS_RATE = 224 # R--GI + +# +# NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH - returns the maximum +# PCIe link width, in number of lanes. +# +NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH = NV_CTRL_BUS_RATE +# +# NV_CTRL_SHOW_SLI_VISUAL_INDICATOR - when TRUE, OpenGL will draw information +# about the current SLI mode. +# + +NV_CTRL_SHOW_SLI_VISUAL_INDICATOR = 225 # RW-X +NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_FALSE = 0 +NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_TRUE = 1 + +# +# NV_CTRL_SHOW_SLI_HUD - when TRUE, OpenGL will draw information about the +# current SLI mode. +# Renamed this attribute to NV_CTRL_SHOW_SLI_VISUAL_INDICATOR +# + +NV_CTRL_SHOW_SLI_HUD = NV_CTRL_SHOW_SLI_VISUAL_INDICATOR +NV_CTRL_SHOW_SLI_HUD_FALSE = NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_FALSE +NV_CTRL_SHOW_SLI_HUD_TRUE = NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_TRUE + +# +# NV_CTRL_XV_SYNC_TO_DISPLAY - deprecated +# +# NV_CTRL_XV_SYNC_TO_DISPLAY_ID should be used instead. +# + +NV_CTRL_XV_SYNC_TO_DISPLAY = 226 # deprecated + +# +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 - this attribute is only +# intended to be used to query the ValidValues for +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for VIDEO_FORMAT values between +# 31 and 63. See NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for details. +# + +NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 = 227 # ---GI + +# +# NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2 - renamed +# +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 should be used instead. +# +NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2 = 227 # renamed + +# +# NV_CTRL_GVO_OVERRIDE_HW_CSC - Override the SDI hardware's Color Space +# Conversion with the values controlled through +# XNVCTRLSetGvoColorConversion() and XNVCTRLGetGvoColorConversion(). If +# this attribute is FALSE, then the values specified through +# XNVCTRLSetGvoColorConversion() are ignored. +# + +NV_CTRL_GVO_OVERRIDE_HW_CSC = 228 # RW- +NV_CTRL_GVO_OVERRIDE_HW_CSC_FALSE = 0 +NV_CTRL_GVO_OVERRIDE_HW_CSC_TRUE = 1 + +# +# NV_CTRL_GVO_CAPABILITIES - this read-only attribute describes GVO +# capabilities that differ between NVIDIA SDI products. This value +# is a bitmask where each bit indicates whether that capability is +# available. +# +# APPLY_CSC_IMMEDIATELY - whether the CSC matrix, offset, and scale +# specified through XNVCTRLSetGvoColorConversion() will take affect +# immediately, or only after SDI output is disabled and enabled +# again. +# +# APPLY_CSC_TO_X_SCREEN - whether the CSC matrix, offset, and scale +# specified through XNVCTRLSetGvoColorConversion() will also apply +# to GVO output of an X screen, or only to OpenGL GVO output, as +# enabled through the GLX_NV_video_out extension. +# +# COMPOSITE_TERMINATION - whether the 75 ohm termination of the +# SDI composite input signal can be programmed through the +# NV_CTRL_GVO_COMPOSITE_TERMINATION attribute. +# +# SHARED_SYNC_BNC - whether the SDI device has a single BNC +# connector used for both (SDI & Composite) incoming signals. +# +# MULTIRATE_SYNC - whether the SDI device supports synchronization +# of input and output video modes that match in being odd or even +# modes (ie, AA.00 Hz modes can be synched to other BB.00 Hz modes and +# AA.XX Hz can match to BB.YY Hz where .XX and .YY are not .00) +# + +NV_CTRL_GVO_CAPABILITIES = 229 # R-- +NV_CTRL_GVO_CAPABILITIES_APPLY_CSC_IMMEDIATELY = 0x00000001 +NV_CTRL_GVO_CAPABILITIES_APPLY_CSC_TO_X_SCREEN = 0x00000002 +NV_CTRL_GVO_CAPABILITIES_COMPOSITE_TERMINATION = 0x00000004 +NV_CTRL_GVO_CAPABILITIES_SHARED_SYNC_BNC = 0x00000008 +NV_CTRL_GVO_CAPABILITIES_MULTIRATE_SYNC = 0x00000010 +NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW = 0x00000020 + +# +# NV_CTRL_GVO_COMPOSITE_TERMINATION - enable or disable 75 ohm +# termination of the SDI composite input signal. +# + +NV_CTRL_GVO_COMPOSITE_TERMINATION = 230 # RW- +NV_CTRL_GVO_COMPOSITE_TERMINATION_ENABLE = 1 +NV_CTRL_GVO_COMPOSITE_TERMINATION_DISABLE = 0 + +# +# NV_CTRL_ASSOCIATED_DISPLAY_DEVICES - deprecated +# +# NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN should be used instead. +# + +NV_CTRL_ASSOCIATED_DISPLAY_DEVICES = 231 # deprecated + +# +# NV_CTRL_FRAMELOCK_SLAVES - deprecated +# +# NV_CTRL_FRAMELOCK_DISPLAY_CONFIG should be used instead. +# + +NV_CTRL_FRAMELOCK_SLAVES = 232 # deprecated + +# +# NV_CTRL_FRAMELOCK_MASTERABLE - deprecated +# +# NV_CTRL_FRAMELOCK_DISPLAY_CONFIG should be used instead. +# + +NV_CTRL_FRAMELOCK_MASTERABLE = 233 # deprecated + +# +# NV_CTRL_PROBE_DISPLAYS - re-probes the hardware to detect what +# display devices are connected to the GPU or GPU driving the +# specified X screen. The return value is deprecated and should not be used. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_PROBE_DISPLAYS = 234 # R--G + +# +# NV_CTRL_REFRESH_RATE - Returns the refresh rate of the specified +# display device in 100# Hz (ie. to get the refresh rate in Hz, divide +# the returned value by 100.) +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_REFRESH_RATE = 235 # R-DG + +# +# NV_CTRL_GVO_FLIP_QUEUE_SIZE - The Graphics to Video Out interface +# exposed through NV-CONTROL and the GLX_NV_video_out extension uses +# an internal flip queue when pbuffers are sent to the video device +# (via glXSendPbufferToVideoNV()). The NV_CTRL_GVO_FLIP_QUEUE_SIZE +# can be used to query and assign the flip queue size. This +# attribute is applied to GLX when glXGetVideoDeviceNV() is called by +# the application. +# + +NV_CTRL_GVO_FLIP_QUEUE_SIZE = 236 # RW- + +# +# NV_CTRL_CURRENT_SCANLINE - query the current scanline for the +# specified display device. +# + +NV_CTRL_CURRENT_SCANLINE = 237 # R-DG + +# +# NV_CTRL_INITIAL_PIXMAP_PLACEMENT - Controls where X pixmaps are initially +# created. +# +# NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM causes pixmaps to stay in +# system memory. These pixmaps can't be accelerated by the NVIDIA driver; this +# will cause blank windows if used with an OpenGL compositing manager. +# NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM creates pixmaps in system memory +# initially, but allows them to migrate to video memory. +# NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM creates pixmaps in video memory +# when enough resources are available. +# NV_CTRL_INITIAL_PIXMAP_PLACEMENT_RESERVED is currently reserved for future +# use. Behavior is undefined. +# NV_CTRL_INITIAL_PIXMAP_PLACEMENT_GPU_SYSMEM creates pixmaps in GPU accessible +# system memory when enough resources are available. +# + +NV_CTRL_INITIAL_PIXMAP_PLACEMENT = 238 # RW- +NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM = 0 +NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM = 1 +NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM = 2 +NV_CTRL_INITIAL_PIXMAP_PLACEMENT_RESERVED = 3 +NV_CTRL_INITIAL_PIXMAP_PLACEMENT_GPU_SYSMEM = 4 + +# +# NV_CTRL_PCI_BUS - Returns the PCI bus number the specified device is using. +# + +NV_CTRL_PCI_BUS = 239 # R--GI + +# +# NV_CTRL_PCI_DEVICE - Returns the PCI device number the specified device is +# using. +# + +NV_CTRL_PCI_DEVICE = 240 # R--GI + +# +# NV_CTRL_PCI_FUNCTION - Returns the PCI function number the specified device +# is using. +# + +NV_CTRL_PCI_FUNCTION = 241 # R--GI + +# +# NV_CTRL_FRAMELOCK_FPGA_REVISION - Queries the FPGA revision of the +# Frame Lock device. +# +# This attribute must be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK target. +# + +NV_CTRL_FRAMELOCK_FPGA_REVISION = 242 # R--F + +# +# NV_CTRL_MAX_SCREEN_{WIDTH,HEIGHT} - the maximum allowable size, in +# pixels, of either the specified X screen (if the target_type of the +# query is an X screen), or any X screen on the specified GPU (if the +# target_type of the query is a GPU). +# + +NV_CTRL_MAX_SCREEN_WIDTH = 243 # R--G +NV_CTRL_MAX_SCREEN_HEIGHT = 244 # R--G + +# +# NV_CTRL_MAX_DISPLAYS - The maximum number of display devices that +# can be driven simultaneously on a GPU (e.g., that can be used in a +# MetaMode at once). Note that this does not indicate the maximum +# number of displays that are listed in NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU +# and NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU because more display +# devices can be connected than are actively in use. +# + +NV_CTRL_MAX_DISPLAYS = 245 # R--G + +# +# NV_CTRL_DYNAMIC_TWINVIEW - Returns whether or not the screen +# supports dynamic twinview. +# + +NV_CTRL_DYNAMIC_TWINVIEW = 246 # R-- + +# +# NV_CTRL_MULTIGPU_DISPLAY_OWNER - Returns the (NV-CONTROL) GPU ID of +# the GPU that has the display device(s) used for showing the X Screen. +# + +NV_CTRL_MULTIGPU_DISPLAY_OWNER = 247 # R-- + +# +# NV_CTRL_GPU_SCALING - not supported +# + +NV_CTRL_GPU_SCALING = 248 # not supported + +NV_CTRL_GPU_SCALING_TARGET_INVALID = 0 # not supported +NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_BEST_FIT = 1 # not supported +NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_NATIVE = 2 # not supported + +NV_CTRL_GPU_SCALING_METHOD_INVALID = 0 # not supported +NV_CTRL_GPU_SCALING_METHOD_STRETCHED = 1 # not supported +NV_CTRL_GPU_SCALING_METHOD_CENTERED = 2 # not supported +NV_CTRL_GPU_SCALING_METHOD_ASPECT_SCALED = 3 # not supported + +# +# NV_CTRL_FRONTEND_RESOLUTION - not supported +# + +NV_CTRL_FRONTEND_RESOLUTION = 249 # not supported + +# +# NV_CTRL_BACKEND_RESOLUTION - not supported +# + +NV_CTRL_BACKEND_RESOLUTION = 250 # not supported + +# +# NV_CTRL_FLATPANEL_NATIVE_RESOLUTION - not supported +# + +NV_CTRL_FLATPANEL_NATIVE_RESOLUTION = 251 # not supported + +# +# NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION - not supported +# + +NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION = 252 # not supported + +# +# NV_CTRL_GPU_SCALING_ACTIVE - not supported +# + +NV_CTRL_GPU_SCALING_ACTIVE = 253 # not supported + +# +# NV_CTRL_DFP_SCALING_ACTIVE - not supported +# + +NV_CTRL_DFP_SCALING_ACTIVE = 254 # not supported + +# +# NV_CTRL_FSAA_APPLICATION_ENHANCED - Controls how the NV_CTRL_FSAA_MODE +# is applied when NV_CTRL_FSAA_APPLICATION_CONTROLLED is set to +# NV_CTRL_APPLICATION_CONTROLLED_DISABLED. When +# NV_CTRL_FSAA_APPLICATION_ENHANCED is _DISABLED, OpenGL applications will +# be forced to use the FSAA mode specified by NV_CTRL_FSAA_MODE. when set +# to _ENABLED, only those applications that have selected a multisample +# FBConfig will be made to use the NV_CTRL_FSAA_MODE specified. +# +# This attribute is ignored when NV_CTRL_FSAA_APPLICATION_CONTROLLED is +# set to NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED. +# + +NV_CTRL_FSAA_APPLICATION_ENHANCED = 255 # RW-X +NV_CTRL_FSAA_APPLICATION_ENHANCED_ENABLED = 1 +NV_CTRL_FSAA_APPLICATION_ENHANCED_DISABLED = 0 + +# +# NV_CTRL_FRAMELOCK_SYNC_RATE_4 - This is the refresh rate that the +# frame lock board is sending to the GPU with 4 digits of precision. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK. +# + +NV_CTRL_FRAMELOCK_SYNC_RATE_4 = 256 # R--F + +# +# NV_CTRL_GVO_LOCK_OWNER - indicates that the GVO device is available +# or in use (by GLX or an X screen). +# +# The GVO device is locked by GLX when either glXGetVideoDeviceNV +# (part of GLX_NV_video_out) or glXBindVideoDeviceNV (part of +# GLX_NV_present_video) is called. All GVO output resources are +# locked until released by the GLX_NV_video_out/GLX_NV_present_video +# client. +# +# The GVO device is locked/unlocked by an X screen, when the GVO device is +# used in a MetaMode on an X screen. +# +# When the GVO device is locked, setting of the following GVO NV-CONTROL +# attributes will not happen immediately and will instead be cached. The +# GVO resource will need to be disabled/released and re-enabled/claimed for +# the values to be flushed. These attributes are: +# +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT +# NV_CTRL_GVO_DATA_FORMAT +# NV_CTRL_GVO_FLIP_QUEUE_SIZE +# + +NV_CTRL_GVO_LOCK_OWNER = 257 # R-- +NV_CTRL_GVO_LOCK_OWNER_NONE = 0 +NV_CTRL_GVO_LOCK_OWNER_GLX = 1 +NV_CTRL_GVO_LOCK_OWNER_CLONE = 2 # not supported +NV_CTRL_GVO_LOCK_OWNER_X_SCREEN = 3 + +# +# NV_CTRL_HWOVERLAY - when a workstation overlay is in use, reports +# whether the hardware overlay is used, or if the overlay is emulated. +# + +NV_CTRL_HWOVERLAY = 258 # R-- +NV_CTRL_HWOVERLAY_FALSE = 0 +NV_CTRL_HWOVERLAY_TRUE = 1 + +# +# NV_CTRL_NUM_GPU_ERRORS_RECOVERED - Returns the number of GPU errors +# occured. This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_NUM_GPU_ERRORS_RECOVERED = 259 # R--- + +# +# NV_CTRL_REFRESH_RATE_3 - Returns the refresh rate of the specified +# display device in 1000# Hz (ie. to get the refresh rate in Hz, divide +# the returned value by 1000.) +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_REFRESH_RATE_3 = 260 # R-DG + +# +# NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS - not supported +# + +NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS = 261 # not supported +NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS_OFF = 0 # not supported +NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS_ON = 1 # not supported + +# +# NV_CTRL_GPU_POWER_SOURCE reports the type of power source +# of the GPU driving the X screen. +# + +NV_CTRL_GPU_POWER_SOURCE = 262 # R--G +NV_CTRL_GPU_POWER_SOURCE_AC = 0 +NV_CTRL_GPU_POWER_SOURCE_BATTERY = 1 + +# +# NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE - not supported +# + +NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE = 263 # not supported +NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE_DESKTOP = 0 # not supported +NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE_MAXPERF = 1 # not supported + +# NV_CTRL_GLYPH_CACHE - Enables RENDER Glyph Caching to VRAM + +NV_CTRL_GLYPH_CACHE = 264 # RW- +NV_CTRL_GLYPH_CACHE_DISABLED = 0 +NV_CTRL_GLYPH_CACHE_ENABLED = 1 + +# +# NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL reports the current +# Performance level of the GPU driving the X screen. Each +# Performance level has associated NVClock and Mem Clock values. +# + +NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL = 265 # R--G + +# +# NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE reports if Adaptive Clocking +# is Enabled on the GPU driving the X screen. +# + +NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE = 266 # R--G +NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE_DISABLED = 0 +NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE_ENABLED = 1 + +# +# NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED - Returns whether or not the GVO output +# video is locked to the GPU. +# + +NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED = 267 # R--- +NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED_FALSE = 0 +NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED_TRUE = 1 + +# +# NV_CTRL_GVO_SYNC_LOCK_STATUS - Returns whether or not the GVO device +# is locked to the input ref signal. If the sync mode is set to +# NV_CTRL_GVO_SYNC_MODE_GENLOCK, then this returns the genlock +# sync status, and if the sync mode is set to NV_CTRL_GVO_SYNC_MODE_FRAMELOCK, +# then this reports the frame lock status. +# + +NV_CTRL_GVO_SYNC_LOCK_STATUS = 268 # R--- +NV_CTRL_GVO_SYNC_LOCK_STATUS_UNLOCKED = 0 +NV_CTRL_GVO_SYNC_LOCK_STATUS_LOCKED = 1 + +# +# NV_CTRL_GVO_ANC_TIME_CODE_GENERATION - Allows SDI device to generate +# time codes in the ANC region of the SDI video output stream. +# + +NV_CTRL_GVO_ANC_TIME_CODE_GENERATION = 269 # RW-- +NV_CTRL_GVO_ANC_TIME_CODE_GENERATION_DISABLE = 0 +NV_CTRL_GVO_ANC_TIME_CODE_GENERATION_ENABLE = 1 + +# +# NV_CTRL_GVO_COMPOSITE - Enables/Disables SDI compositing. This attribute +# is only available when an SDI input source is detected and is in genlock +# mode. +# + +NV_CTRL_GVO_COMPOSITE = 270 # RW-- +NV_CTRL_GVO_COMPOSITE_DISABLE = 0 +NV_CTRL_GVO_COMPOSITE_ENABLE = 1 + +# +# NV_CTRL_GVO_COMPOSITE_ALPHA_KEY - When compositing is enabled, this +# enables/disables alpha blending. +# + +NV_CTRL_GVO_COMPOSITE_ALPHA_KEY = 271 # RW-- +NV_CTRL_GVO_COMPOSITE_ALPHA_KEY_DISABLE = 0 +NV_CTRL_GVO_COMPOSITE_ALPHA_KEY_ENABLE = 1 + +# +# NV_CTRL_GVO_COMPOSITE_LUMA_KEY_RANGE - Set the values of a luma +# channel range. This is a packed int that has the following format +# (in order of high-bits to low bits): +# +# Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits) +# +# To query the current values, pass the range # throught the display_mask +# variable. +# + +NV_CTRL_GVO_COMPOSITE_LUMA_KEY_RANGE = 272 # RW-- + +# +# NV_CTRL_GVO_COMPOSITE_CR_KEY_RANGE - Set the values of a CR +# channel range. This is a packed int that has the following format +# (in order of high-bits to low bits): +# +# Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits) +# +# To query the current values, pass the range # throught he display_mask +# variable. +# + +NV_CTRL_GVO_COMPOSITE_CR_KEY_RANGE = 273 # RW-- + +# +# NV_CTRL_GVO_COMPOSITE_CB_KEY_RANGE - Set the values of a CB +# channel range. This is a packed int that has the following format +# (in order of high-bits to low bits): +# +# Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits) +# +# To query the current values, pass the range # throught he display_mask +# variable. +# + +NV_CTRL_GVO_COMPOSITE_CB_KEY_RANGE = 274 # RW-- + +# +# NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES - Returns the number of ranges +# available for each channel (Y/Luma, Cr, and Cb.) +# + +NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES = 275 # R--- + +# +# NV_CTRL_SWITCH_TO_DISPLAYS - not supported +# + +NV_CTRL_SWITCH_TO_DISPLAYS = 276 # not supported + +# +# NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT - not supported +# + +NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT = 277 # not supported + +# +# NV_CTRL_NOTEBOOK_INTERNAL_LCD - deprecated +# + +NV_CTRL_NOTEBOOK_INTERNAL_LCD = 278 # deprecated + +# +# NV_CTRL_DEPTH_30_ALLOWED - returns whether the NVIDIA X driver supports +# depth 30 on the specified X screen or GPU. +# + +NV_CTRL_DEPTH_30_ALLOWED = 279 # R--G + +# +# NV_CTRL_MODE_SET_EVENT This attribute is sent as an event +# when hotkey, ctrl-alt-+/- or randr event occurs. Note that +# This attribute cannot be set or queried and is meant to +# be received by clients that wish to be notified of when +# mode set events occur. +# + +NV_CTRL_MODE_SET_EVENT = 280 # --- + +# +# NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE - the gamma value used by +# OpenGL when NV_CTRL_OPENGL_AA_LINE_GAMMA is enabled +# + +NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE = 281 # RW-X + +# +# NV_CTRL_VCSC_HIGH_PERF_MODE - deprecated +# +# Is used to both query High Performance Mode status on the Visual Computing +# System, and also to enable or disable High Performance Mode. +# + +NV_CTRL_VCSC_HIGH_PERF_MODE = 282 # RW-V +NV_CTRL_VCSC_HIGH_PERF_MODE_DISABLE = 0 +NV_CTRL_VCSC_HIGH_PERF_MODE_ENABLE = 1 + +# +# NV_CTRL_DISPLAYPORT_LINK_RATE - returns the negotiated lane bandwidth of the +# DisplayPort main link. The numerical value of this attribute is the link +# rate in bps divided by 27000000. +# This attribute is only available for DisplayPort flat panels. +# + +NV_CTRL_DISPLAYPORT_LINK_RATE = 291 # R-DG +NV_CTRL_DISPLAYPORT_LINK_RATE_DISABLED = 0x0 +NV_CTRL_DISPLAYPORT_LINK_RATE_1_62GBPS = 0x6 # deprecated +NV_CTRL_DISPLAYPORT_LINK_RATE_2_70GBPS = 0xA # deprecated + +# +# NV_CTRL_STEREO_EYES_EXCHANGE - Controls whether or not the left and right +# eyes of a stereo image are flipped. +# + +NV_CTRL_STEREO_EYES_EXCHANGE = 292 # RW-X +NV_CTRL_STEREO_EYES_EXCHANGE_OFF = 0 +NV_CTRL_STEREO_EYES_EXCHANGE_ON = 1 + +# +# NV_CTRL_NO_SCANOUT - returns whether the special "NoScanout" mode is +# enabled on the specified X screen or GPU; for details on this mode, +# see the description of the "none" value for the "UseDisplayDevice" +# X configuration option in the NVIDIA driver README. +# + +NV_CTRL_NO_SCANOUT = 293 # R--G +NV_CTRL_NO_SCANOUT_DISABLED = 0 +NV_CTRL_NO_SCANOUT_ENABLED = 1 + +# +# NV_CTRL_GVO_CSC_CHANGED_EVENT This attribute is sent as an event +# when the color space conversion matrix has been altered by another +# client. +# + +NV_CTRL_GVO_CSC_CHANGED_EVENT = 294 # --- + +# +# NV_CTRL_FRAMELOCK_SLAVEABLE - deprecated +# +# NV_CTRL_FRAMELOCK_DISPLAY_CONFIG should be used instead. +# + +NV_CTRL_FRAMELOCK_SLAVEABLE = 295 # deprecated + +# +# NV_CTRL_GVO_SYNC_TO_DISPLAY This attribute controls whether or not +# the non-SDI display device will be sync'ed to the SDI display device +# (when configured in TwinView, Clone Mode or when using the SDI device +# with OpenGL). +# + +NV_CTRL_GVO_SYNC_TO_DISPLAY = 296 # --- +NV_CTRL_GVO_SYNC_TO_DISPLAY_DISABLE = 0 +NV_CTRL_GVO_SYNC_TO_DISPLAY_ENABLE = 1 + +# +# NV_CTRL_X_SERVER_UNIQUE_ID - returns a pseudo-unique identifier for this +# X server. Intended for use in cases where an NV-CONTROL client communicates +# with multiple X servers, and wants some level of confidence that two +# X Display connections correspond to the same or different X servers. +# + +NV_CTRL_X_SERVER_UNIQUE_ID = 297 # R--- + +# +# NV_CTRL_PIXMAP_CACHE - This attribute controls whether the driver attempts to +# store video memory pixmaps in a cache. The cache speeds up allocation and +# deallocation of pixmaps, but could use more memory than when the cache is +# disabled. +# + +NV_CTRL_PIXMAP_CACHE = 298 # RW-X +NV_CTRL_PIXMAP_CACHE_DISABLE = 0 +NV_CTRL_PIXMAP_CACHE_ENABLE = 1 + +# +# NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB - When the pixmap cache is enabled and +# there is not enough free space in the cache to fit a new pixmap, the driver +# will round up to the next multiple of this number of kilobytes when +# allocating more memory for the cache. +# + +NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB = 299 # RW-X + +# +# NV_CTRL_IS_GVO_DISPLAY - returns whether or not a given display is an +# SDI device. +# + +NV_CTRL_IS_GVO_DISPLAY = 300 # R-D +NV_CTRL_IS_GVO_DISPLAY_FALSE = 0 +NV_CTRL_IS_GVO_DISPLAY_TRUE = 1 + +# +# NV_CTRL_PCI_ID - Returns the PCI vendor and device ID of the specified +# device. +# +# NV_CTRL_PCI_ID is a "packed" integer attribute; the PCI vendor ID is stored +# in the upper 16 bits of the integer, and the PCI device ID is stored in the +# lower 16 bits of the integer. +# + +NV_CTRL_PCI_ID = 301 # R--GI + +# +# NV_CTRL_GVO_FULL_RANGE_COLOR - Allow full range color data [4-1019] +# without clamping to [64-940]. +# + +NV_CTRL_GVO_FULL_RANGE_COLOR = 302 # RW- +NV_CTRL_GVO_FULL_RANGE_COLOR_DISABLED = 0 +NV_CTRL_GVO_FULL_RANGE_COLOR_ENABLED = 1 + +# +# NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE - Returns whether or not +# SLI Mosaic Mode supported. +# + +NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE = 303 # R-- +NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_FALSE = 0 +NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_TRUE = 1 + +# +# NV_CTRL_GVO_ENABLE_RGB_DATA - Allows clients to specify when +# the GVO board should process colors as RGB when the output data +# format is one of the NV_CTRL_GVO_DATA_FORMAT_???_PASSTRHU modes. +# + +NV_CTRL_GVO_ENABLE_RGB_DATA = 304 # RW- +NV_CTRL_GVO_ENABLE_RGB_DATA_DISABLE = 0 +NV_CTRL_GVO_ENABLE_RGB_DATA_ENABLE = 1 + +# +# NV_CTRL_IMAGE_SHARPENING_DEFAULT - Returns default value of +# Image Sharpening. +# + +NV_CTRL_IMAGE_SHARPENING_DEFAULT = 305 # R-- + +# +# NV_CTRL_PCI_DOMAIN - Returns the PCI domain number the specified device is +# using. +# + +NV_CTRL_PCI_DOMAIN = 306 # R--GI + +# +# NV_CTRL_GVI_NUM_JACKS - Returns the number of input BNC jacks available +# on a GVI device. +# + +NV_CTRL_GVI_NUM_JACKS = 307 # R--I + +# +# NV_CTRL_GVI_MAX_LINKS_PER_STREAM - Returns the maximum supported number of +# links that can be tied to one stream. +# + +NV_CTRL_GVI_MAX_LINKS_PER_STREAM = 308 # R--I + +# +# NV_CTRL_GVI_DETECTED_CHANNEL_BITS_PER_COMPONENT - Returns the detected +# number of bits per component (BPC) of data on the given input jack+ +# channel. +# +# The jack number should be specified in the lower 16 bits of the +# "display_mask" parameter, while the channel number should be specified in +# the upper 16 bits. +# + +NV_CTRL_GVI_DETECTED_CHANNEL_BITS_PER_COMPONENT = 309 # R--I +NV_CTRL_GVI_BITS_PER_COMPONENT_UNKNOWN = 0 +NV_CTRL_GVI_BITS_PER_COMPONENT_8 = 1 +NV_CTRL_GVI_BITS_PER_COMPONENT_10 = 2 +NV_CTRL_GVI_BITS_PER_COMPONENT_12 = 3 + +# +# NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT - Specify the number of +# bits per component (BPC) of data for the captured stream. +# The stream number should be specified in the "display_mask" parameter. +# +# Note: Setting this attribute may also result in the following +# NV-CONTROL attributes being reset on the GVI device (to ensure +# the configuration remains valid): +# NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING +# + +NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT = 310 # RW-I + +# +# NV_CTRL_GVI_DETECTED_CHANNEL_COMPONENT_SAMPLING - Returns the detected +# sampling format for the input jack+channel. +# +# The jack number should be specified in the lower 16 bits of the +# "display_mask" parameter, while the channel number should be specified in +# the upper 16 bits. +# + +NV_CTRL_GVI_DETECTED_CHANNEL_COMPONENT_SAMPLING = 311 # R--I +NV_CTRL_GVI_COMPONENT_SAMPLING_UNKNOWN = 0 +NV_CTRL_GVI_COMPONENT_SAMPLING_4444 = 1 +NV_CTRL_GVI_COMPONENT_SAMPLING_4224 = 2 +NV_CTRL_GVI_COMPONENT_SAMPLING_444 = 3 +NV_CTRL_GVI_COMPONENT_SAMPLING_422 = 4 +NV_CTRL_GVI_COMPONENT_SAMPLING_420 = 5 + +# +# NV_CTRL_GVI_REQUESTED_COMPONENT_SAMPLING - Specify the sampling format for +# the captured stream. +# The possible values are the NV_CTRL_GVI_DETECTED_COMPONENT_SAMPLING +# constants. +# The stream number should be specified in the "display_mask" parameter. +# + +NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING = 312 # RW-I + +# +# NV_CTRL_GVI_CHROMA_EXPAND - Enable or disable 4:2:2 -> 4:4:4 chroma +# expansion for the captured stream. This value is ignored when a +# COMPONENT_SAMPLING format is selected that does not use chroma subsampling, +# or if a BITS_PER_COMPONENT value is selected that is not supported. +# The stream number should be specified in the "display_mask" parameter. +# + +NV_CTRL_GVI_REQUESTED_STREAM_CHROMA_EXPAND = 313 # RW-I +NV_CTRL_GVI_CHROMA_EXPAND_FALSE = 0 +NV_CTRL_GVI_CHROMA_EXPAND_TRUE = 1 + +# +# NV_CTRL_GVI_DETECTED_CHANNEL_COLOR_SPACE - Returns the detected color space +# of the input jack+channel. +# +# The jack number should be specified in the lower 16 bits of the +# "display_mask" parameter, while the channel number should be specified in +# the upper 16 bits. +# + +NV_CTRL_GVI_DETECTED_CHANNEL_COLOR_SPACE = 314 # R--I +NV_CTRL_GVI_COLOR_SPACE_UNKNOWN = 0 +NV_CTRL_GVI_COLOR_SPACE_GBR = 1 +NV_CTRL_GVI_COLOR_SPACE_GBRA = 2 +NV_CTRL_GVI_COLOR_SPACE_GBRD = 3 +NV_CTRL_GVI_COLOR_SPACE_YCBCR = 4 +NV_CTRL_GVI_COLOR_SPACE_YCBCRA = 5 +NV_CTRL_GVI_COLOR_SPACE_YCBCRD = 6 + +# +# NV_CTRL_GVI_DETECTED_CHANNEL_LINK_ID - Returns the detected link identifier +# for the given input jack+channel. +# +# The jack number should be specified in the lower 16 bits of the +# "display_mask" parameter, while the channel number should be specified in +# the upper 16 bits. +# + +NV_CTRL_GVI_DETECTED_CHANNEL_LINK_ID = 315 # R--I +NV_CTRL_GVI_LINK_ID_UNKNOWN = 0xFFFF + +# +# NV_CTRL_GVI_DETECTED_CHANNEL_SMPTE352_IDENTIFIER - Returns the 4-byte +# SMPTE 352 identifier from the given input jack+channel. +# +# The jack number should be specified in the lower 16 bits of the +# "display_mask" parameter, while the channel number should be specified in +# the upper 16 bits. +# + +NV_CTRL_GVI_DETECTED_CHANNEL_SMPTE352_IDENTIFIER = 316 # R--I + +# +# NV_CTRL_GVI_GLOBAL_IDENTIFIER - Returns a global identifier for the +# GVI device. This identifier can be used to relate GVI devices named +# in NV-CONTROL with those enumerated in OpenGL. +# + +NV_CTRL_GVI_GLOBAL_IDENTIFIER = 317 # R--I + +# +# NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION - Returns the number of nanoseconds +# that one unit of NV_CTRL_FRAMELOCK_SYNC_DELAY corresponds to. +# +NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION = 318 # R-- + +# +# NV_CTRL_GPU_COOLER_MANUAL_CONTROL - Query the current or set a new +# cooler control state; the value of this attribute controls the +# availability of additional cooler control attributes (see below). +# +# Note: this attribute is unavailable unless cooler control support +# has been enabled in the X server (by the user). +# + +NV_CTRL_GPU_COOLER_MANUAL_CONTROL = 319 # RW-G +NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE = 0 +NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE = 1 + +# +# NV_CTRL_THERMAL_COOLER_LEVEL - The cooler's target level. +# Normally, the driver dynamically adjusts the cooler based on +# the needs of the GPU. But when NV_CTRL_GPU_COOLER_MANUAL_CONTROL=TRUE, +# the driver will attempt to make the cooler achieve the setting in +# NV_CTRL_THERMAL_COOLER_LEVEL. The actual current level of the cooler +# is reported in NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL. +# + +NV_CTRL_THERMAL_COOLER_LEVEL = 320 # RW-C + +# NV_CTRL_THERMAL_COOLER_LEVEL_SET_DEFAULT - Sets default values of +# cooler. +# + +NV_CTRL_THERMAL_COOLER_LEVEL_SET_DEFAULT = 321 # -W-C + +# +# NV_CTRL_THERMAL_COOLER_CONTROL_TYPE - +# Returns a cooler's control signal characteristics. +# The possible types are restricted, Variable and Toggle. +# + +NV_CTRL_THERMAL_COOLER_CONTROL_TYPE = 322 # R--C +NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_NONE = 0 +NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_TOGGLE = 1 +NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_VARIABLE = 2 + +# +# NV_CTRL_THERMAL_COOLER_TARGET - Returns objects that cooler cools. +# Targets may be GPU, Memory, Power Supply or All of these. +# GPU_RELATED = GPU | MEMORY | POWER_SUPPLY +# +# + +NV_CTRL_THERMAL_COOLER_TARGET = 323 # R--C +NV_CTRL_THERMAL_COOLER_TARGET_NONE = 0 +NV_CTRL_THERMAL_COOLER_TARGET_GPU = 1 +NV_CTRL_THERMAL_COOLER_TARGET_MEMORY = 2 +NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY = 4 +NV_CTRL_THERMAL_COOLER_TARGET_GPU_RELATED = NV_CTRL_THERMAL_COOLER_TARGET_GPU | NV_CTRL_THERMAL_COOLER_TARGET_MEMORY | NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY + +# +# NV_CTRL_GPU_ECC_SUPPORTED - Reports whether ECC is supported by the +# targeted GPU. +# +NV_CTRL_GPU_ECC_SUPPORTED = 324 # R--G +NV_CTRL_GPU_ECC_SUPPORTED_FALSE = 0 +NV_CTRL_GPU_ECC_SUPPORTED_TRUE = 1 + +# +# NV_CTRL_GPU_ECC_STATUS - Returns the current hardware ECC setting +# for the targeted GPU. +# +NV_CTRL_GPU_ECC_STATUS = 325 # R--G +NV_CTRL_GPU_ECC_STATUS_DISABLED = 0 +NV_CTRL_GPU_ECC_STATUS_ENABLED = 1 + +# +# NV_CTRL_GPU_ECC_CONFIGURATION - Reports whether ECC can be configured +# dynamically for the GPU in question. +# +NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED = 326 # R--G +NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_FALSE = 0 +NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_TRUE = 1 + +# +# NV_CTRL_GPU_ECC_CONFIGURATION_SETTING - Returns the current ECC +# configuration setting or specifies new settings. New settings do not +# take effect until the next POST. +# +NV_CTRL_GPU_ECC_CONFIGURATION = 327 # RW-G +NV_CTRL_GPU_ECC_CONFIGURATION_DISABLED = 0 +NV_CTRL_GPU_ECC_CONFIGURATION_ENABLED = 1 + +# +# NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_SETTING - Returns the default +# ECC configuration setting. +# +NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION = 328 # R--G +NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_DISABLED = 0 +NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_ENABLED = 1 + +# +# NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS - Returns the number of single-bit +# ECC errors detected by the targeted GPU since the last POST. +# Note: this attribute is a 64-bit integer attribute. +# +NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS = 329 # R--GQ + +# +# NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS - Returns the number of double-bit +# ECC errors detected by the targeted GPU since the last POST. +# Note: this attribute is a 64-bit integer attribute. +# +NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS = 330 # R--GQ + +# +# NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS - Returns the number of +# single-bit ECC errors detected by the targeted GPU since the +# last counter reset. +# Note: this attribute is a 64-bit integer attribute. +# +NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS = 331 # R--GQ + +# +# NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS - Returns the number of +# double-bit ECC errors detected by the targeted GPU since the +# last counter reset. +# Note: this attribute is a 64-bit integer attribute. +# +NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS = 332 # R--GQ + +# +# NV_CTRL_GPU_ECC_RESET_ERROR_STATUS - Resets the volatile/aggregate +# single-bit and double-bit error counters. This attribute is a +# bitmask attribute. +# +NV_CTRL_GPU_ECC_RESET_ERROR_STATUS = 333 # -W-G +NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_VOLATILE = 0x00000001 +NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_AGGREGATE = 0x00000002 + +# +# NV_CTRL_GPU_POWER_MIZER_MODE - Provides a hint to the driver +# as to how to manage the performance of the GPU. +# +# ADAPTIVE - adjust GPU clocks based on GPU +# utilization +# PREFER_MAXIMUM_PERFORMANCE - raise GPU clocks to favor +# maximum performance, to the extent +# that thermal and other constraints +# allow +# AUTO - let the driver choose the performance +# policy +# PREFER_CONSISTENT_PERFORMANCE - lock to GPU base clocks +# +NV_CTRL_GPU_POWER_MIZER_MODE = 334 # RW-G +NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE = 0 +NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE = 1 +NV_CTRL_GPU_POWER_MIZER_MODE_AUTO = 2 +NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_CONSISTENT_PERFORMANCE = 3 + +# +# NV_CTRL_GVI_SYNC_OUTPUT_FORMAT - Returns the output sync signal +# from the GVI device. +# + +NV_CTRL_GVI_SYNC_OUTPUT_FORMAT = 335 # R--I + +# +# NV_CTRL_GVI_MAX_CHANNELS_PER_JACK - Returns the maximum +# supported number of (logical) channels within a single physical jack of +# a GVI device. For most SDI video formats, there is only one channel +# (channel 0). But for 3G video formats (as specified in SMPTE 425), +# as an example, there are two channels (channel 0 and channel 1) per +# physical jack. +# + +NV_CTRL_GVI_MAX_CHANNELS_PER_JACK = 336 # R--I + +# +# NV_CTRL_GVI_MAX_STREAMS - Returns the maximum number of streams +# that can be configured on the GVI device. +# + +NV_CTRL_GVI_MAX_STREAMS = 337 # R--I + +# +# NV_CTRL_GVI_NUM_CAPTURE_SURFACES - The GVI interface exposed through +# NV-CONTROL and the GLX_NV_video_input extension uses internal capture +# surfaces when frames are read from the GVI device. The +# NV_CTRL_GVI_NUM_CAPTURE_SURFACES can be used to query and assign the +# number of capture surfaces. This attribute is applied when +# glXBindVideoCaptureDeviceNV() is called by the application. +# +# A lower number of capture surfaces will mean less video memory is used, +# but can result in frames being dropped if the application cannot keep up +# with the capture device. A higher number will prevent frames from being +# dropped, making capture more reliable but will consume move video memory. +# +NV_CTRL_GVI_NUM_CAPTURE_SURFACES = 338 # RW-I + +# +# NV_CTRL_OVERSCAN_COMPENSATION - not supported +# +NV_CTRL_OVERSCAN_COMPENSATION = 339 # not supported + +# +# NV_CTRL_GPU_PCIE_GENERATION - Reports the current PCIe generation. +# +NV_CTRL_GPU_PCIE_GENERATION = 341 # R--GI +NV_CTRL_GPU_PCIE_GENERATION1 = 0x00000001 +NV_CTRL_GPU_PCIE_GENERATION2 = 0x00000002 +NV_CTRL_GPU_PCIE_GENERATION3 = 0x00000003 + +# +# NV_CTRL_GVI_BOUND_GPU - Returns the NV_CTRL_TARGET_TYPE_GPU target_id of +# the GPU currently bound to the GVI device. Returns -1 if no GPU is +# currently bound to the GVI device. +# +NV_CTRL_GVI_BOUND_GPU = 342 # R--I + +# +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 - this attribute is only +# intended to be used to query the ValidValues for +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for VIDEO_FORMAT values between +# 64 and 95. See NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for details. +# + +NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 = 343 # ---GI + +# +# NV_CTRL_ACCELERATE_TRAPEZOIDS - Toggles RENDER Trapezoid acceleration +# + +NV_CTRL_ACCELERATE_TRAPEZOIDS = 344 # RW- +NV_CTRL_ACCELERATE_TRAPEZOIDS_DISABLE = 0 +NV_CTRL_ACCELERATE_TRAPEZOIDS_ENABLE = 1 + +# +# NV_CTRL_GPU_CORES - Returns number of GPU cores supported by the graphics +# pipeline. +# + +NV_CTRL_GPU_CORES = 345 # R--G + +# +# NV_CTRL_GPU_MEMORY_BUS_WIDTH - Returns memory bus bandwidth on the associated +# subdevice. +# + +NV_CTRL_GPU_MEMORY_BUS_WIDTH = 346 # R--G + +# +# NV_CTRL_GVI_TEST_MODE - This attribute controls the GVI test mode. When +# enabled, the GVI device will generate fake data as quickly as possible. All +# GVI settings are still valid when this is enabled (e.g., the requested video +# format is honored and sets the video size). +# This may be used to test the pipeline. +# + +NV_CTRL_GVI_TEST_MODE = 347 # R--I +NV_CTRL_GVI_TEST_MODE_DISABLE = 0 +NV_CTRL_GVI_TEST_MODE_ENABLE = 1 + +# +# NV_CTRL_COLOR_SPACE - This option controls the preferred color space of the +# video signal. This may not match the current color space depending on the +# current mode on this display. +# +# NV_CTRL_CURRENT_COLOR_SPACE will reflect the actual color space in use. +# +NV_CTRL_COLOR_SPACE = 348 # RWDG +NV_CTRL_COLOR_SPACE_RGB = 0 +NV_CTRL_COLOR_SPACE_YCbCr422 = 1 +NV_CTRL_COLOR_SPACE_YCbCr444 = 2 + +# +# NV_CTRL_COLOR_RANGE - This option controls the preferred color range of the +# video signal. +# +# If the current color space requires it, the actual color range will be +# limited. +# +# NV_CTRL_CURRENT_COLOR_RANGE will reflect the actual color range in use. +# +NV_CTRL_COLOR_RANGE = 349 # RWDG +NV_CTRL_COLOR_RANGE_FULL = 0 +NV_CTRL_COLOR_RANGE_LIMITED = 1 + +# +# NV_CTRL_GPU_SCALING_DEFAULT_TARGET - not supported +# + +NV_CTRL_GPU_SCALING_DEFAULT_TARGET = 350 # not supported + +# +# NV_CTRL_GPU_SCALING_DEFAULT_METHOD - not supported +# + +NV_CTRL_GPU_SCALING_DEFAULT_METHOD = 351 # not supported + +# +# NV_CTRL_DITHERING_MODE - Controls the dithering mode, when +# NV_CTRL_CURRENT_DITHERING is Enabled. +# +# AUTO: allow the driver to choose the dithering mode automatically. +# +# DYNAMIC_2X2: use a 2x2 matrix to dither from the GPU's pixel +# pipeline to the bit depth of the flat panel. The matrix values +# are changed from frame to frame. +# +# STATIC_2X2: use a 2x2 matrix to dither from the GPU's pixel +# pipeline to the bit depth of the flat panel. The matrix values +# do not change from frame to frame. +# +# TEMPORAL: use a pseudorandom value from a uniform distribution calculated at +# every pixel to achieve stochastic dithering. This method produces a better +# visual result than 2x2 matrix approaches. +# +NV_CTRL_DITHERING_MODE = 352 # RWDG +NV_CTRL_DITHERING_MODE_AUTO = 0 +NV_CTRL_DITHERING_MODE_DYNAMIC_2X2 = 1 +NV_CTRL_DITHERING_MODE_STATIC_2X2 = 2 +NV_CTRL_DITHERING_MODE_TEMPORAL = 3 + +# +# NV_CTRL_CURRENT_DITHERING - Returns the current dithering state. +# +NV_CTRL_CURRENT_DITHERING = 353 # R-DG +NV_CTRL_CURRENT_DITHERING_DISABLED = 0 +NV_CTRL_CURRENT_DITHERING_ENABLED = 1 + +# +# NV_CTRL_CURRENT_DITHERING_MODE - Returns the current dithering +# mode. +# +NV_CTRL_CURRENT_DITHERING_MODE = 354 # R-DG +NV_CTRL_CURRENT_DITHERING_MODE_NONE = 0 +NV_CTRL_CURRENT_DITHERING_MODE_DYNAMIC_2X2 = 1 +NV_CTRL_CURRENT_DITHERING_MODE_STATIC_2X2 = 2 +NV_CTRL_CURRENT_DITHERING_MODE_TEMPORAL = 3 + +# +# NV_CTRL_THERMAL_SENSOR_READING - Returns the thermal sensor's current +# reading. +# +NV_CTRL_THERMAL_SENSOR_READING = 355 # R--S + +# +# NV_CTRL_THERMAL_SENSOR_PROVIDER - Returns the hardware device that +# provides the thermal sensor. +# +NV_CTRL_THERMAL_SENSOR_PROVIDER = 356 # R--S +NV_CTRL_THERMAL_SENSOR_PROVIDER_NONE = 0 +NV_CTRL_THERMAL_SENSOR_PROVIDER_GPU_INTERNAL = 1 +NV_CTRL_THERMAL_SENSOR_PROVIDER_ADM1032 = 2 +NV_CTRL_THERMAL_SENSOR_PROVIDER_ADT7461 = 3 +NV_CTRL_THERMAL_SENSOR_PROVIDER_MAX6649 = 4 +NV_CTRL_THERMAL_SENSOR_PROVIDER_MAX1617 = 5 +NV_CTRL_THERMAL_SENSOR_PROVIDER_LM99 = 6 +NV_CTRL_THERMAL_SENSOR_PROVIDER_LM89 = 7 +NV_CTRL_THERMAL_SENSOR_PROVIDER_LM64 = 8 +NV_CTRL_THERMAL_SENSOR_PROVIDER_G781 = 9 +NV_CTRL_THERMAL_SENSOR_PROVIDER_ADT7473 = 10 +NV_CTRL_THERMAL_SENSOR_PROVIDER_SBMAX6649 = 11 +NV_CTRL_THERMAL_SENSOR_PROVIDER_VBIOSEVT = 12 +NV_CTRL_THERMAL_SENSOR_PROVIDER_OS = 13 +NV_CTRL_THERMAL_SENSOR_PROVIDER_UNKNOWN = 0xFFFFFFFF + +# +# NV_CTRL_THERMAL_SENSOR_TARGET - Returns what hardware component +# the thermal sensor is measuring. +# +NV_CTRL_THERMAL_SENSOR_TARGET = 357 # R--S +NV_CTRL_THERMAL_SENSOR_TARGET_NONE = 0 +NV_CTRL_THERMAL_SENSOR_TARGET_GPU = 1 +NV_CTRL_THERMAL_SENSOR_TARGET_MEMORY = 2 +NV_CTRL_THERMAL_SENSOR_TARGET_POWER_SUPPLY = 4 +NV_CTRL_THERMAL_SENSOR_TARGET_BOARD = 8 +NV_CTRL_THERMAL_SENSOR_TARGET_UNKNOWN = 0xFFFFFFFF + +# +# NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR - when TRUE, OpenGL will +# draw information about the current MULTIGPU mode. +# +NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR = 358 # RW-X +NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR_FALSE = 0 +NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR_TRUE = 1 + +# +# NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS - Returns GPU's processor +# clock freqs. +# +NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS = 359 # RW-G + +# +# NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS - query the flags (various information +# for the specified NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be +# queried with existing interfaces, the video format should be specified +# in the display_mask field; eg: +# +# XNVCTRLQueryTargetAttribute(dpy, +# NV_CTRL_TARGET_TYPE_GVI, +# gvi, +# NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296, +# NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS, +# &flags); +# +# Note: The NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC flag is set +# for those 1080P 3G modes (level A and B) that do not support +# 12 bits per component (when configuring a GVI stream.) +# + +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS = 360 # R--I +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_NONE = 0x00000000 +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_INTERLACED = 0x00000001 +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PROGRESSIVE = 0x00000002 +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PSF = 0x00000004 +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A = 0x00000008 +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B = 0x00000010 +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G = NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A | NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B +NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC = 0x00000020 + +# +# NV_CTRL_GPU_PCIE_MAX_LINK_SPEED - returns maximum PCIe link speed, +# in gigatransfers per second (GT/s). +# + +NV_CTRL_GPU_PCIE_MAX_LINK_SPEED = 361 # R--GI + +# +# NV_CTRL_3D_VISION_PRO_RESET_TRANSCEIVER_TO_FACTORY_SETTINGS - Resets the +# 3D Vision Pro transceiver to its factory settings. +# +NV_CTRL_3D_VISION_PRO_RESET_TRANSCEIVER_TO_FACTORY_SETTINGS = 363 # -W-T + +# +# NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL - Controls the channel that is +# currently used by the 3D Vision Pro transceiver. +# +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL = 364 # RW-T + +# +# NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE - Controls the mode in which the +# 3D Vision Pro transceiver operates. +# NV_CTRL_3D_VISION_PRO_TM_LOW_RANGE is bidirectional +# NV_CTRL_3D_VISION_PRO_TM_MEDIUM_RANGE is bidirectional +# NV_CTRL_3D_VISION_PRO_TM_HIGH_RANGE may be bidirectional just up to a +# given range, and unidirectional beyond it +# NV_CTRL_3D_VISION_PRO_TM_COUNT is the total number of +# 3D Vision Pro transceiver modes +# +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE = 365 # RW-T +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_INVALID = 0 +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_LOW_RANGE = 1 +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_MEDIUM_RANGE = 2 +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_HIGH_RANGE = 3 +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_COUNT = 4 + +# +# NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES - controls whether updates to the color +# lookup table (LUT) are synchronous with respect to X rendering. For example, +# if an X client sends XStoreColors followed by XFillRectangle, the driver will +# guarantee that the FillRectangle request is not processed until after the +# updated LUT colors are actually visible on the screen if +# NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES is enabled. Otherwise, the rendering may +# occur first. +# +# This makes a difference for applications that use the LUT to animate, such as +# XPilot. If you experience flickering in applications that use LUT +# animations, try enabling this attribute. +# +# When synchronous updates are enabled, XStoreColors requests will be processed +# at your screen's refresh rate. +# + +NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES = 367 # RWDG +NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES_DISABLE = 0 +NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES_ENABLE = 1 + +# +# NV_CTRL_DITHERING_DEPTH - Controls the dithering depth when +# NV_CTRL_CURRENT_DITHERING is ENABLED. Some displays connected +# to the GPU via the DVI or LVDS interfaces cannot display the +# full color range of ten bits per channel, so the GPU will +# dither to either 6 or 8 bits per channel. +# +NV_CTRL_DITHERING_DEPTH = 368 # RWDG +NV_CTRL_DITHERING_DEPTH_AUTO = 0 +NV_CTRL_DITHERING_DEPTH_6_BITS = 1 +NV_CTRL_DITHERING_DEPTH_8_BITS = 2 + +# +# NV_CTRL_CURRENT_DITHERING_DEPTH - Returns the current dithering +# depth value. +# +NV_CTRL_CURRENT_DITHERING_DEPTH = 369 # R-DG +NV_CTRL_CURRENT_DITHERING_DEPTH_NONE = 0 +NV_CTRL_CURRENT_DITHERING_DEPTH_6_BITS = 1 +NV_CTRL_CURRENT_DITHERING_DEPTH_8_BITS = 2 + +# +# NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_FREQUENCY - Returns the +# frequency of the channel(in kHz) of the 3D Vision Pro transceiver. +# Use the display_mask parameter to specify the channel number. +# +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_FREQUENCY = 370 # R--T + +# +# NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_QUALITY - Returns the +# quality of the channel(in percentage) of the 3D Vision Pro transceiver. +# Use the display_mask parameter to specify the channel number. +# +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_QUALITY = 371 # R--T + +# +# NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_COUNT - Returns the number of +# channels on the 3D Vision Pro transceiver. +# +NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_COUNT = 372 # R--T + +# +# NV_CTRL_3D_VISION_PRO_PAIR_GLASSES - Puts the 3D Vision Pro +# transceiver into pairing mode to gather additional glasses. +# NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_STOP - stops any pairing +# NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON - starts continuous +# pairing via beacon mode +# Any other value, N - Puts the 3D Vision Pro transceiver into +# authenticated pairing mode for N seconds. +# +NV_CTRL_3D_VISION_PRO_PAIR_GLASSES = 373 # -W-T +NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_STOP = 0 +NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON = 0xFFFFFFFF + +# +# NV_CTRL_3D_VISION_PRO_UNPAIR_GLASSES - Tells a specific pair +# of glasses to unpair. The glasses will "forget" the address +# of the 3D Vision Pro transceiver to which they have been paired. +# To unpair all the currently paired glasses, specify +# the glasses id as 0. +# +NV_CTRL_3D_VISION_PRO_UNPAIR_GLASSES = 374 # -W-T + +# +# NV_CTRL_3D_VISION_PRO_DISCOVER_GLASSES - Tells the 3D Vision Pro +# transceiver about the glasses that have been paired using +# NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON. Unless this is done, +# the 3D Vision Pro transceiver will not know about glasses paired in +# beacon mode. +# +NV_CTRL_3D_VISION_PRO_DISCOVER_GLASSES = 375 # -W-T + +# +# NV_CTRL_3D_VISION_PRO_IDENTIFY_GLASSES - Causes glasses LEDs to +# flash for a short period of time. +# +NV_CTRL_3D_VISION_PRO_IDENTIFY_GLASSES = 376 # -W-T + +# +# NV_CTRL_3D_VISION_PRO_GLASSES_SYNC_CYCLE - Controls the +# sync cycle duration(in milliseconds) of the glasses. +# Use the display_mask parameter to specify the glasses id. +# +NV_CTRL_3D_VISION_PRO_GLASSES_SYNC_CYCLE = 378 # RW-T + +# +# NV_CTRL_3D_VISION_PRO_GLASSES_MISSED_SYNC_CYCLES - Returns the +# number of state sync cycles recently missed by the glasses. +# Use the display_mask parameter to specify the glasses id. +# +NV_CTRL_3D_VISION_PRO_GLASSES_MISSED_SYNC_CYCLES = 379 # R--T + +# +# NV_CTRL_3D_VISION_PRO_GLASSES_BATTERY_LEVEL - Returns the +# battery level(in percentage) of the glasses. +# Use the display_mask parameter to specify the glasses id. +# +NV_CTRL_3D_VISION_PRO_GLASSES_BATTERY_LEVEL = 380 # R--T + +# +# NV_CTRL_GVO_ANC_PARITY_COMPUTATION - Controls the SDI device's computation +# of the parity bit (bit 8) for ANC data words. +# + +NV_CTRL_GVO_ANC_PARITY_COMPUTATION = 381 # RW--- +NV_CTRL_GVO_ANC_PARITY_COMPUTATION_AUTO = 0 +NV_CTRL_GVO_ANC_PARITY_COMPUTATION_ON = 1 +NV_CTRL_GVO_ANC_PARITY_COMPUTATION_OFF = 2 + +# +# NV_CTRL_3D_VISION_PRO_GLASSES_PAIR_EVENT - This attribute is sent +# as an event when glasses get paired in response to pair command +# from any of the clients. +# +NV_CTRL_3D_VISION_PRO_GLASSES_PAIR_EVENT = 382 # ---T + +# +# NV_CTRL_3D_VISION_PRO_GLASSES_UNPAIR_EVENT - This attribute is sent +# as an event when glasses get unpaired in response to unpair command +# from any of the clients. +# +NV_CTRL_3D_VISION_PRO_GLASSES_UNPAIR_EVENT = 383 # ---T + +# +# NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH - returns the current +# PCIe link width, in number of lanes. +# +NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH = 384 # R--GI + +# +# NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED - returns the current +# PCIe link speed, in megatransfers per second (GT/s). +# +NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED = 385 # R--GI + +# +# NV_CTRL_GVO_AUDIO_BLANKING - specifies whether the GVO device should delete +# audio ancillary data packets when frames are repeated. +# +# When a new frame is not ready in time, the current frame, including all +# ancillary data packets, is repeated. When this data includes audio packets, +# this can result in stutters or clicks. When this option is enabled, the GVO +# device will detect when frames are repeated, identify audio ancillary data +# packets, and mark them for deletion. +# +# This option is applied when the GVO device is bound. +# +NV_CTRL_GVO_AUDIO_BLANKING = 386 # RW- +NV_CTRL_GVO_AUDIO_BLANKING_DISABLE = 0 +NV_CTRL_GVO_AUDIO_BLANKING_ENABLE = 1 + +# +# NV_CTRL_CURRENT_METAMODE_ID - switch modes to the MetaMode with +# the specified ID. +# +NV_CTRL_CURRENT_METAMODE_ID = 387 # RW- + +# +# NV_CTRL_DISPLAY_ENABLED - Returns whether or not the display device +# is currently enabled. +# +NV_CTRL_DISPLAY_ENABLED = 388 # R-D +NV_CTRL_DISPLAY_ENABLED_TRUE = 1 +NV_CTRL_DISPLAY_ENABLED_FALSE = 0 + +# +# NV_CTRL_FRAMELOCK_INCOMING_HOUSE_SYNC_RATE: this is the rate +# of an incomming house sync signal to the frame lock board, in milliHz. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN +# target. +# +NV_CTRL_FRAMELOCK_INCOMING_HOUSE_SYNC_RATE = 389 # R--F + +# +# NV_CTRL_FXAA - enables FXAA. A pixel shader based anti- +# aliasing method. +# +NV_CTRL_FXAA = 390 # RW-X +NV_CTRL_FXAA_DISABLE = 0 +NV_CTRL_FXAA_ENABLE = 1 + +# +# NV_CTRL_DISPLAY_RANDR_OUTPUT_ID - the RandR Output ID (type RROutput) +# that corresponds to the specified Display Device target. If a new +# enough version of RandR is not available in the X server, +# DISPLAY_RANDR_OUTPUT_ID will be 0. +# +NV_CTRL_DISPLAY_RANDR_OUTPUT_ID = 391 # R-D- + +# +# NV_CTRL_FRAMELOCK_DISPLAY_CONFIG - Configures whether the display device +# should listen, ignore or drive the framelock sync signal. +# +# Note that whether or not a display device may be set as a client/server +# depends on the current configuration. For example, only one server may be +# set per Quadro Sync device, and displays can only be configured as a client +# if their refresh rate sufficiently matches the refresh rate of the server +# device. +# +# Note that when querying the ValidValues for this data type, the values are +# reported as bits within a bitmask (ATTRIBUTE_TYPE_INT_BITS); +# +NV_CTRL_FRAMELOCK_DISPLAY_CONFIG = 392 # RWD +NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_DISABLED = 0 +NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_CLIENT = 1 +NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_SERVER = 2 + +# +# NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY - Returns the total amount of dedicated +# GPU video memory, in MB, on the specified GPU. This excludes any TurboCache +# padding included in the value returned by NV_CTRL_TOTAL_GPU_MEMORY. +# +NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY = 393 # R--G + +# +# NV_CTRL_USED_DEDICATED_GPU_MEMORY- Returns the amount of video memory +# currently used on the graphics card in MB. +# +NV_CTRL_USED_DEDICATED_GPU_MEMORY = 394 # R--G + +# +# NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE +# Some GPUs can make a tradeoff between double-precision floating-point +# performance and clock speed. Enabling double-precision floating point +# performance may benefit CUDA or OpenGL applications that require high +# bandwidth double-precision performance. Disabling this feature may benefit +# graphics applications that require higher clock speeds. +# +# This attribute is only available when toggling double precision boost +# can be done immediately (without need for a rebooot). +# +NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE = 395 # RW-G +NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE_DISABLED = 0 +NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE_ENABLED = 1 + +# +# NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT +# Some GPUs can make a tradeoff between double-precision floating-point +# performance and clock speed. Enabling double-precision floating point +# performance may benefit CUDA or OpenGL applications that require high +# bandwidth double-precision performance. Disabling this feature may benefit +# graphics applications that require higher clock speeds. +# +# This attribute is only available when toggling double precision boost +# requires a reboot. +# + +NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT = 396 # RW-G +NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT_DISABLED = 0 +NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT_ENALED = 1 + +# +# NV_CTRL_DPY_HDMI_3D - Returns whether the specified display device is +# currently using HDMI 3D Frame Packed Stereo mode. Clients may use this +# to help interpret the refresh rate returned by NV_CTRL_REFRESH_RATE or +# NV_CTRL_REFRESH_RATE_3, which will be doubled when using HDMI 3D mode. +# +# This attribute may be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU target. +# + +NV_CTRL_DPY_HDMI_3D = 397 # R-DG +NV_CTRL_DPY_HDMI_3D_DISABLED = 0 +NV_CTRL_DPY_HDMI_3D_ENABLED = 1 + +# +# NV_CTRL_BASE_MOSAIC - Returns whether Base Mosaic is currently enabled on the +# given GPU. Querying the valid values of this attribute returns capabilities. +# + +NV_CTRL_BASE_MOSAIC = 398 # R--G +NV_CTRL_BASE_MOSAIC_DISABLED = 0 +NV_CTRL_BASE_MOSAIC_FULL = 1 +NV_CTRL_BASE_MOSAIC_LIMITED = 2 + +# +# NV_CTRL_MULTIGPU_MASTER_POSSIBLE - Returns whether the GPU can be configured +# as the master GPU in a Multi GPU configuration (SLI, SLI Mosaic, +# Base Mosaic). +# + +NV_CTRL_MULTIGPU_MASTER_POSSIBLE = 399 # R--G +NV_CTRL_MULTIGPU_MASTER_POSSIBLE_FALSE = 0 +NV_CTRL_MULTIGPU_MASTER_POSSIBLE_TRUE = 1 + +# +# NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE - Returns the default PowerMizer mode +# for the given GPU. +# +NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE = 400 # R--G + +# +# NV_CTRL_XV_SYNC_TO_DISPLAY_ID - When XVideo Sync To VBlank is enabled, this +# controls which display device will be synched to if the display is enabled. +# Returns NV_CTRL_XV_SYNC_TO_DISPLAY_ID_AUTO if no display has been +# selected. +# +NV_CTRL_XV_SYNC_TO_DISPLAY_ID = 401 # RW- +NV_CTRL_XV_SYNC_TO_DISPLAY_ID_AUTO = 0xFFFFFFFF + +# +# NV_CTRL_BACKLIGHT_BRIGHTNESS - The backlight brightness of an internal panel. +# +NV_CTRL_BACKLIGHT_BRIGHTNESS = 402 # RWD- + +# +# NV_CTRL_GPU_LOGO_BRIGHTNESS - Controls brightness +# of the logo on the GPU, if any. The value is variable from 0% - 100%. +# +NV_CTRL_GPU_LOGO_BRIGHTNESS = 403 # RW-G + +# +# NV_CTRL_GPU_SLI_LOGO_BRIGHTNESS - Controls brightness of the logo +# on the SLI bridge, if any. The value is variable from 0% - 100%. +# +NV_CTRL_GPU_SLI_LOGO_BRIGHTNESS = 404 # RW-G + +# +# NV_CTRL_THERMAL_COOLER_SPEED - Returns cooler's current operating speed in +# rotations per minute (RPM). +# + +NV_CTRL_THERMAL_COOLER_SPEED = 405 # R--C + +# +# NV_CTRL_PALETTE_UPDATE_EVENT - The Color Palette has been changed and the +# color correction info needs to be updated. +# + +NV_CTRL_PALETTE_UPDATE_EVENT = 406 # --- + +# +# NV_CTRL_VIDEO_ENCODER_UTILIZATION - Returns the video encoder engine +# utilization as a percentage. +# +NV_CTRL_VIDEO_ENCODER_UTILIZATION = 407 # R--G + +# +# NV_CTRL_GSYNC_ALLOWED - when TRUE, OpenGL will enable G-SYNC when possible; +# when FALSE, OpenGL will always use a fixed monitor refresh rate. +# + +NV_CTRL_GSYNC_ALLOWED = 408 # RW-X +NV_CTRL_GSYNC_ALLOWED_FALSE = 0 +NV_CTRL_GSYNC_ALLOWED_TRUE = 1 + +# +# NV_CTRL_GPU_NVCLOCK_OFFSET - This attribute controls the GPU clock offsets +# (in MHz) used for overclocking per performance level. +# Use the display_mask parameter to specify the performance level. +# +# Note: To enable overclocking support, set the X configuration +# option "Coolbits" to value "8". +# +# This offset can have any integer value between +# NVCTRLAttributeValidValues.u.range.min and +# NVCTRLAttributeValidValues.u.range.max (inclusive). +# +# This attribute is available on GeForce GTX 400 series and later +# Geforce GPUs. +# +NV_CTRL_GPU_NVCLOCK_OFFSET = 409 # RW-G + +# +# NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET - This attribute controls +# the memory transfer rate offsets (in MHz) used for overclocking +# per performance level. +# Use the display_mask parameter to specify the performance level. +# +# Note: To enable overclocking support, set the X configuration +# option "Coolbits" to value "8". +# +# This offset can have any integer value between +# NVCTRLAttributeValidValues.u.range.min and +# NVCTRLAttributeValidValues.u.range.max (inclusive). +# +# This attribute is available on GeForce GTX 400 series and later +# Geforce GPUs. +# +NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET = 410 # RW-G + +# +# NV_CTRL_VIDEO_DECODER_UTILIZATION - Returns the video decoder engine +# utilization as a percentage. +# +NV_CTRL_VIDEO_DECODER_UTILIZATION = 411 # R--G + +# +# NV_CTRL_GPU_OVER_VOLTAGE_OFFSET - This attribute controls +# the overvoltage offset in microvolts (uV). +# +# Note: To enable overvoltage support, set the X configuration +# option "Coolbits" to value "16". +# +# This offset can have any integer value between +# NVCTRLAttributeValidValues.u.range.min and +# NVCTRLAttributeValidValues.u.range.max (inclusive). +# +# This attribute is available on GeForce GTX 400 series and later +# Geforce GPUs. +# + +NV_CTRL_GPU_OVER_VOLTAGE_OFFSET = 412 # RW-G + +# +# NV_CTRL_GPU_CURRENT_CORE_VOLTAGE - This attribute returns the +# GPU's current operating voltage in microvolts (uV). +# +# This attribute is available on GPUs that support +# NV_CTRL_GPU_OVER_VOLTAGE_OFFSET. +# +NV_CTRL_GPU_CURRENT_CORE_VOLTAGE = 413 # R--G + +# +# NV_CTRL_CURRENT_COLOR_SPACE - Returns the current color space of the video +# signal. +# +# This will match NV_CTRL_COLOR_SPACE unless the current mode on this display +# device is an HDMI 2.0 4K@60Hz mode and the display device or GPU does not +# support driving this mode in RGB, in which case YCbCr420 will be returned. +# +NV_CTRL_CURRENT_COLOR_SPACE = 414 # R-DG +NV_CTRL_CURRENT_COLOR_SPACE_RGB = 0 +NV_CTRL_CURRENT_COLOR_SPACE_YCbCr422 = 1 +NV_CTRL_CURRENT_COLOR_SPACE_YCbCr444 = 2 +NV_CTRL_CURRENT_COLOR_SPACE_YCbCr420 = 3 + +# +# NV_CTRL_CURRENT_COLOR_RANGE - Returns the current color range of the video +# signal. +# +NV_CTRL_CURRENT_COLOR_RANGE = 415 # R-DG +NV_CTRL_CURRENT_COLOR_RANGE_FULL = 0 +NV_CTRL_CURRENT_COLOR_RANGE_LIMITED = 1 + +# +# NV_CTRL_SHOW_GSYNC_VISUAL_INDICATOR - when TRUE, OpenGL will indicate when +# G-SYNC is in use for full-screen applications. +# + +NV_CTRL_SHOW_GSYNC_VISUAL_INDICATOR = 416 # RW-X +NV_CTRL_SHOW_GSYNC_VISUAL_INDICATOR_FALSE = 0 +NV_CTRL_SHOW_GSYNC_VISUAL_INDICATOR_TRUE = 1 + +# +# NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL - Returns cooler's current +# operating level. This may fluctuate dynamically. When +# NV_CTRL_GPU_COOLER_MANUAL_CONTROL=TRUE, the driver attempts +# to make this match NV_CTRL_THERMAL_COOLER_LEVEL. When +# NV_CTRL_GPU_COOLER_MANUAL_CONTROL=FALSE, the driver adjusts the +# current level based on the needs of the GPU. +# + +NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL = 417 # R--C + +# +# NV_CTRL_STEREO_SWAP_MODE - This attribute controls the swap mode when +# Quad-Buffered stereo is used. +# NV_CTRL_STEREO_SWAP_MODE_APPLICATION_CONTROL : Stereo swap mode is derived +# from the value of swap interval. +# If it's odd, the per eye swap mode is used. +# If it's even, the per eye pair swap mode is used. +# NV_CTRL_STEREO_SWAP_MODE_PER_EYE : The driver swaps each eye as it is ready. +# NV_CTRL_STEREO_SWAP_MODE_PER_EYE_PAIR : The driver waits for both eyes to +# complete rendering before swapping. +# + +NV_CTRL_STEREO_SWAP_MODE = 418 # RW-X +NV_CTRL_STEREO_SWAP_MODE_APPLICATION_CONTROL = 0 +NV_CTRL_STEREO_SWAP_MODE_PER_EYE = 1 +NV_CTRL_STEREO_SWAP_MODE_PER_EYE_PAIR = 2 + +# +# NV_CTRL_CURRENT_XV_SYNC_TO_DISPLAY_ID - When XVideo Sync To VBlank is +# enabled, this returns the display id of the device currently synched to. +# Returns NV_CTRL_XV_SYNC_TO_DISPLAY_ID_AUTO if no display is currently +# set. +# + +NV_CTRL_CURRENT_XV_SYNC_TO_DISPLAY_ID = 419 # R-- + +# +# NV_CTRL_GPU_FRAMELOCK_FIRMWARE_UNSUPPORTED - Returns true if the +# Quadro Sync card connected to this GPU has a firmware version incompatible +# with this GPU. +# + +NV_CTRL_GPU_FRAMELOCK_FIRMWARE_UNSUPPORTED = 420 # R--G +NV_CTRL_GPU_FRAMELOCK_FIRMWARE_UNSUPPORTED_FALSE = 0 +NV_CTRL_GPU_FRAMELOCK_FIRMWARE_UNSUPPORTED_TRUE = 1 + +# +# NV_CTRL_DISPLAYPORT_CONNECTOR_TYPE - Returns the connector type used by +# a DisplayPort display. +# + +NV_CTRL_DISPLAYPORT_CONNECTOR_TYPE = 421 # R-DG +NV_CTRL_DISPLAYPORT_CONNECTOR_TYPE_UNKNOWN = 0 +NV_CTRL_DISPLAYPORT_CONNECTOR_TYPE_DISPLAYPORT = 1 +NV_CTRL_DISPLAYPORT_CONNECTOR_TYPE_HDMI = 2 +NV_CTRL_DISPLAYPORT_CONNECTOR_TYPE_DVI = 3 +NV_CTRL_DISPLAYPORT_CONNECTOR_TYPE_VGA = 4 + +# +# NV_CTRL_DISPLAYPORT_IS_MULTISTREAM - Returns multi-stream support for +# DisplayPort displays. +# +NV_CTRL_DISPLAYPORT_IS_MULTISTREAM = 422 # R-DG + +# +# NV_CTRL_DISPLAYPORT_SINK_IS_AUDIO_CAPABLE - Returns whether a DisplayPort +# device supports audio. +# +NV_CTRL_DISPLAYPORT_SINK_IS_AUDIO_CAPABLE = 423 # R-DG + +# +# NV_CTRL_GPU_NVCLOCK_OFFSET_ALL_PERFORMANCE_LEVELS - This attribute +# controls the GPU clock offsets (in MHz) used for overclocking. +# The offset is applied to all performance levels. +# +# Note: To enable overclocking support, set the X configuration +# option "Coolbits" to value "8". +# +# This offset can have any integer value between +# NVCTRLAttributeValidValues.u.range.min and +# NVCTRLAttributeValidValues.u.range.max (inclusive). +# +# This attribute is available on GeForce GTX 1000 series and later +# Geforce GPUs. +# +NV_CTRL_GPU_NVCLOCK_OFFSET_ALL_PERFORMANCE_LEVELS = 424 # RW-G + +# +# NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS - This +# attribute controls the memory transfer rate offsets (in MHz) used +# for overclocking. The offset is applied to all performance levels. +# +# Note: To enable overclocking support, set the X configuration +# option "Coolbits" to value "8". +# +# This offset can have any integer value between +# NVCTRLAttributeValidValues.u.range.min and +# NVCTRLAttributeValidValues.u.range.max (inclusive). +# +# This attribute is available on GeForce GTX 1000 series and later +# Geforce GPUs. +# +NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET_ALL_PERFORMANCE_LEVELS = 425 # RW-G + +# +# NV_CTRL_FRAMELOCK_FIRMWARE_VERSION - Queries the firmware major version of +# the Frame Lock device. +# +# This attribute must be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK target. +# + +NV_CTRL_FRAMELOCK_FIRMWARE_VERSION = 426 # R--F + +# +# NV_CTRL_FRAMELOCK_FIRMWARE_MINOR_VERSION - Queries the firmware minor +# version of the Frame Lock device. +# +# This attribute must be queried through XNVCTRLQueryTargetAttribute() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK target. +# + +NV_CTRL_FRAMELOCK_FIRMWARE_MINOR_VERSION = 427 # R--F + +# +# NV_CTRL_SHOW_GRAPHICS_VISUAL_INDICATOR - when TRUE, graphics APIs will +# indicate various runtime information such as flip/blit, vsync status, API +# in use. +# + +NV_CTRL_SHOW_GRAPHICS_VISUAL_INDICATOR = 428 # RW-X +NV_CTRL_SHOW_GRAPHICS_VISUAL_INDICATOR_FALSE = 0 +NV_CTRL_SHOW_GRAPHICS_VISUAL_INDICATOR_TRUE = 1 + +NV_CTRL_LAST_ATTRIBUTE = NV_CTRL_SHOW_GRAPHICS_VISUAL_INDICATOR + +############################################################################ + +# +# String Attributes: +# +# String attributes can be queryied through the XNVCTRLQueryStringAttribute() +# and XNVCTRLQueryTargetStringAttribute() function calls. +# +# String attributes can be set through the XNVCTRLSetStringAttribute() +# function call. (There are currently no string attributes that can be +# set on non-X Screen targets.) +# +# Unless otherwise noted, all string attributes can be queried/set using an +# NV_CTRL_TARGET_TYPE_X_SCREEN target. Attributes that cannot take an +# NV_CTRL_TARGET_TYPE_X_SCREEN target also cannot be queried/set through +# XNVCTRLQueryStringAttribute()/XNVCTRLSetStringAttribute() (Since +# these assume an X Screen target). +# + + +# +# NV_CTRL_STRING_PRODUCT_NAME - the product name on which the +# specified X screen is running, or the product name of the specified +# Frame Lock device. +# +# This attribute may be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target to +# return the product name of the GPU, or a NV_CTRL_TARGET_TYPE_FRAMELOCK to +# return the product name of the Frame Lock device. +# + +NV_CTRL_STRING_PRODUCT_NAME = 0 # R--GF + +# +# NV_CTRL_STRING_VBIOS_VERSION - the video bios version on the GPU on +# which the specified X screen is running. +# + +NV_CTRL_STRING_VBIOS_VERSION = 1 # R--G + +# +# NV_CTRL_STRING_NVIDIA_DRIVER_VERSION - string representation of the +# NVIDIA driver version number for the NVIDIA X driver in use. +# + +NV_CTRL_STRING_NVIDIA_DRIVER_VERSION = 3 # R--G + +# +# NV_CTRL_STRING_DISPLAY_DEVICE_NAME - name of the display device +# specified in the display_mask argument. +# +# This attribute may be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_STRING_DISPLAY_DEVICE_NAME = 4 # R-DG + +# +# NV_CTRL_STRING_TV_ENCODER_NAME - not supported +# + +NV_CTRL_STRING_TV_ENCODER_NAME = 5 # not supported + +# +# NV_CTRL_STRING_GVIO_FIRMWARE_VERSION - indicates the version of the +# Firmware on the GVIO device. +# + +NV_CTRL_STRING_GVIO_FIRMWARE_VERSION = 8 # R--I + +# +# NV_CTRL_STRING_GVO_FIRMWARE_VERSION - renamed +# +# NV_CTRL_STRING_GVIO_FIRMWARE_VERSION should be used instead. +# +NV_CTRL_STRING_GVO_FIRMWARE_VERSION = 8 # renamed + +# +# NV_CTRL_STRING_CURRENT_MODELINE - Return the ModeLine currently +# being used by the specified display device. +# +# This attribute may be queried through XNVCTRLQueryTargetStringAttribute() +# using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# +# The ModeLine string may be prepended with a comma-separated list of +# "token=value" pairs, separated from the ModeLine string by "::". +# This "token=value" syntax is the same as that used in +# NV_CTRL_BINARY_DATA_MODELINES +# + +NV_CTRL_STRING_CURRENT_MODELINE = 9 # R-DG + +# +# NV_CTRL_STRING_ADD_MODELINE - Adds a ModeLine to the specified +# display device. The ModeLine is not added if validation fails. +# +# The ModeLine string should have the same syntax as a ModeLine in +# the X configuration file; e.g., +# +# "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +HSync +VSync +# + +NV_CTRL_STRING_ADD_MODELINE = 10 # -WDG + +# +# NV_CTRL_STRING_DELETE_MODELINE - Deletes an existing ModeLine +# from the specified display device. The currently selected +# ModeLine cannot be deleted. (This also means you cannot delete +# the last ModeLine.) +# +# The ModeLine string should have the same syntax as a ModeLine in +# the X configuration file; e.g., +# +# "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +HSync +VSync +# + +NV_CTRL_STRING_DELETE_MODELINE = 11 # -WDG + +# +# NV_CTRL_STRING_CURRENT_METAMODE - Returns the metamode currently +# being used by the specified X screen. The MetaMode string has the +# same syntax as the MetaMode X configuration option, as documented +# in the NVIDIA driver README. +# +# The returned string may be prepended with a comma-separated list of +# "token=value" pairs, separated from the MetaMode string by "::". +# This "token=value" syntax is the same as that used in +# NV_CTRL_BINARY_DATA_METAMODES. +# + +NV_CTRL_STRING_CURRENT_METAMODE = 12 # RW-- +NV_CTRL_STRING_CURRENT_METAMODE_VERSION_1 = NV_CTRL_STRING_CURRENT_METAMODE + +# +# NV_CTRL_STRING_ADD_METAMODE - Adds a MetaMode to the specified +# X Screen. +# +# It is recommended to not use this attribute, but instead use +# NV_CTRL_STRING_OPERATION_ADD_METAMODE. +# + +NV_CTRL_STRING_ADD_METAMODE = 13 # -W-- + +# +# NV_CTRL_STRING_DELETE_METAMODE - Deletes an existing MetaMode from +# the specified X Screen. The currently selected MetaMode cannot be +# deleted. (This also means you cannot delete the last MetaMode). +# The MetaMode string should have the same syntax as the MetaMode X +# configuration option, as documented in the NVIDIA driver README. +# + +NV_CTRL_STRING_DELETE_METAMODE = 14 # -WD-- + +# +# NV_CTRL_STRING_VCSC_PRODUCT_NAME - deprecated +# +# Queries the product name of the VCSC device. +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# + +NV_CTRL_STRING_VCSC_PRODUCT_NAME = 15 # R---V + +# +# NV_CTRL_STRING_VCSC_PRODUCT_ID - deprecated +# +# Queries the product ID of the VCSC device. +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# + +NV_CTRL_STRING_VCSC_PRODUCT_ID = 16 # R---V + +# +# NV_CTRL_STRING_VCSC_SERIAL_NUMBER - deprecated +# +# Queries the unique serial number of the VCS device. +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# + +NV_CTRL_STRING_VCSC_SERIAL_NUMBER = 17 # R---V + +# +# NV_CTRL_STRING_VCSC_BUILD_DATE - deprecated +# +# Queries the date of the VCS device. the returned string is in the following +# format: "Week.Year" +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# + +NV_CTRL_STRING_VCSC_BUILD_DATE = 18 # R---V + +# +# NV_CTRL_STRING_VCSC_FIRMWARE_VERSION - deprecated +# +# Queries the firmware version of the VCS device. +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# + +NV_CTRL_STRING_VCSC_FIRMWARE_VERSION = 19 # R---V + +# +# NV_CTRL_STRING_VCSC_FIRMWARE_REVISION - deprecated +# +# Queries the firmware revision of the VCS device. +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCS target. +# + +NV_CTRL_STRING_VCSC_FIRMWARE_REVISION = 20 # R---V + +# +# NV_CTRL_STRING_VCSC_HARDWARE_VERSION - deprecated +# +# Queries the hardware version of the VCS device. +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# + +NV_CTRL_STRING_VCSC_HARDWARE_VERSION = 21 # R---V + +# +# NV_CTRL_STRING_VCSC_HARDWARE_REVISION - deprecated +# +# Queries the hardware revision of the VCS device. +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# + +NV_CTRL_STRING_VCSC_HARDWARE_REVISION = 22 # R---V + +# +# NV_CTRL_STRING_MOVE_METAMODE - Moves a MetaMode to the specified +# index location. The MetaMode must already exist in the X Screen's +# list of MetaModes (as returned by the NV_CTRL_BINARY_DATA_METAMODES +# attribute). If the index is larger than the number of MetaModes in +# the list, the MetaMode is moved to the end of the list. The +# MetaMode string should have the same syntax as the MetaMode X +# configuration option, as documented in the NVIDIA driver README. + +# The MetaMode string must be prepended with a comma-separated list +# of "token=value" pairs, separated from the MetaMode string by "::". +# Currently, the only valid token is "index", which indicates where +# in the MetaMode list the MetaMode should be moved to. +# +# Other tokens may be added in the future. +# +# E.g., +# "index=5 :: CRT-0: 1024x768 @1024x768 +0+0" +# + +NV_CTRL_STRING_MOVE_METAMODE = 23 # -W-- + +# +# NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES - returns the valid +# horizontal sync ranges used to perform mode validation for the +# specified display device. The ranges are in the same format as the +# "HorizSync" X config option: +# +# "horizsync-range may be a comma separated list of either discrete +# values or ranges of values. A range of values is two values +# separated by a dash." +# +# The values are in kHz. +# +# Additionally, the string may be prepended with a comma-separated +# list of "token=value" pairs, separated from the HorizSync string by +# "::". Valid tokens: +# +# Token Value +# "source" "edid" - HorizSync is from the display device's EDID +# "xconfig" - HorizSync is from the "HorizSync" entry in +# the Monitor section of the X config file +# "option" - HorizSync is from the "HorizSync" NVIDIA X +# config option +# "builtin" - HorizSync is from NVIDIA X driver builtin +# default values +# +# Additional tokens and/or values may be added in the future. +# +# Example: "source=edid :: 30.000-62.000" +# + +NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES = 24 # R-DG + +# +# NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES - returns the valid +# vertical refresh ranges used to perform mode validation for the +# specified display device. The ranges are in the same format as the +# "VertRefresh" X config option: +# +# "vertrefresh-range may be a comma separated list of either discrete +# values or ranges of values. A range of values is two values +# separated by a dash." +# +# The values are in Hz. +# +# Additionally, the string may be prepended with a comma-separated +# list of "token=value" pairs, separated from the VertRefresh string by +# "::". Valid tokens: +# +# Token Value +# "source" "edid" - VertRefresh is from the display device's EDID +# "xconfig" - VertRefresh is from the "VertRefresh" entry in +# the Monitor section of the X config file +# "option" - VertRefresh is from the "VertRefresh" NVIDIA X +# config option +# "builtin" - VertRefresh is from NVIDIA X driver builtin +# default values +# +# Additional tokens and/or values may be added in the future. +# +# Example: "source=edid :: 50.000-75.000" +# + +NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES = 25 # R-DG + +# +# NV_CTRL_STRING_SCREEN_RECTANGLE - returns the physical X Screen's +# initial position and size (in absolute coordinates) within the +# desktop as the "token=value" string: "x=#, y=#, width=#, height=#" +# +# Querying this attribute returns success only when Xinerama is enabled +# or the X server ABI is greater than equal to 12. +# + +NV_CTRL_STRING_SCREEN_RECTANGLE = 26 # R--- + +# +# NV_CTRL_STRING_XINERAMA_SCREEN_INFO - renamed +# +# NV_CTRL_STRING_SCREEN_RECTANGLE should be used instead. +# + +NV_CTRL_STRING_XINERAMA_SCREEN_INFO = 26 # renamed + +# +# NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER - used to specify the +# order that display devices will be returned via Xinerama when +# nvidiaXineramaInfo is enabled. Follows the same syntax as the +# nvidiaXineramaInfoOrder X config option. +# + +NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER = 27 # RW-- + +NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER = NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER # for backwards compatibility: + +# +# NV_CTRL_STRING_SLI_MODE - returns a string describing the current +# SLI mode, if any, or FALSE if SLI is not currently enabled. +# +# This string should be used for informational purposes only, and +# should not be used to distinguish between SLI modes, other than to +# recognize when SLI is disabled (FALSE is returned) or +# enabled (the returned string is non-NULL and describes the current +# SLI configuration). +# + +NV_CTRL_STRING_SLI_MODE = 28 # R---*/ + +# +# NV_CTRL_STRING_PERFORMANCE_MODES - returns a string with all the +# performance modes defined for this GPU along with their associated +# NV Clock and Memory Clock values. +# Not all tokens will be reported on all GPUs, and additional tokens +# may be added in the future. +# For backwards compatibility we still provide nvclock, memclock, and +# processorclock those are the same as nvclockmin, memclockmin and +# processorclockmin. +# +# Note: These clock values take into account the offset +# set by clients through NV_CTRL_GPU_NVCLOCK_OFFSET and +# NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET. +# +# Each performance modes are returned as a comma-separated list of +# "token=value" pairs. Each set of performance mode tokens are separated +# by a ";". Valid tokens: +# +# Token Value +# "perf" integer - the Performance level +# "nvclock" integer - the GPU clocks (in MHz) for the perf level +# "nvclockmin" integer - the GPU clocks min (in MHz) for the perf level +# "nvclockmax" integer - the GPU clocks max (in MHz) for the perf level +# "nvclockeditable" integer - if the GPU clock domain is editable +# for the perf level +# "memclock" integer - the memory clocks (in MHz) for the perf level +# "memclockmin" integer - the memory clocks min (in MHz) for the perf level +# "memclockmax" integer - the memory clocks max (in MHz) for the perf level +# "memclockeditable" integer - if the memory clock domain is editable +# for the perf level +# "memtransferrate" integer - the memory transfer rate (in MHz) +# for the perf level +# "memtransferratemin" integer - the memory transfer rate min (in MHz) +# for the perf level +# "memtransferratemax" integer - the memory transfer rate max (in MHz) +# for the perf level +# "memtransferrateeditable" integer - if the memory transfer rate is editable +# for the perf level +# "processorclock" integer - the processor clocks (in MHz) +# for the perf level +# "processorclockmin" integer - the processor clocks min (in MHz) +# for the perf level +# "processorclockmax" integer - the processor clocks max (in MHz) +# for the perf level +# "processorclockeditable" integer - if the processor clock domain is editable +# for the perf level +# +# Example: +# +# perf=0, nvclock=324, nvclockmin=324, nvclockmax=324, nvclockeditable=0, +# memclock=324, memclockmin=324, memclockmax=324, memclockeditable=0, +# memtransferrate=648, memtransferratemin=648, memtransferratemax=648, +# memtransferrateeditable=0 ; +# perf=1, nvclock=324, nvclockmin=324, nvclockmax=640, nvclockeditable=0, +# memclock=810, memclockmin=810, memclockmax=810, memclockeditable=0, +# memtransferrate=1620, memtransferrate=1620, memtransferrate=1620, +# memtransferrateeditable=0 ; +# +# This attribute may be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_STRING_PERFORMANCE_MODES = 29 # R--G + +# +# NV_CTRL_STRING_VCSC_FAN_STATUS - deprecated +# +# Returns a string with status of all the fans in the Visual Computing System, +# if such a query is supported. Fan information is reported along with its +# tachometer reading (in RPM) and a flag indicating whether the fan has failed +# or not. +# +# Valid tokens: +# +# Token Value +# "fan" integer - the Fan index +# "speed" integer - the tachometer reading of the fan in rpm +# "fail" integer - flag to indicate whether the fan has failed +# +# Example: +# +# fan=0, speed=694, fail=0 ; fan=1, speed=693, fail=0 +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# +# + +NV_CTRL_STRING_VCSC_FAN_STATUS = 30 # R---V + +# +# NV_CTRL_STRING_VCSC_TEMPERATURES - Deprecated +# +# Returns a string with all Temperature readings in the Visual Computing +# System, if such a query is supported. Intake, Exhaust and Board Temperature +# values are reported in Celcius. +# +# Valid tokens: +# +# Token Value +# "intake" integer - the intake temperature for the VCS +# "exhaust" integer - the exhaust temperature for the VCS +# "board" integer - the board temperature of the VCS +# +# Example: +# +# intake=29, exhaust=46, board=41 +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# +# + +NV_CTRL_STRING_VCSC_TEMPERATURES = 31 # R---V + +# +# NV_CTRL_STRING_VCSC_PSU_INFO - Deprecated +# +# Returns a string with all Power Supply Unit related readings in the Visual +# Computing System, if such a query is supported. Current in amperes, Power +# in watts, Voltage in volts and PSU state may be reported. Not all PSU types +# support all of these values, and therefore some readings may be unknown. +# +# Valid tokens: +# +# Token Value +# "current" integer - the current drawn in amperes by the VCS +# "power" integer - the power drawn in watts by the VCS +# "voltage" integer - the voltage reading of the VCS +# "state" integer - flag to indicate whether PSU is operating normally +# +# Example: +# +# current=10, power=15, voltage=unknown, state=normal +# +# This attribute must be queried through XNVCTRLQueryTargetStringAttribute() +# using a NV_CTRL_TARGET_TYPE_VCSC target. +# +# + + +NV_CTRL_STRING_VCSC_PSU_INFO = 32 # R---V + +# +# NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME - query the name for the specified +# NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be queried with existing +# interfaces, XNVCTRLQueryStringAttribute() should be used, and the video +# format specified in the display_mask field; eg: +# +# XNVCTRLQueryStringAttribute(dpy, +# screen, +# NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296, +# NV_CTRL_GVIO_VIDEO_FORMAT_NAME, +# &name); +# + +NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME = 33 # R--GI + +# +# NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME - renamed +# +# NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME should be used instead. +# +NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME = 33 # renamed + +# +# NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS - returns a string with the +# associated NV Clock, Memory Clock and Processor Clock values. +# +# Current valid tokens are "nvclock", "nvclockmin", "nvclockmax", +# "memclock", "memclockmin", "memclockmax", "processorclock", +# "processorclockmin" and "processorclockmax". +# Not all tokens will be reported on all GPUs, and additional tokens +# may be added in the future. +# +# Note: These clock values take into account the offset +# set by clients through NV_CTRL_GPU_NVCLOCK_OFFSET and +# NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET. +# +# Clock values are returned as a comma-separated list of +# "token=value" pairs. +# Valid tokens: +# +# Token Value +# "nvclock" integer - the GPU clocks (in MHz) for the perf level +# "nvclockmin" integer - the GPU clocks min (in MHz) for the perf level +# "nvclockmax" integer - the GPU clocks max (in MHz) for the perf level +# "nvclockeditable" integer - if the GPU clock domain is editable +# for the perf level +# "memclock" integer - the memory clocks (in MHz) for the perf level +# "memclockmin" integer - the memory clocks min (in MHz) for the perf level +# "memclockmax" integer - the memory clocks (max in MHz) for the perf level +# "memclockeditable" integer - if the memory clock domain is editable +# for the perf level +# "memtransferrate" integer - the memory transfer rate (in MHz) +# for the perf level +# "memtransferratemin" integer - the memory transfer rate min (in MHz) +# for the perf level +# "memtransferratemax" integer - the memory transfer rate max (in MHz) +# for the perf level +# "memtransferrateeditable" integer - if the memory transfer rate is editable +# for the perf level +# "processorclock" integer - the processor clocks (in MHz) +# for the perf level +# "processorclockmin" integer - the processor clocks min (in MHz) +# for the perf level +# "processorclockmax" integer - the processor clocks max (in MHz) +# for the perf level +# "processorclockeditable" integer - if the processor clock domain is editable +# for the perf level +# +# Example: +# +# nvclock=324, nvclockmin=324, nvclockmax=324, nvclockeditable=0 +# memclock=324, memclockmin=324, memclockmax=324, memclockeditable=0 +# memtrasferrate=628 +# +# This attribute may be queried through XNVCTRLQueryTargetStringAttribute() +# using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS = 34 # RW-G + +# +# NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_HARDWARE_REVISION - Returns the +# hardware revision of the 3D Vision Pro transceiver. +# +NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_HARDWARE_REVISION = 35 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_A - Returns the +# firmware version of chip A of the 3D Vision Pro transceiver. +# +NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_A = 36 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_A - Returns the +# date of the firmware of chip A of the 3D Vision Pro transceiver. +# +NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_A = 37 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_B - Returns the +# firmware version of chip B of the 3D Vision Pro transceiver. +# +NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_B = 38 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_B - Returns the +# date of the firmware of chip B of the 3D Vision Pro transceiver. +# +NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_B = 39 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_ADDRESS - Returns the RF address +# of the 3D Vision Pro transceiver. +# +NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_ADDRESS = 40 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_VERSION_A - Returns the +# firmware version of chip A of the glasses. +# Use the display_mask parameter to specify the glasses id. +# +NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_VERSION_A = 41 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_DATE_A - Returns the +# date of the firmware of chip A of the glasses. +# Use the display_mask parameter to specify the glasses id. +# +NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_DATE_A = 42 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_GLASSES_ADDRESS - Returns the RF address +# of the glasses. +# Use the display_mask parameter to specify the glasses id. +# +NV_CTRL_STRING_3D_VISION_PRO_GLASSES_ADDRESS = 43 # R--T + +# +# NV_CTRL_STRING_3D_VISION_PRO_GLASSES_NAME - Controls the name the +# glasses should use. +# Use the display_mask parameter to specify the glasses id. +# Glasses' name should start and end with an alpha-numeric character. +# +NV_CTRL_STRING_3D_VISION_PRO_GLASSES_NAME = 44 # RW-T + +# +# NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2 - Returns the metamode currently +# being used by the specified X screen. The MetaMode string has the same +# syntax as the MetaMode X configuration option, as documented in the NVIDIA +# driver README. Also, see NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 for more +# details on the base syntax. +# +# The returned string may also be prepended with a comma-separated list of +# "token=value" pairs, separated from the MetaMode string by "::". +# +NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2 = 45 # RW-- + +# +# NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME - Returns a type name for the +# display device ("CRT", "DFP", or "TV"). However, note that the determination +# of the name is based on the protocol through which the X driver communicates +# to the display device. E.g., if the driver communicates using VGA ,then the +# basename is "CRT"; if the driver communicates using TMDS, LVDS, or DP, then +# the name is "DFP". +# +NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME = 46 # R-D- + +# +# NV_CTRL_STRING_DISPLAY_NAME_TYPE_ID - Returns the type-based name + ID for +# the display device, e.g. "CRT-0", "DFP-1", "TV-2". If this device is a +# DisplayPort multistream device, then this name will also be prepended with the +# device's port address like so: "DFP-1.0.1.2.3". See +# NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME for more information about the +# construction of type-based names. +# +NV_CTRL_STRING_DISPLAY_NAME_TYPE_ID = 47 # R-D- + +# +# NV_CTRL_STRING_DISPLAY_NAME_DP_GUID - Returns the GUID of the DisplayPort +# display device. e.g. "DP-GUID-f16a5bde-79f3-11e1-b2ae-8b5a8969ba9c" +# +# The display device must be a DisplayPort 1.2 device. +# +NV_CTRL_STRING_DISPLAY_NAME_DP_GUID = 48 # R-D- + +# +# NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH - Returns the SHA-1 hash of the +# display device's EDID in 8-4-4-4-12 UID format. e.g. +# "DPY-EDID-f16a5bde-79f3-11e1-b2ae-8b5a8969ba9c" +# +# The display device must have a valid EDID. +# +NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH = 49 # R-D- + +# +# NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX - Returns the current NV-CONTROL +# target ID (name) of the display device. e.g. "DPY-1", "DPY-4" +# +# This name for the display device is not guarenteed to be the same between +# different runs of the X server. +# +NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX = 50 # R-D- + +# +# NV_CTRL_STRING_DISPLAY_NAME_RANDR - Returns the RandR output name for the +# display device. e.g. "VGA-1", "DVI-I-0", "DVI-D-3", "LVDS-1", "DP-2", +# "HDMI-3", "eDP-6". This name should match If this device is a DisplayPort +# 1.2 device, then this name will also be prepended with the device's port +# address like so: "DVI-I-3.0.1.2.3" +# +NV_CTRL_STRING_DISPLAY_NAME_RANDR = 51 # R-D- + +# +# NV_CTRL_STRING_GPU_UUID - Returns the UUID of the given GPU. +# +NV_CTRL_STRING_GPU_UUID = 52 # R--G + +# +# NV_CTRL_STRING_GPU_UTILIZATION - Returns the current percentage usage +# of the various components of the GPU. +# +# Current valid tokens are "graphics", "memory", "video" and "PCIe". +# Not all tokens will be reported on all GPUs, and additional tokens +# may be added in the future. +# +# Utilization values are returned as a comma-separated list of +# "token=value" pairs. +# Valid tokens: +# +# Token Value +# "graphics" integer - the percentage usage of graphics engine. +# "memory" integer - the percentage usage of FB. +# "video" integer - the percentage usage of video engine. +# "PCIe" integer - the percentage usage of PCIe bandwidth. +# +# +# Example: +# +# graphics=45, memory=6, video=0, PCIe=0 +# +# This attribute may be queried through XNVCTRLQueryTargetStringAttribute() +# using an NV_CTRL_TARGET_TYPE_GPU. +# +NV_CTRL_STRING_GPU_UTILIZATION = 53 # R--G + +# +# NV_CTRL_STRING_MULTIGPU_MODE - returns a string describing the current +# MULTIGPU mode, if any, or FALSE if MULTIGPU is not currently enabled. +# +NV_CTRL_STRING_MULTIGPU_MODE = 54 # R--- + +# +# NV_CTRL_STRING_PRIME_OUTPUTS_DATA - returns a semicolon delimited list of +# strings that describe all PRIME configured displays. +# +# ex. "xpos=1920, ypos=0, width=1280, height=1024, screen=0;xpos=3200, +# ypos=0, width=800, height=600, screen=0;" +# +NV_CTRL_STRING_PRIME_OUTPUTS_DATA = 55 # R--- + +NV_CTRL_STRING_LAST_ATTRIBUTE = NV_CTRL_STRING_PRIME_OUTPUTS_DATA + +############################################################################ + +# +# Binary Data Attributes: +# +# Binary data attributes can be queryied through the XNVCTRLQueryBinaryData() +# and XNVCTRLQueryTargetBinaryData() function calls. +# +# There are currently no binary data attributes that can be set. +# +# Unless otherwise noted, all Binary data attributes can be queried +# using an NV_CTRL_TARGET_TYPE_X_SCREEN target. Attributes that cannot take +# an NV_CTRL_TARGET_TYPE_X_SCREEN target also cannot be queried through +# XNVCTRLQueryBinaryData() (Since an X Screen target is assumed). +# + + +# +# NV_CTRL_BINARY_DATA_EDID - Returns a display device's EDID information +# data. +# +# This attribute may be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_BINARY_DATA_EDID = 0 # R-DG + +# +# NV_CTRL_BINARY_DATA_MODELINES - Returns a display device's supported +# ModeLines. ModeLines are returned in a buffer, separated by a single +# '\0' and terminated by two consecutive '\0' s like so: +# +# "ModeLine 1\0ModeLine 2\0ModeLine 3\0Last ModeLine\0\0" +# +# This attribute may be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target. +# +# Each ModeLine string may be prepended with a comma-separated list +# of "token=value" pairs, separated from the ModeLine string with a +# "::". Valid tokens: +# +# Token Value +# "source" "xserver" - the ModeLine is from the core X server +# "xconfig" - the ModeLine was specified in the X config file +# "builtin" - the NVIDIA driver provided this builtin ModeLine +# "vesa" - this is a VESA standard ModeLine +# "edid" - the ModeLine was in the display device's EDID +# "nv-control" - the ModeLine was specified via NV-CONTROL +# +# "xconfig-name" - for ModeLines that were specified in the X config +# file, this is the name the X config file +# gave for the ModeLine. +# +# Note that a ModeLine can have several sources; the "source" token +# can appear multiple times in the "token=value" pairs list. +# Additional source values may be specified in the future. +# +# Additional tokens may be added in the future, so it is recommended +# that any token parser processing the returned string from +# NV_CTRL_BINARY_DATA_MODELINES be implemented to gracefully ignore +# unrecognized tokens. +# +# E.g., +# +# "source=xserver, source=vesa, source=edid :: "1024x768_70" 75.0 1024 1048 1184 1328 768 771 777 806 -HSync -VSync" +# "source=xconfig, xconfig-name=1600x1200_60.00 :: "1600x1200_60_0" 161.0 1600 1704 1880 2160 1200 1201 1204 1242 -HSync +VSync" +# + +NV_CTRL_BINARY_DATA_MODELINES = 1 # R-DG + +# +# NV_CTRL_BINARY_DATA_METAMODES - Returns an X Screen's supported +# MetaModes. MetaModes are returned in a buffer separated by a +# single '\0' and terminated by two consecutive '\0' s like so: +# +# "MetaMode 1\0MetaMode 2\0MetaMode 3\0Last MetaMode\0\0" +# +# The MetaMode string should have the same syntax as the MetaMode X +# configuration option, as documented in the NVIDIA driver README. + +# Each MetaMode string may be prepended with a comma-separated list +# of "token=value" pairs, separated from the MetaMode string with +# "::". Currently, valid tokens are: +# +# Token Value +# "id" - the id of this MetaMode; this is stored in +# the Vertical Refresh field, as viewed +# by the XRandR and XF86VidMode X# +# extensions. +# +# "switchable" "yes"/"no" - whether this MetaMode may be switched to via +# ctrl-alt-+/-; Implicit MetaModes (see +# the "IncludeImplicitMetaModes" X +# config option), for example, are not +# normally made available through +# ctrl-alt-+/-. +# +# "source" "xconfig" - the MetaMode was specified in the X +# config file. +# "implicit" - the MetaMode was implicitly added; see the +# "IncludeImplicitMetaModes" X config option +# for details. +# "nv-control" - the MetaMode was added via the NV-CONTROL X +# extension to the currently running X server. +# "RandR" - the MetaMode was modified in response to an +# RandR RRSetCrtcConfig request. +# +# Additional tokens may be added in the future, so it is recommended +# that any token parser processing the returned string from +# NV_CTRL_BINARY_DATA_METAMODES be implemented to gracefully ignore +# unrecognized tokens. +# +# E.g., +# +# "id=50, switchable=yes, source=xconfig :: CRT-0: 1024x768 @1024x768 +0+0" +# + +NV_CTRL_BINARY_DATA_METAMODES = 2 # R-D- +NV_CTRL_BINARY_DATA_METAMODES_VERSION_1 = NV_CTRL_BINARY_DATA_METAMODES + +# +# NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU - Returns the list of X +# screens currently driven by the given GPU. +# +# The format of the returned data is: +# +# 4 CARD32 number of screens +# 4# n CARD32 screen indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN. +# + +NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU = 3 # R-DG + +# +# NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN - Returns the list of GPUs +# currently in use by the given X screen. +# +# The format of the returned data is: +# +# 4 CARD32 number of GPUs +# 4# n CARD32 GPU indices +# + +NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN = 4 # R--- + +# +# NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK - Returns the list of +# GPUs currently connected to the given frame lock board. +# +# The format of the returned data is: +# +# 4 CARD32 number of GPUs +# 4# n CARD32 GPU indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_FRAMELOCK target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN. +# + +NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK = 5 # R-DF + +# +# NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT - Returns the Display Device's +# viewport box into the given X Screen (in X Screen coordinates.) +# +# The format of the returned data is: +# +# 4 CARD32 Offset X +# 4 CARD32 Offset Y +# 4 CARD32 Width +# 4 CARD32 Height +# + +NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT = 6 # R-DG + +# +# NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU - Returns the list of +# Framelock devices currently connected to the given GPU. +# +# The format of the returned data is: +# +# 4 CARD32 number of Framelocks +# 4# n CARD32 Framelock indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN. +# + +NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU = 7 # R-DG + +# +# NV_CTRL_BINARY_DATA_GPUS_USING_VCSC - Deprecated +# +# Returns the list of GPU devices connected to the given VCS. +# +# The format of the returned data is: +# +# 4 CARD32 number of GPUs +# 4# n CARD32 GPU indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_VCSC target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN and cannot be queried using +# a NV_CTRL_TARGET_TYPE_X_GPU +# + +NV_CTRL_BINARY_DATA_GPUS_USING_VCSC = 8 # R-DV + +# +# NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU - Deprecated +# +# Returns the VCSC device that is controlling the given GPU. +# +# The format of the returned data is: +# +# 4 CARD32 number of VCS (always 1) +# 4# n CARD32 VCS indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN +# + +NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU = 9 # R-DG + +# +# NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU - Returns the coolers that +# are cooling the given GPU. +# +# The format of the returned data is: +# +# 4 CARD32 number of COOLER +# 4# n CARD32 COOLER indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN +# + +NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU = 10 # R-DG + +# +# NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN - Returns the list of +# GPUs currently driving the given X screen. If Xinerama is enabled, this +# will return all GPUs that are driving any X screen. +# +# The format of the returned data is: +# +# 4 CARD32 number of GPUs +# 4# n CARD32 GPU indices +# + +NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN = 11 # R--- + +# +# NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU - Returns the sensors that +# are attached to the given GPU. +# +# The format of the returned data is: +# +# 4 CARD32 number of SENSOR +# 4# n CARD32 SENSOR indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be +# queried using a NV_CTRL_TARGET_TYPE_X_SCREEN +# + +NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU = 12 # R--G + +# +# NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER - Returns +# the id of the glasses that are currently paired to the given +# 3D Vision Pro transceiver. +# +# The format of the returned data is: +# +# 4 CARD32 number of glasses +# 4# n CARD32 id of glasses +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target. +# +NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER = 13 # R--T + +# +# NV_CTRL_BINARY_DATA_DISPLAY_TARGETS - Returns all the display devices +# currently connected to any GPU on the X server. +# +# The format of the returned data is: +# +# 4 CARD32 number of display devices +# 4# n CARD32 display device indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData(). +# + +NV_CTRL_BINARY_DATA_DISPLAY_TARGETS = 14 # R--- + +# +# NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU - Returns the list of +# display devices that are connected to the GPU target. +# +# The format of the returned data is: +# +# 4 CARD32 number of display devices +# 4# n CARD32 display device indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. +# + +NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU = 15 # R--G + +# +# NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 - Returns values similar to +# NV_CTRL_BINARY_DATA_METAMODES(_VERSION_1) but also returns extended syntax +# information to indicate a specific display device, as well as other per- +# display deviceflags as "token=value" pairs. For example: +# +# "DPY-1: 1280x1024 {Stereo=PassiveLeft}, +# DPY-2: 1280x1024 {Stereo=PassiveRight}," +# +# The display device names have the form "DPY-%d", where the integer +# part of the name is the NV-CONTROL target ID for that display device +# for this instance of the X server. Note that display device NV-CONTROL +# target IDs are not guaranteed to be the same from one run of the X +# server to the next. +# + +NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 = 16 # R-D- + +# +# NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN - Returns the list of +# display devices that are currently scanning out the X screen target. +# +# The format of the returned data is: +# +# 4 CARD32 number of display devices +# 4# n CARD32 display device indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN = 17 # R--- + +# +# NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN - Returns the list of +# display devices that are currently assigned the X screen target. +# +# The format of the returned data is: +# +# 4 CARD32 number of display devices +# 4# n CARD32 display device indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + +NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN = 18 # R--- + +# +# NV_CTRL_BINARY_DATA_GPU_FLAGS - Returns a list of flags for the +# given GPU. A flag can, for instance, be a capability which enables +# or disables some features according to the GPU state. +# +# The format of the returned data is: +# +# 4 CARD32 number of GPU flags +# 4# n CARD32 GPU flag +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. +# +NV_CTRL_BINARY_DATA_GPU_FLAGS = 19 # R--- + +# Stereo and display composition transformations are mutually exclusive. +NV_CTRL_BINARY_DATA_GPU_FLAGS_STEREO_DISPLAY_TRANSFORM_EXCLUSIVE = 0 +# Overlay and display composition transformations are mutually exclusive. +NV_CTRL_BINARY_DATA_GPU_FLAGS_OVERLAY_DISPLAY_TRANSFORM_EXCLUSIVE = 1 +# Depth 8 and display composition transformations are mutually exclusive. +NV_CTRL_BINARY_DATA_GPU_FLAGS_DEPTH_8_DISPLAY_TRANSFORM_EXCLUSIVE = 2 + +# +# NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU - Returns the list of valid +# display devices that can be connected to the GPU target. +# +# The format of the returned data is: +# +# 4 CARD32 number of display devices +# 4# n CARD32 display device indices +# +# This attribute can only be queried through XNVCTRLQueryTargetBinaryData() +# using a NV_CTRL_TARGET_TYPE_GPU target. +# + +NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU = 20 # R--G + +NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE = NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU + +############################################################################ + +# +# String Operation Attributes: +# +# These attributes are used with the XNVCTRLStringOperation() +# function; a string is specified as input, and a string is returned +# as output. +# +# Unless otherwise noted, all attributes can be operated upon using +# an NV_CTRL_TARGET_TYPE_X_SCREEN target. +# + + +# +# NV_CTRL_STRING_OPERATION_ADD_METAMODE - provide a MetaMode string +# as input, and returns a string containing comma-separated list of +# "token=value" pairs as output. Currently, the only output token is +# "id", which indicates the id that was assigned to the MetaMode. +# +# All ModeLines referenced in the MetaMode must already exist for +# each display device (as returned by the +# NV_CTRL_BINARY_DATA_MODELINES attribute). +# +# The MetaMode string should have the same syntax as the MetaMode X +# configuration option, as documented in the NVIDIA driver README. +# +# The input string can optionally be prepended with a string of +# comma-separated "token=value" pairs, separated from the MetaMode +# string by "::". Currently, the only valid token is "index" which +# indicates the insertion index for the MetaMode. +# +# E.g., +# +# Input: "index=5 :: 1600x1200+0+0, 1600x1200+1600+0" +# Output: "id=58" +# +# which causes the MetaMode to be inserted at position 5 in the +# MetaMode list (all entries after 5 will be shifted down one slot in +# the list), and the X server's containing mode stores 58 as the +# VRefresh, so that the MetaMode can be uniquely identifed through +# XRandR and XF86VidMode. +# + +NV_CTRL_STRING_OPERATION_ADD_METAMODE = 0 # ---- + +# +# NV_CTRL_STRING_OPERATION_GTF_MODELINE - provide as input a string +# of comma-separated "token=value" pairs, and returns a ModeLine +# string, computed using the GTF formula using the parameters from +# the input string. Valid tokens for the input string are "width", +# "height", and "refreshrate". +# +# E.g., +# +# Input: "width=1600, height=1200, refreshrate=60" +# Output: "160.96 1600 1704 1880 2160 1200 1201 1204 1242 -HSync +VSync" +# +# This operation does not have any impact on any display device's +# modePool, and the ModeLine is not validated; it is simply intended +# for generating ModeLines. +# + +NV_CTRL_STRING_OPERATION_GTF_MODELINE = 1 # --- + +# +# NV_CTRL_STRING_OPERATION_CVT_MODELINE - provide as input a string +# of comma-separated "token=value" pairs, and returns a ModeLine +# string, computed using the CVT formula using the parameters from +# the input string. Valid tokens for the input string are "width", +# "height", "refreshrate", and "reduced-blanking". The +# "reduced-blanking" argument can be "0" or "1", to enable or disable +# use of reduced blanking for the CVT formula. +# +# E.g., +# +# Input: "width=1600, height=1200, refreshrate=60, reduced-blanking=1" +# Output: "130.25 1600 1648 1680 1760 1200 1203 1207 1235 +HSync -VSync" +# +# This operation does not have any impact on any display device's +# modePool, and the ModeLine is not validated; it is simply intended +# for generating ModeLines. +# + +NV_CTRL_STRING_OPERATION_CVT_MODELINE = 2 # --- + +# +# NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL - build a ModePool for the +# specified display device on the specified target (either an X +# screen or a GPU). This is typically used to generate a ModePool +# for a display device on a GPU on which no X screens are present. +# +# Currently, a display device's ModePool is static for the life of +# the X server, so XNVCTRLStringOperation will return FALSE if +# requested to build a ModePool on a display device that already has +# a ModePool. +# +# The string input to BUILD_MODEPOOL may be NULL. If it is not NULL, +# then it is interpreted as a double-colon ("::") separated list +# of "option=value" pairs, where the options and the syntax of their +# values are the X configuration options that impact the behavior of +# modePool construction; namely: +# +# "ModeValidation" +# "HorizSync" +# "VertRefresh" +# "FlatPanelProperties" +# "ExactModeTimingsDVI" +# "UseEdidFreqs" +# +# An example input string might look like: +# +# "ModeValidation=NoVesaModes :: HorizSync=50-110 :: VertRefresh=50-150" +# +# This request currently does not return a string. +# + +NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL = 3 # DG + +# +# NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS - Configure the streams- +# to-jack+channel topology for a GVI (Graphics capture board). +# +# The string input to GVI_CONFIGURE_STREAMS may be NULL. If this is the +# case, then the current topology is returned. +# +# If the input string to GVI_CONFIGURE_STREAMS is not NULL, the string +# is interpreted as a semicolon (";") separated list of comma-separated +# lists of "option=value" pairs that define a stream's composition. The +# available options and their values are: +# +# "stream": Defines which stream this comma-separated list describes. +# Valid values are the integers between 0 and +# NV_CTRL_GVI_NUM_STREAMS-1 (inclusive). +# +# "linkN": Defines a jack+channel pair to use for the given link N. +# Valid options are the string "linkN", where N is an integer +# between 0 and NV_CTRL_GVI_MAX_LINKS_PER_STREAM-1 (inclusive). +# Valid values for these options are strings of the form +# "jackX" and/or "jackX.Y", where X is an integer between 0 and +# NV_CTRL_GVI_NUM_JACKS-1 (inclusive), and Y (optional) is an +# integer between 0 and NV_CTRL_GVI_MAX_CHANNELS_PER_JACK-1 +# (inclusive). +# +# An example input string might look like: +# +# "stream=0, link0=jack0, link1=jack1; stream=1, link0=jack2.1" +# +# This example specifies two streams, stream 0 and stream 1. Stream 0 +# is defined to capture link0 data from the first channel (channel 0) of +# BNC jack 0 and link1 data from the first channel of BNC jack 1. The +# second stream (Stream 1) is defined to capture link0 data from channel 1 +# (second channel) of BNC jack 2. +# +# This example shows a possible configuration for capturing 3G input: +# +# "stream=0, link0=jack0.0, link1=jack0.1" +# +# Applications should query the following attributes to determine +# possible combinations: +# +# NV_CTRL_GVI_MAX_STREAMS +# NV_CTRL_GVI_MAX_LINKS_PER_STREAM +# NV_CTRL_GVI_NUM_JACKS +# NV_CTRL_GVI_MAX_CHANNELS_PER_JACK +# +# Note: A jack+channel pair can only be tied to one link/stream. +# +# Upon successful configuration or querying of this attribute, a string +# representing the current topology for all known streams on the device +# will be returned. On failure, NULL is returned. +# +# Note: Setting this attribute may also result in the following +# NV-CONTROL attributes being reset on the GVI device (to ensure +# the configuration remains valid): +# NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT +# NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT +# NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING +# + +NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS = 4 # RW-I + +# +# NV_CTRL_STRING_OPERATION_PARSE_METAMODE - Parses the given MetaMode string +# and returns the validated MetaMode string - possibly re-calculating various +# values such as ViewPortIn. If the MetaMode matches an existing MetaMode, +# the details of the existing MetaMode are returned. If the MetaMode fails to +# be parsed, NULL is returned. +# +NV_CTRL_STRING_OPERATION_PARSE_METAMODE = 5 # R--- + +NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE = NV_CTRL_STRING_OPERATION_PARSE_METAMODE + +############################################################################### +# NV-CONTROL major op numbers. these constants identify the request type +# +X_nvCtrlQueryExtension = 0 +X_nvCtrlQueryAttribute = 2 +X_nvCtrlQueryStringAttribute = 4 +X_nvCtrlQueryValidAttributeValues = 5 +X_nvCtrlSetStringAttribute = 9 +X_nvCtrlSetAttributeAndGetStatus = 19 +X_nvCtrlQueryBinaryData = 20 +X_nvCtrlQueryTargetCount = 24 +X_nvCtrlStringOperation = 25 + +############################################################################### +# various lists that go with attrs, but are handled more compactly +# this way. these lists are indexed by the possible values of their attrs +# and are explained in NVCtrl.h +# + +ATTRIBUTE_TYPE_UNKNOWN = 0 +ATTRIBUTE_TYPE_INTEGER = 1 +ATTRIBUTE_TYPE_BITMASK = 2 +ATTRIBUTE_TYPE_BOOL = 3 +ATTRIBUTE_TYPE_RANGE = 4 +ATTRIBUTE_TYPE_INT_BITS = 5 + +ATTRIBUTE_TYPE_READ = 0x01 +ATTRIBUTE_TYPE_WRITE = 0x02 +ATTRIBUTE_TYPE_DISPLAY = 0x04 +ATTRIBUTE_TYPE_GPU = 0x08 +ATTRIBUTE_TYPE_FRAMELOCK = 0x10 +ATTRIBUTE_TYPE_X_SCREEN = 0x20 +ATTRIBUTE_TYPE_XINERAMA = 0x40 +ATTRIBUTE_TYPE_VCSC = 0x80 + +############################################################################ + +# +# Attribute Targets +# +# Targets define attribute groups. For example, some attributes are only +# valid to set on a GPU, others are only valid when talking about an +# X Screen. Target types are then what is used to identify the target +# group of the attribute you wish to set/query. +# +# Here are the supported target types: +# + +NV_CTRL_TARGET_TYPE_X_SCREEN = 0 +NV_CTRL_TARGET_TYPE_GPU = 1 +NV_CTRL_TARGET_TYPE_FRAMELOCK = 2 +# Visual Computing System - deprecated. To be removed along with all +# VCS-specific attributes in a later release. +NV_CTRL_TARGET_TYPE_VCSC = 3 +NV_CTRL_TARGET_TYPE_GVI = 4 +NV_CTRL_TARGET_TYPE_COOLER = 5 # e.g., fan +NV_CTRL_TARGET_TYPE_THERMAL_SENSOR = 6 +NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER = 7 +NV_CTRL_TARGET_TYPE_DISPLAY = 8 + + +############################################################################### +# Targets, to indicate where a command should be executed. +# +class Target(object): + def __init__(self): + self._id = -1 + self._type = -1 + self._name = '' + + def id(self): + return self._id + + def type(self): + return self._type + + def __str__(self): + return ''.format(self._name, self.id()) + + +class Gpu(Target): + def __init__(self, ngpu=0): + """Target a GPU""" + super(self.__class__, self).__init__() + self._id = ngpu + self._type = NV_CTRL_TARGET_TYPE_GPU + self._name = 'GPU' + + +class Screen(Target): + def __init__(self, nscr=0): + """Target an X screen""" + super(self.__class__, self).__init__() + self._id = nscr + self._type = NV_CTRL_TARGET_TYPE_X_SCREEN + self._name = 'X screen' + + +class Cooler(Target): + def __init__(self, nfan=0): + """Target a fann""" + super(self.__class__, self).__init__() + self._id = nfan + self._type = NV_CTRL_TARGET_TYPE_COOLER + self._name = 'Cooler' + + +class NVCtrlQueryTargetCountReplyRequest(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(X_nvCtrlQueryTargetCount), + rq.RequestLength(), + rq.Card32('target_type'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('padb1'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('count'), + rq.Card32('pad4'), + rq.Card32('pad5'), + rq.Card32('pad6'), + rq.Card32('pad7'), + rq.Card32('pad8'), + ) + + +class NVCtrlQueryAttributeReplyRequest(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(X_nvCtrlQueryAttribute), + rq.RequestLength(), + rq.Card16('target_id'), + rq.Card16('target_type'), + rq.Card32('display_mask'), + rq.Card32('attr'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('pad0'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('flags'), + rq.Int32('value'), + rq.Card32('pad4'), + rq.Card32('pad5'), + rq.Card32('pad6'), + rq.Card32('pad7'), + ) + + +class NVCtrlSetAttributeAndGetStatusReplyRequest(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(X_nvCtrlSetAttributeAndGetStatus), + rq.RequestLength(), + rq.Card16('target_id'), + rq.Card16('target_type'), + rq.Card32('display_mask'), + rq.Card32('attr'), + rq.Int32('value') + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('pad0'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('flags'), + rq.Card32('pad3'), + rq.Card32('pad4'), + rq.Card32('pad5'), + rq.Card32('pad6'), + rq.Card32('pad7'), + ) + + +class NVCtrlQueryStringAttributeReplyRequest(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(X_nvCtrlQueryStringAttribute), + rq.RequestLength(), + rq.Card16('target_id'), + rq.Card16('target_type'), + rq.Card32('display_mask'), + rq.Card32('attr'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('pad0'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('flags'), + rq.Card32('string', 4), + rq.Card32('pad4'), + rq.Card32('pad5'), + rq.Card32('pad6'), + rq.Card32('pad7'), + rq.String8('string'), + ) + + +class NVCtrlQueryValidAttributeValuesReplyRequest(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(X_nvCtrlQueryValidAttributeValues), + rq.RequestLength(), + rq.Card16('target_id'), + rq.Card16('target_type'), + rq.Card32('display_mask'), + rq.Card32('attr'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('pad0'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('flags'), + rq.Int32('attr_type'), + rq.Int32('min'), + rq.Int32('max'), + rq.Card32('bits'), + rq.Card32('perms'), + ) + + +class NVCtrlQueryBinaryDataReplyRequest(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(X_nvCtrlQueryBinaryData), + rq.RequestLength(), + rq.Card16('target_id'), + rq.Card16('target_type'), + rq.Card32('display_mask'), + rq.Card32('attr'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('pad0'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('flags'), + rq.Card32('data', 4), + rq.Card32('pad4'), + rq.Card32('pad5'), + rq.Card32('pad6'), + rq.Card32('pad7'), + rq.Binary('data'), + ) + + +class NVCtrlQueryListCard32ReplyRequest(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(X_nvCtrlQueryBinaryData), + rq.RequestLength(), + rq.Card16('target_id'), + rq.Card16('target_type'), + rq.Card32('display_mask'), + rq.Card32('attr'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('pad0'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('flags'), + rq.Card32('list', 4), + rq.Card32('pad4'), + rq.Card32('pad5'), + rq.Card32('pad6'), + rq.Card32('pad7'), + rq.List('list', rq.Card32), + ) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/randr.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/randr.py new file mode 100644 index 0000000..8149c48 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/randr.py @@ -0,0 +1,1292 @@ +# Xlib.ext.randr -- RandR extension module +# +# Copyright (C) 2006 Mike Meyer +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +"""RandR - provide access to the RandR extension information. + +This implementation is based off version 1.5 of the XRandR protocol, and may +not be compatible with other versions. + +Version 1.5 of the protocol is documented at: +http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt + +Version 1.3.1 here: +http://www.x.org/releases/X11R7.5/doc/randrproto/randrproto.txt + +""" + + +from Xlib import X +from Xlib.protocol import rq + +extname = 'RANDR' + + +# Event codes # +RRScreenChangeNotify = 0 + +# V1.2 additions +RRNotify = 1 + +# RRNotify Subcodes +RRNotify_CrtcChange = 0 +RRNotify_OutputChange = 1 +RRNotify_OutputProperty = 2 + + +# Event selection bits # +RRScreenChangeNotifyMask = (1 << 0) + +# V1.2 additions +RRCrtcChangeNotifyMask = (1 << 1) +RROutputChangeNotifyMask = (1 << 2) +RROutputPropertyNotifyMask = (1 << 3) + + +# Constants # +SetConfigSuccess = 0 +SetConfigInvalidConfigTime = 1 +SetConfigInvalidTime = 2 +SetConfigFailed = 3 + +# used in the rotation field; rotation and reflection in 0.1 proto. +Rotate_0 = 1 +Rotate_90 = 2 +Rotate_180 = 4 +Rotate_270 = 8 + +# new in 1.0 protocol, to allow reflection of screen +Reflect_X = 16 +Reflect_Y = 32 + +# new in 1.2 protocol +HSyncPositive = 0x00000001 +HSyncNegative = 0x00000002 +VSyncPositive = 0x00000004 +VSyncNegative = 0x00000008 +Interlace = 0x00000010 +DoubleScan = 0x00000020 +CSync = 0x00000040 +CSyncPositive = 0x00000080 +CSyncNegative = 0x00000100 +HSkewPresent = 0x00000200 +BCast = 0x00000400 +PixelMultiplex = 0x00000800 +DoubleClock = 0x00001000 +ClockDivideBy2 = 0x00002000 + +# event types? +Connected = 0 +Disconnected = 1 +UnknownConnection = 2 + +# Conventional RandR output properties +PROPERTY_RANDR_EDID = "EDID" +PROPERTY_SIGNAL_FORMAT = "SignalFormat" +PROPERTY_SIGNAL_PROPERTIES = "SignalProperties" +PROPERTY_CONNECTOR_TYPE = "ConnectorType" +PROPERTY_CONNECTOR_NUMBER = "ConnectorNumber" +PROPERTY_COMPATIBILITY_LIST = "CompatibilityList" +PROPERTY_CLONE_LIST = "CloneList" + +# subpixel order - TODO: These constants are part of the RENDER extension and +# should be moved there if/when that extension is added to python-xlib. +SubPixelUnknown = 0 +SubPixelHorizontalRGB = 1 +SubPixelHorizontalBGR = 2 +SubPixelVerticalRGB = 3 +SubPixelVerticalBGR = 4 +SubPixelNone = 5 + + +# Error Codes # +BadRROutput = 0 +BadRRCrtc = 1 +BadRRMode = 2 + +# Error classes # +class BadRROutputError(Exception): pass + +class BadRRCrtcError(Exception): pass + +class BadRRModeError(Exception): pass + +# Data Structures # + +RandR_ScreenSizes = rq.Struct( + rq.Card16('width_in_pixels'), + rq.Card16('height_in_pixels'), + rq.Card16('width_in_millimeters'), + rq.Card16('height_in_millimeters'), + ) + + +RandR_ModeInfo = rq.Struct( + rq.Card32('id'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card32('dot_clock'), + rq.Card16('h_sync_start'), + rq.Card16('h_sync_end'), + rq.Card16('h_total'), + rq.Card16('h_skew'), + rq.Card16('v_sync_start'), + rq.Card16('v_sync_end'), + rq.Card16('v_total'), + rq.Card16('name_length'), + rq.Card32('flags'), + ) + +RandR_Rates = rq.Struct( + rq.LengthOf('rates', 2), + rq.List('rates', rq.Card16Obj) + ) + +# TODO: This struct is part of the RENDER extension and should be moved there +# if/when that extension is added to python-xlib. +Render_Transform = rq.Struct( + rq.Card32('matrix11'), #FIXME: All of these are listed as FIXED in the protocol header. + rq.Card32('matrix12'), + rq.Card32('matrix13'), + rq.Card32('matrix21'), + rq.Card32('matrix22'), + rq.Card32('matrix23'), + rq.Card32('matrix31'), + rq.Card32('matrix32'), + rq.Card32('matrix33'), + ) + +MonitorInfo = rq.Struct( + rq.Card32('name'), + rq.Bool('primary'), + rq.Bool('automatic'), + rq.LengthOf('crtcs', 2), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width_in_pixels'), + rq.Card16('height_in_pixels'), + rq.Card32('width_in_millimeters'), + rq.Card32('height_in_millimeters'), + rq.List('crtcs', rq.Card32Obj) +) + +# Requests # + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + rq.Pad(16), + ) + +def query_version(self): + """Get the current version of the RandR extension. + + """ + return QueryVersion( + display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=5, + ) + + +class _1_0SetScreenConfig(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.Card16('size_id'), + rq.Card16('rotation'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('new_timestamp'), + rq.Card32('new_config_timestamp'), + rq.Window('root'), + rq.Card16('subpixel_order'), + rq.Pad(10), + ) + +def _1_0set_screen_config(self, size_id, rotation, config_timestamp, timestamp=X.CurrentTime): + """Sets the screen to the specified size and rotation. + + """ + return _1_0SetScreenConfig( + display=self.display, + opcode=self.display.get_extension_major(extname), + drawable=self, + timestamp=timestamp, + config_timestamp=config_timestamp, + size_id=size_id, + rotation=rotation, + ) + + +class SetScreenConfig(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.Card16('size_id'), + rq.Card16('rotation'), + rq.Card16('rate'), # added in version 1.1 + rq.Pad(2), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('new_timestamp'), + rq.Card32('new_config_timestamp'), + rq.Window('root'), + rq.Card16('subpixel_order'), + rq.Pad(10), + ) + +def set_screen_config(self, size_id, rotation, config_timestamp, rate=0, timestamp=X.CurrentTime): + """Sets the screen to the specified size, rate, rotation and reflection. + + rate can be 0 to have the server select an appropriate rate. + + """ + return SetScreenConfig( + display=self.display, + opcode=self.display.get_extension_major(extname), + drawable=self, + timestamp=timestamp, + config_timestamp=config_timestamp, + size_id=size_id, + rotation=rotation, + rate=rate, + ) + + +class SelectInput(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + rq.Window('window'), + rq.Card16('mask'), + rq.Pad(2), + ) + +def select_input(self, mask): + return SelectInput( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + mask=mask, + ) + + +class GetScreenInfo(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(5), + rq.RequestLength(), + rq.Window('window'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('set_of_rotations'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('root'), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.LengthOf('sizes', 2), + rq.Card16('size_id'), + rq.Card16('rotation'), + rq.Card16('rate'), # added in version 1.1 + rq.Card16('n_rate_ents'), # XCB's protocol description disagrees with the X headers on this; ignoring. + rq.Pad(2), + rq.List('sizes', RandR_ScreenSizes), + #rq.List('rates', RandR_Rates) #FIXME: Why does uncommenting this cause an error? + ) + +def get_screen_info(self): + """Retrieve information about the current and available configurations for + the screen associated with this window. + + """ + return GetScreenInfo( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + ) + + +# version 1.2 + +class GetScreenSizeRange(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(6), + rq.RequestLength(), + rq.Window('window'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('min_width'), + rq.Card16('min_height'), + rq.Card16('max_width'), + rq.Card16('max_height'), + rq.Pad(16), + ) + +def get_screen_size_range(self): + """Retrieve the range of possible screen sizes. The screen may be set to + any size within this range. + + """ + return GetScreenSizeRange( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + ) + + +class SetScreenSize(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(7), + rq.RequestLength(), + rq.Window('window'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card32('width_in_millimeters'), + rq.Card32('height_in_millimeters'), + ) + +def set_screen_size(self, width, height, width_in_millimeters=None, height_in_millimeters=None): + return SetScreenSize( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + width=width, + height=height, + width_in_millimeters=width_in_millimeters, + height_in_millimeters=height_in_millimeters, + ) + + +class GetScreenResources(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(8), + rq.RequestLength(), + rq.Window('window'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.LengthOf('crtcs', 2), + rq.LengthOf('outputs', 2), + rq.LengthOf('modes', 2), + rq.LengthOf('mode_names', 2), + rq.Pad(8), + rq.List('crtcs', rq.Card32Obj), + rq.List('outputs', rq.Card32Obj), + rq.List('modes', RandR_ModeInfo), + rq.String8('mode_names'), + ) + +def get_screen_resources(self): + return GetScreenResources( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + ) + + +class GetOutputInfo(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(9), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('config_timestamp'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('timestamp'), + rq.Card32('crtc'), + rq.Card32('mm_width'), + rq.Card32('mm_height'), + rq.Card8('connection'), + rq.Card8('subpixel_order'), + rq.LengthOf('crtcs', 2), + rq.LengthOf('modes', 2), + rq.Card16('num_preferred'), + rq.LengthOf('clones', 2), + rq.LengthOf('name', 2), + rq.List('crtcs', rq.Card32Obj), + rq.List('modes', rq.Card32Obj), + rq.List('clones', rq.Card32Obj), + rq.String8('name'), + ) + +def get_output_info(self, output, config_timestamp): + return GetOutputInfo( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + config_timestamp=config_timestamp, + ) + + +class ListOutputProperties(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(10), + rq.RequestLength(), + rq.Card32('output'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('atoms', 2), + rq.Pad(22), + rq.List('atoms', rq.Card32Obj), + ) + +def list_output_properties(self, output): + return ListOutputProperties ( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + ) + + +class QueryOutputProperty(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(11), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('property'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Bool('pending'), + rq.Bool('range'), + rq.Bool('immutable'), + rq.Pad(21), + rq.List('valid_values', rq.Card32Obj), + ) + +def query_output_property(self, output, property): + return QueryOutputProperty ( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + property=property, + ) + + +class ConfigureOutputProperty (rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(12), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('property'), + rq.Bool('pending'), + rq.Bool('range'), + rq.Pad(2), + rq.List('valid_values', rq.Card32Obj), + ) + +def configure_output_property (self, output, property): + return ConfigureOutputProperty ( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + property=property, + ) + + +class ChangeOutputProperty(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(13), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('property'), + rq.Card32('type'), + rq.Format('value', 1), + rq.Card8('mode'), + rq.Pad(2), + rq.LengthOf('value', 4), + rq.PropertyData('value'), + ) + +def change_output_property(self, output, property, type, mode, value): + return ChangeOutputProperty( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + property=property, + type=type, + mode=mode, + value=value, + ) + + +class DeleteOutputProperty(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(14), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('property'), + ) + +def delete_output_property(self, output, property): + return DeleteOutputProperty( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + property=property, + ) + + +class GetOutputProperty(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(15), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('property'), + rq.Card32('type'), + rq.Card32('long_offset'), + rq.Card32('long_length'), + rq.Bool('delete'), + rq.Bool('pending'), + rq.Pad(2), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Format('value', 1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('property_type'), + rq.Card32('bytes_after'), + rq.LengthOf('value', 4), + rq.Pad(12), + rq.List('value', rq.Card8Obj), + ) + +def get_output_property(self, output, property, type, long_offset, long_length, delete=False, pending=False): + return GetOutputProperty( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + property=property, + type=type, + long_offset=long_offset, + long_length=long_length, + delete=delete, + pending=pending, + ) + + +class CreateMode(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(16), + rq.RequestLength(), + rq.Window('window'), + rq.Object('mode', RandR_ModeInfo), + rq.String8('name'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('mode'), + rq.Pad(20), + ) + +def create_mode(self, mode, name): + return CreateMode ( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + mode=mode, + name=name, + ) + + +class DestroyMode(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(17), + rq.RequestLength(), + rq.Card32('mode'), + ) + +def destroy_mode(self, mode): + return DestroyMode( + display=self.display, + opcode=self.display.get_extension_major(extname), + mode=mode, + ) + + +class AddOutputMode(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(18), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('mode'), + ) + +def add_output_mode(self, output, mode): + return AddOutputMode( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + mode=mode, + ) + + +class DeleteOutputMode(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(19), + rq.RequestLength(), + rq.Card32('output'), + rq.Card32('mode'), + ) + +def delete_output_mode(self, output, mode): + return DeleteOutputMode( + display=self.display, + opcode=self.display.get_extension_major(extname), + output=output, + mode=mode, + ) + + +class GetCrtcInfo(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(20), + rq.RequestLength(), + rq.Card32('crtc'), + rq.Card32('config_timestamp'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('timestamp'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card32('mode'), + rq.Card16('rotation'), + rq.Card16('possible_rotations'), + rq.LengthOf('outputs', 2), + rq.LengthOf('possible_outputs', 2), + rq.List('outputs', rq.Card32Obj), + rq.List('possible_outputs', rq.Card32Obj), + ) + +def get_crtc_info(self, crtc, config_timestamp): + return GetCrtcInfo ( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + config_timestamp=config_timestamp, + ) + + +class SetCrtcConfig(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(21), + rq.RequestLength(), + rq.Card32('crtc'), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card32('mode'), + rq.Card16('rotation'), + rq.Pad(2), + rq.List('outputs', rq.Card32Obj), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('new_timestamp'), + rq.Pad(20), + ) + +def set_crtc_config(self, crtc, config_timestamp, x, y, mode, rotation, outputs, timestamp=X.CurrentTime): + return SetCrtcConfig ( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + config_timestamp=config_timestamp, + x=x, + y=y, + mode=mode, + rotation=rotation, + outputs=outputs, + timestamp=timestamp, + ) + + +class GetCrtcGammaSize(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(22), + rq.RequestLength(), + rq.Card32('crtc'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('size'), + rq.Pad(22), + ) + +def get_crtc_gamma_size(self, crtc): + return GetCrtcGammaSize ( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + ) + + +class GetCrtcGamma(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(23), + rq.RequestLength(), + rq.Card32('crtc'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf(('red', 'green', 'blue'), 2), + rq.Pad(22), + rq.List('red', rq.Card16Obj), + rq.List('green', rq.Card16Obj), + rq.List('blue', rq.Card16Obj), + ) + +def get_crtc_gamma(self, crtc): + return GetCrtcGamma ( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + ) + + +class SetCrtcGamma(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(24), + rq.RequestLength(), + rq.Card32('crtc'), + rq.Card16('size'), + rq.Pad(2), + rq.List('red', rq.Card16Obj), + rq.List('green', rq.Card16Obj), + rq.List('blue', rq.Card16Obj), + ) + +def set_crtc_gamma(self, crtc, size, red, green, blue): + return SetCrtcGamma( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + size=size, + red=red, + green=green, + blue=blue, + ) + + +# version 1.3 + +class GetScreenResourcesCurrent(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(25), + rq.RequestLength(), + rq.Window('window'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.LengthOf('crtcs', 2), + rq.LengthOf('outputs', 2), + rq.LengthOf('modes', 2), + rq.LengthOf('names', 2), + rq.Pad(8), + rq.List('crtcs', rq.Card32Obj), + rq.List('outputs', rq.Card32Obj), + rq.List('modes', RandR_ModeInfo), + rq.String8('names'), + ) + +def get_screen_resources_current(self): + return GetScreenResourcesCurrent( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + ) + + +class SetCrtcTransform(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(26), + rq.RequestLength(), + rq.Card32('crtc'), + rq.Object('transform', Render_Transform), + rq.LengthOf('filter_name', 2), + rq.Pad(2), + rq.String8('filter_name'), + rq.List('filter_params', rq.Card32Obj), #FIXME: The protocol says FIXED? http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt#n2161 + ) + +def set_crtc_transform(self, crtc, n_bytes_filter): + return SetCrtcTransform( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + n_bytes_filter=n_bytes_filter, + ) + + +class GetCrtcTransform(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(27), + rq.RequestLength(), + rq.Card32('crtc'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Object('pending_transform', Render_Transform), + rq.Bool('has_transforms'), + rq.Pad(3), + rq.Object('current_transform', Render_Transform), + rq.Pad(4), + rq.LengthOf('pending_filter_name', 2), + rq.LengthOf('pending_filter_params', 2), + rq.LengthOf('current_filter_name', 2), + rq.LengthOf('current_filter_params', 2), + rq.String8('pending_filter_name'), + rq.List('pending_filter_params', rq.Card32Obj), #FIXME: The protocol says FIXED? http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt#n2161 + rq.String8('current_filter_name'), + rq.List('current_filter_params', rq.Card32Obj), #FIXME: The protocol says FIXED? http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt#n2161 + ) + +def get_crtc_transform(self, crtc): + return GetCrtcTransform( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + ) + + +class GetPanning(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(28), + rq.RequestLength(), + rq.Card32('crtc'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('timestamp'), + rq.Card16('left'), + rq.Card16('top'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('track_left'), + rq.Card16('track_top'), + rq.Card16('track_width'), + rq.Card16('track_height'), + rq.Int16('border_left'), + rq.Int16('border_top'), + rq.Int16('border_right'), + rq.Int16('border_bottom'), + ) + +def get_panning(self, crtc): + return GetPanning ( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + ) + + +class SetPanning(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(29), + rq.RequestLength(), + rq.Card32('crtc'), + rq.Card32('timestamp'), + rq.Card16('left'), + rq.Card16('top'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('track_left'), + rq.Card16('track_top'), + rq.Card16('track_width'), + rq.Card16('track_height'), + rq.Int16('border_left'), + rq.Int16('border_top'), + rq.Int16('border_right'), + rq.Int16('border_bottom'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('new_timestamp'), + rq.Pad(20), + ) + +def set_panning(self, crtc, left, top, width, height, track_left, track_top, track_width, track_height, border_left, border_top, border_width, border_height, timestamp=X.CurrentTime): + return SetPanning ( + display=self.display, + opcode=self.display.get_extension_major(extname), + crtc=crtc, + left=left, + top=top, + width=width, + height=height, + track_left=track_left, + track_top=track_top, + track_width=track_width, + track_height=track_height, + border_left=border_left, + border_top=border_top, + border_width=border_width, + border_height=border_height, + timestamp=timestamp, + ) + + +class SetOutputPrimary(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(30), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('output'), + ) + +def set_output_primary(self, output): + return SetOutputPrimary( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + output=output, + ) + + +class GetOutputPrimary(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(31), + rq.RequestLength(), + rq.Window('window'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('output'), + rq.Pad(20), + ) + +def get_output_primary(self): + return GetOutputPrimary( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + ) + + +# Version 1.5 methods + +class GetMonitors(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(42), + rq.RequestLength(), + rq.Window('window'), + rq.Bool('is_active'), + rq.Pad(3) + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('timestamp'), + rq.LengthOf('monitors', 4), + rq.Card32('outputs'), + rq.Pad(12), + rq.List('monitors', MonitorInfo) + ) + + +def get_monitors(self, is_active=True): + return GetMonitors( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + is_active=is_active + ) + +class SetMonitor(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(43), + rq.RequestLength(), + rq.Window('window'), + rq.Object('monitor_info', MonitorInfo) + ) + + +def set_monitor(self, monitor_info): + return SetMonitor( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + monitor_info=monitor_info + ) + + +class DeleteMonitor(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(44), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('name') + ) + + +def delete_monitor(self, name): + return DeleteMonitor( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + name=name + ) + +# Events # + +class ScreenChangeNotify(rq.Event): + _code = None + _fields = rq.Struct( + rq.Card8('type'), + rq.Card8('rotation'), + rq.Card16('sequence_number'), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.Window('root'), + rq.Window('window'), + rq.Card16('size_id'), + rq.Card16('subpixel_order'), + rq.Card16('width_in_pixels'), + rq.Card16('height_in_pixels'), + rq.Card16('width_in_millimeters'), + rq.Card16('height_in_millimeters'), + ) + + +class CrtcChangeNotify(rq.Event): + _code = None + _fields = rq.Struct( + rq.Card8('type'), + rq.Card8('sub_code'), + rq.Card16('sequence_number'), + rq.Card32('timestamp'), + rq.Window('window'), + rq.Card32('crtc'), + rq.Card32('mode'), + rq.Card16('rotation'), + rq.Pad(2), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + ) + + +class OutputChangeNotify(rq.Event): + _code = None + _fields = rq.Struct( + rq.Card8('type'), + rq.Card8('sub_code'), + rq.Card16('sequence_number'), + rq.Card32('timestamp'), + rq.Card32('config_timestamp'), + rq.Window('window'), + rq.Card32('output'), + rq.Card32('crtc'), + rq.Card32('mode'), + rq.Card16('rotation'), + rq.Card8('connection'), + rq.Card8('subpixel_order'), + ) + + +class OutputPropertyNotify(rq.Event): + _code = None + _fields = rq.Struct( + rq.Card8('type'), + rq.Card8('sub_code'), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card32('output'), + rq.Card32('atom'), + rq.Card32('timestamp'), + rq.Card8('state'), + rq.Pad(11), + ) +# Initialization # + +def init(disp, info): + disp.extension_add_method('display', 'xrandr_query_version', query_version) + disp.extension_add_method('window', 'xrandr_select_input', select_input) + disp.extension_add_method('window', 'xrandr_get_screen_info', get_screen_info) + disp.extension_add_method('drawable', 'xrandr_1_0set_screen_config', _1_0set_screen_config) + disp.extension_add_method('drawable', 'xrandr_set_screen_config', set_screen_config) + disp.extension_add_method('window', 'xrandr_get_screen_size_range', get_screen_size_range) + disp.extension_add_method('window', 'xrandr_set_screen_size', set_screen_size) + disp.extension_add_method('window', 'xrandr_get_screen_resources', get_screen_resources) + disp.extension_add_method('display', 'xrandr_get_output_info', get_output_info) + disp.extension_add_method('display', 'xrandr_list_output_properties', list_output_properties) + disp.extension_add_method('display', 'xrandr_query_output_property', query_output_property) + disp.extension_add_method('display', 'xrandr_configure_output_property ', configure_output_property ) + disp.extension_add_method('display', 'xrandr_change_output_property', change_output_property) + disp.extension_add_method('display', 'xrandr_delete_output_property', delete_output_property) + disp.extension_add_method('display', 'xrandr_get_output_property', get_output_property) + disp.extension_add_method('window', 'xrandr_create_mode', create_mode) + disp.extension_add_method('display', 'xrandr_destroy_mode', destroy_mode) + disp.extension_add_method('display', 'xrandr_add_output_mode', add_output_mode) + disp.extension_add_method('display', 'xrandr_delete_output_mode', delete_output_mode) + disp.extension_add_method('display', 'xrandr_get_crtc_info', get_crtc_info) + disp.extension_add_method('display', 'xrandr_set_crtc_config', set_crtc_config) + disp.extension_add_method('display', 'xrandr_get_crtc_gamma_size', get_crtc_gamma_size) + disp.extension_add_method('display', 'xrandr_get_crtc_gamma', get_crtc_gamma) + disp.extension_add_method('display', 'xrandr_set_crtc_gamma', set_crtc_gamma) + disp.extension_add_method('window', 'xrandr_get_screen_resources_current', get_screen_resources_current) + disp.extension_add_method('display', 'xrandr_set_crtc_transform', set_crtc_transform) + disp.extension_add_method('display', 'xrandr_get_crtc_transform', get_crtc_transform) + disp.extension_add_method('window', 'xrandr_set_output_primary', set_output_primary) + disp.extension_add_method('window', 'xrandr_get_output_primary', get_output_primary) + disp.extension_add_method('display', 'xrandr_get_panning', get_panning) + disp.extension_add_method('display', 'xrandr_set_panning', set_panning) + + # If the server is running RANDR 1.5+, enable 1.5 compatible methods and events + version = query_version(disp) + if version.major_version == 1 and version.minor_version >= 5: + # version 1.5 compatible + disp.extension_add_method('window', 'xrandr_get_monitors', get_monitors) + disp.extension_add_method('window', 'xrandr_set_monitor', set_monitor) + disp.extension_add_method('window', 'xrandr_delete_monitor', delete_monitor) + + disp.extension_add_event(info.first_event + RRScreenChangeNotify, ScreenChangeNotify) + # add RRNotify events (1 event code with 3 subcodes) + disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_CrtcChange, CrtcChangeNotify) + disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_OutputChange, OutputChangeNotify) + disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_OutputProperty, OutputPropertyNotify) + + disp.extension_add_error(BadRROutput, BadRROutputError) + disp.extension_add_error(BadRRCrtc, BadRRCrtcError) + disp.extension_add_error(BadRRMode, BadRRModeError) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/record.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/record.py new file mode 100644 index 0000000..5b1e2a8 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/record.py @@ -0,0 +1,282 @@ +# Xlib.ext.record -- RECORD extension module +# +# Copyright (C) 2006 Alex Badea +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib.protocol import rq + +extname = 'RECORD' + +FromServerTime = 0x01 +FromClientTime = 0x02 +FromClientSequence = 0x04 + +CurrentClients = 1 +FutureClients = 2 +AllClients = 3 + +FromServer = 0 +FromClient = 1 +ClientStarted = 2 +ClientDied = 3 +StartOfData = 4 +EndOfData = 5 + +Record_Range8 = rq.Struct( + rq.Card8('first'), + rq.Card8('last')) +Record_Range16 = rq.Struct( + rq.Card16('first'), + rq.Card16('last')) +Record_ExtRange = rq.Struct( + rq.Card8('major_range_first'), + rq.Card8('major_range_last'), + rq.Card16('minor_range_first'), + rq.Card16('minor_range_last')) +Record_Range = rq.Struct( + rq.Object('core_requests', Record_Range8), + rq.Object('core_replies', Record_Range8), + rq.Object('ext_requests', Record_ExtRange), + rq.Object('ext_replies', Record_ExtRange), + rq.Object('delivered_events', Record_Range8), + rq.Object('device_events', Record_Range8), + rq.Object('errors', Record_Range8), + rq.Bool('client_started'), + rq.Bool('client_died')) + +Record_ClientInfo = rq.Struct( + rq.Card32('client_resource'), + rq.LengthOf('ranges', 4), + rq.List('ranges', Record_Range)) + + +class RawField(rq.ValueField): + """A field with raw data, stored as a string""" + + structcode = None + + def pack_value(self, val): + return val, len(val), None + + def parse_binary_value(self, data, display, length, format): + return data, '' + + +class GetVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card16('major_version'), + rq.Card16('minor_version')) + _reply = rq.Struct( + rq.Pad(2), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + rq.Pad(20)) + +def get_version(self, major, minor): + return GetVersion( + display = self.display, + opcode = self.display.get_extension_major(extname), + major_version = major, + minor_version = minor) + + +class CreateContext(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + rq.Card32('context'), # Record_RC + rq.Card8('element_header'), # Record_Element_Header + rq.Pad(3), + rq.LengthOf('clients', 4), + rq.LengthOf('ranges', 4), + rq.List('clients', rq.Card32Obj), + rq.List('ranges', Record_Range)) + +def create_context(self, datum_flags, clients, ranges): + context = self.display.allocate_resource_id() + CreateContext( + display = self.display, + opcode = self.display.get_extension_major(extname), + context = context, + element_header = datum_flags, + clients = clients, + ranges = ranges) + return context + + +class RegisterClients(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Card32('context'), # Record_RC + rq.Card8('element_header'), # Record_Element_Header + rq.Pad(3), + rq.LengthOf('clients', 4), + rq.LengthOf('ranges', 4), + rq.List('clients', rq.Card32Obj), + rq.List('ranges', Record_Range)) + +def register_clients(self, context, element_header, clients, ranges): + RegisterClients( + display = self.display, + opcode = self.display.get_extension_major(extname), + context = context, + element_header = element_header, + clients = clients, + ranges = ranges) + + +class UnregisterClients(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + rq.Card32('context'), # Record_RC + rq.LengthOf('clients', 4), + rq.List('clients', rq.Card32Obj)) + +def unregister_clients(self, context, clients): + UnregisterClients( + display = self.display, + opcode = self.display.get_extension_major(extname), + context = context, + clients = clients) + + +class GetContext(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + rq.Card32('context')) # Record_RC + _reply = rq.Struct( + rq.Pad(2), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card8('element_header'), # Record_Element_Header + rq.Pad(3), + rq.LengthOf('client_info', 4), + rq.Pad(16), + rq.List('client_info', Record_ClientInfo)) + +def get_context(self, context): + return GetContext( + display = self.display, + opcode = self.display.get_extension_major(extname), + context = context) + + +class EnableContext(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(5), + rq.RequestLength(), + rq.Card32('context')) # Record_RC + _reply = rq.Struct( + rq.Pad(1), + rq.Card8('category'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card8('element_header'), # Record_Element_Header + rq.Bool('client_swapped'), + rq.Pad(2), + rq.Card32('id_base'), # Record_XIDBase + rq.Card32('server_time'), + rq.Card32('recorded_sequence_number'), + rq.Pad(8), + RawField('data')) + + # This request receives multiple responses, so we need to keep + # ourselves in the 'sent_requests' list in order to receive them all. + + # See the discussion on ListFonstsWithInfo in request.py + + def __init__(self, callback, *args, **keys): + self._callback = callback + rq.ReplyRequest.__init__(self, *args, **keys) + + def _parse_response(self, data): + r, d = self._reply.parse_binary(data, self._display) + self._callback(r) + + if r.category == StartOfData: + # Hack ourselves a sequence number, used by the code in + # Xlib.protocol.display.Display.parse_request_response() + self.sequence_number = r.sequence_number + + if r.category == EndOfData: + self._response_lock.acquire() + self._data = r + self._response_lock.release() + else: + self._display.sent_requests.insert(0, self) + +def enable_context(self, context, callback): + EnableContext( + callback = callback, + display = self.display, + opcode = self.display.get_extension_major(extname), + context = context) + + +class DisableContext(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(6), + rq.RequestLength(), + rq.Card32('context')) # Record_RC + +def disable_context(self, context): + DisableContext( + display = self.display, + opcode = self.display.get_extension_major(extname), + context = context) + + +class FreeContext(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(7), + rq.RequestLength(), + rq.Card32('context')) # Record_RC + +def free_context(self, context): + FreeContext( + display = self.display, + opcode = self.display.get_extension_major(extname), + context = context) + self.display.free_resource_id(context) + + +def init(disp, info): + disp.extension_add_method('display', 'record_get_version', get_version) + disp.extension_add_method('display', 'record_create_context', create_context) + disp.extension_add_method('display', 'record_register_clients', register_clients) + disp.extension_add_method('display', 'record_unregister_clients', unregister_clients) + disp.extension_add_method('display', 'record_get_context', get_context) + disp.extension_add_method('display', 'record_enable_context', enable_context) + disp.extension_add_method('display', 'record_disable_context', disable_context) + disp.extension_add_method('display', 'record_free_context', free_context) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/res.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/res.py new file mode 100644 index 0000000..810a3b9 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/res.py @@ -0,0 +1,288 @@ +# Xlib.ext.res -- X-Resource extension module +# +# Copyright (C) 2021 Aleksei Bavshin +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, +# Fifth Floor, +# Boston, MA 02110-1301 USA + +"""X-Resource extension allows a client to query the X server about its usage +of various resources. + +For detailed description see any of the following documents. +Protocol specification: + https://www.x.org/releases/current/doc/resourceproto/resproto.txt +XCB Protocol specification: + https://cgit.freedesktop.org/xcb/proto/tree/src/res.xml +""" +from Xlib.protocol import rq + +RES_MAJOR_VERSION = 1 +RES_MINOR_VERSION = 2 + +extname = "X-Resource" + +# v1.0 +ResQueryVersion = 0 +ResQueryClients = 1 +ResQueryClientResources = 2 +ResQueryClientPixmapBytes = 3 +# v1.2 +ResQueryClientIds = 4 +ResQueryResourceBytes = 5 + + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8("opcode"), + rq.Opcode(ResQueryVersion), + rq.RequestLength(), + rq.Card8("client_major"), + rq.Card8("client_minor"), + rq.Pad(2)) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16("sequence_number"), + rq.ReplyLength(), + rq.Card16("server_major"), + rq.Card16("server_minor"), + rq.Pad(20)) + + +def query_version(self, client_major=RES_MAJOR_VERSION, + client_minor=RES_MINOR_VERSION): + """ Query the protocol version supported by the X server. + + The client sends the highest supported version to the server and the + server sends the highest version it supports, but no higher than the + requested version.""" + return QueryVersion( + display=self.display, + opcode=self.display.get_extension_major(extname), + client_major=client_major, + client_minor=client_minor) + + +Client = rq.Struct( + rq.Card32("resource_base"), + rq.Card32("resource_mask")) + + +class QueryClients(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8("opcode"), + rq.Opcode(ResQueryClients), + rq.RequestLength()) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16("sequence_number"), + rq.ReplyLength(), + rq.LengthOf("clients", 4), + rq.Pad(20), + rq.List("clients", Client)) + + +def query_clients(self): + """Request the list of all currently connected clients.""" + return QueryClients( + display=self.display, + opcode=self.display.get_extension_major(extname)) + + +Type = rq.Struct( + rq.Card32("resource_type"), + rq.Card32("count")) + + +class QueryClientResources(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8("opcode"), + rq.Opcode(ResQueryClientResources), + rq.RequestLength(), + rq.Card32("client")) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16("sequence_number"), + rq.ReplyLength(), + rq.LengthOf("types", 4), + rq.Pad(20), + rq.List("types", Type)) + + +def query_client_resources(self, client): + """Request the number of resources owned by a client. + + The server will return the counts of each type of resource. + """ + return QueryClientResources( + display=self.display, + opcode=self.display.get_extension_major(extname), + client=client) + + +class QueryClientPixmapBytes(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8("opcode"), + rq.Opcode(ResQueryClientPixmapBytes), + rq.RequestLength(), + rq.Card32("client")) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16("sequence_number"), + rq.ReplyLength(), + rq.Card32("bytes"), + rq.Card32("bytes_overflow"), + rq.Pad(16)) + + +def query_client_pixmap_bytes(self, client): + """Query the pixmap usage of some client. + + The returned number is a sum of memory usage of each pixmap that can be + attributed to the given client. + """ + return QueryClientPixmapBytes( + display=self.display, + opcode=self.display.get_extension_major(extname), + client=client) + + +class SizeOf(rq.LengthOf): + """A SizeOf stores the size in bytes of some other Field whose size + may vary, e.g. List + """ + def __init__(self, name, size, item_size): + rq.LengthOf.__init__(self, name, size) + self.item_size = item_size + + def parse_value(self, length, display): + return length // self.item_size + + +ClientXIDMask = 1 << 0 +LocalClientPIDMask = 1 << 1 + + +ClientIdSpec = rq.Struct( + rq.Card32("client"), + rq.Card32("mask")) + + +ClientIdValue = rq.Struct( + rq.Object("spec", ClientIdSpec), + SizeOf("value", 4, 4), + rq.List("value", rq.Card32Obj)) + + +class QueryClientIds(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8("opcode"), + rq.Opcode(ResQueryClientIds), + rq.RequestLength(), + rq.LengthOf("specs", 4), + rq.List("specs", ClientIdSpec)) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16("sequence_number"), + rq.ReplyLength(), + rq.LengthOf("ids", 4), + rq.Pad(20), + rq.List("ids", ClientIdValue)) + + +def query_client_ids(self, specs): + """Request to identify a given set of clients with some identification method. + + The request sends a list of specifiers that select clients and + identification methods to server. The server then tries to identify the + chosen clients using the identification methods specified for each client. + The server returns IDs for those clients that were successfully identified. + """ + return QueryClientIds( + display=self.display, + opcode=self.display.get_extension_major(extname), + specs=specs) + + +ResourceIdSpec = rq.Struct( + rq.Card32("resource"), + rq.Card32("type")) + + +ResourceSizeSpec = rq.Struct( + # inline struct ResourceIdSpec to work around + # a parser bug with nested objects + rq.Card32("resource"), + rq.Card32("type"), + rq.Card32("bytes"), + rq.Card32("ref_count"), + rq.Card32("use_count")) + + +ResourceSizeValue = rq.Struct( + rq.Object("size", ResourceSizeSpec), + rq.LengthOf("cross_references", 4), + rq.List("cross_references", ResourceSizeSpec)) + + +class QueryResourceBytes(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8("opcode"), + rq.Opcode(ResQueryResourceBytes), + rq.RequestLength(), + rq.Card32("client"), + rq.LengthOf("specs", 4), + rq.List("specs", ResourceIdSpec)) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16("sequence_number"), + rq.ReplyLength(), + rq.LengthOf("sizes", 4), + rq.Pad(20), + rq.List("sizes", ResourceSizeValue)) + + +def query_resource_bytes(self, client, specs): + """Query the sizes of resources from X server. + + The request sends a list of specifiers that selects resources for size + calculation. The server tries to calculate the sizes of chosen resources + and returns an estimate for a resource only if the size could be determined + """ + return QueryResourceBytes( + display=self.display, + opcode=self.display.get_extension_major(extname), + client=client, + specs=specs) + + +def init(disp, info): + disp.extension_add_method("display", "res_query_version", query_version) + disp.extension_add_method("display", "res_query_clients", query_clients) + disp.extension_add_method("display", "res_query_client_resources", + query_client_resources) + disp.extension_add_method("display", "res_query_client_pixmap_bytes", + query_client_pixmap_bytes) + disp.extension_add_method("display", "res_query_client_ids", + query_client_ids) + disp.extension_add_method("display", "res_query_resource_bytes", + query_resource_bytes) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/screensaver.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/screensaver.py new file mode 100644 index 0000000..d6bad53 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/screensaver.py @@ -0,0 +1,198 @@ +# Xlib.ext.screensaver -- X ScreenSaver extension module +# +# Copyright (C) 2022 Vladimir Panteleev +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, +# Fifth Floor, +# Boston, MA 02110-1301 USA + +"""This extension allows registering the client as an X screensaver, +or query information about the current screensaver. + +For detailed description see any of the following documents. +Protocol specification: + https://www.x.org/releases/X11R7.7/doc/scrnsaverproto/saver.html +XCB Protocol specification: + https://cgit.freedesktop.org/xcb/proto/tree/src/screensaver.xml + +""" + +from Xlib import X +from Xlib.protocol import rq, structs + +extname = 'MIT-SCREEN-SAVER' + +# Event members +NotifyMask = 1 +CycleMask = 2 + +# Notify state +StateOff = 0 +StateOn = 1 +StateCycle = 2 + +# Notify kind +KindBlanked = 0 +KindInternal = 1 +KindExternal = 2 + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card8('major_version'), + rq.Card8('minor_version'), + rq.Pad(2), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + rq.Pad(20), + ) + +def query_version(self): + return QueryVersion(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=0) + + +class QueryInfo(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + rq.Drawable('drawable'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('state'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('saver_window'), + rq.Card32('til_or_since'), + rq.Card32('idle'), + rq.Card32('event_mask'), # rq.Set('event_mask', 4, (NotifyMask, CycleMask)), + rq.Card8('kind'), + rq.Pad(7), + ) + +def query_info(self): + return QueryInfo(display=self.display, + opcode=self.display.get_extension_major(extname), + drawable=self, + ) + + +class SelectInput(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.Card32('event_mask'), # rq.Set('event_mask', 4, (NotifyMask, CycleMask)), + ) + +def select_input(self, mask): + return SelectInput(display=self.display, + opcode=self.display.get_extension_major(extname), + drawable=self, + event_mask=mask, + ) + + +class SetAttributes(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('border_width'), + rq.Set('window_class', 1, (X.CopyFromParent, X.InputOutput, X.InputOnly)), + rq.Card8('depth'), + rq.Card32('visual'), + structs.WindowValues('attrs'), + ) + +def set_attributes(self, x, y, width, height, border_width, + window_class = X.CopyFromParent, + depth = X.CopyFromParent, + visual = X.CopyFromParent, + onerror = None, + **keys): + return SetAttributes(display=self.display, + onerror = onerror, + opcode=self.display.get_extension_major(extname), + drawable=self, + x = x, + y = y, + width = width, + height = height, + border_width = border_width, + window_class = window_class, + depth = depth, + visual = visual, + attrs = keys) + + +class UnsetAttributes(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + rq.Drawable('drawable'), + ) + +def unset_attributes(self, onerror = None): + return UnsetAttributes(display=self.display, + onerror = onerror, + opcode=self.display.get_extension_major(extname), + drawable=self) + + +class Notify(rq.Event): + _code = None + _fields = rq.Struct( + rq.Card8('type'), + rq.Set('state', 1, (StateOff, StateOn, StateCycle)), + rq.Card16('sequence_number'), + rq.Card32('timestamp'), + rq.Window('root'), + rq.Window('window'), + rq.Set('kind', 1, (KindBlanked, KindInternal, KindExternal)), + rq.Bool('forced'), + rq.Pad(14), + ) + +def init(disp, info): + disp.extension_add_method('display', 'screensaver_query_version', query_version) + disp.extension_add_method('drawable', 'screensaver_query_info', query_info) + disp.extension_add_method('drawable', 'screensaver_select_input', select_input) + disp.extension_add_method('drawable', 'screensaver_set_attributes', set_attributes) + disp.extension_add_method('drawable', 'screensaver_unset_attributes', unset_attributes) + + disp.extension_add_event(info.first_event + 0, Notify) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/security.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/security.py new file mode 100644 index 0000000..ea5070c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/security.py @@ -0,0 +1,139 @@ +# Xlib.ext.security -- SECURITY extension module +# +# Copyright (C) 2010-2013 Outpost Embedded, LLC +# Forest Bond +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +''' +A partial implementation of the SECURITY extension. Support for the +SecurityAuthorizationRevoked event is not implemented. +''' + +from Xlib.protocol import rq + + +extname = 'SECURITY' + + +SecurityClientTrusted = 0 +SecurityClientUntrusted = 1 + +SecurityAuthorizationRevokedMask = 1 + + +AUTHID = rq.Card32 + + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card16('major_version'), + rq.Card16('minor_version') + ) + _reply = rq.Struct(rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + rq.Pad(20) + ) + + +def query_version(self): + return QueryVersion(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=0) + + +class SecurityGenerateAuthorization(rq.ReplyRequest): + # The order of fields here does not match the specifications I've seen + # online, but it *does* match with the X.org implementation. I guess the + # spec is out-of-date. + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + rq.LengthOf('auth_proto', 2), + rq.LengthOf('auth_data', 2), + rq.Card32('value_mask'), + rq.String8('auth_proto'), + rq.Binary('auth_data'), + rq.List('values', rq.Card32Obj) + ) + _reply = rq.Struct(rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + AUTHID('authid'), + rq.LengthOf('auth_data_return', 2), + rq.Pad(18), + rq.Binary('auth_data_return') + ) + + +def generate_authorization(self, auth_proto, auth_data=b'', timeout=None, + trust_level=None, group=None, event_mask=None): + value_mask = 0 + values = [] + if timeout is not None: + value_mask |= 1 + values.append(timeout) + if trust_level is not None: + value_mask |= 2 + values.append(trust_level) + if group is not None: + value_mask |= 4 + values.append(group) + if event_mask is not None: + value_mask |= 8 + values.append(event_mask) + return SecurityGenerateAuthorization(display=self.display, + opcode=self.display.get_extension_major(extname), + value_mask=value_mask, + auth_proto=auth_proto, + auth_data=auth_data, + values=values) + + +class SecurityRevokeAuthorization(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + AUTHID('authid') + ) + + +def revoke_authorization(self, authid): + return SecurityRevokeAuthorization(display=self.display, + opcode=self.display.get_extension_major(extname), + authid=authid) + + +def init(disp, info): + disp.extension_add_method('display', + 'security_query_version', + query_version) + disp.extension_add_method('display', + 'security_generate_authorization', + generate_authorization) + disp.extension_add_method('display', + 'security_revoke_authorization', + revoke_authorization) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/shape.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/shape.py new file mode 100644 index 0000000..1fd440a --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/shape.py @@ -0,0 +1,297 @@ +# Automatically generated file; DO NOT EDIT. +# Generated from: /usr/share/xcb/shape.xml + +from Xlib.protocol import rq, structs + + +extname = 'SHAPE' + +OP = rq.Card8 + +class SO: + Set = 0 + Union = 1 + Intersect = 2 + Subtract = 3 + Invert = 4 + +class SK: + Bounding = 0 + Clip = 1 + Input = 2 + +class KIND(rq.Set): + + def __init__(self, name): + super(KIND, self).__init__(name, 1, + values=(SK.Bounding, + SK.Clip, + SK.Input)) + +class NotifyEventData(rq.Event): + _code = None + _fields = rq.Struct( + rq.Card8('type'), + KIND('shape_kind'), + rq.Card16('sequence_number'), + rq.Window('affected_window'), + rq.Int16('extents_x'), + rq.Int16('extents_y'), + rq.Card16('extents_width'), + rq.Card16('extents_height'), + rq.Card32('server_time'), + rq.Card8('shaped'), + rq.Pad(11), + ) + +class QueryVersion(rq.ReplyRequest): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + ) + +class Rectangles(rq.Request): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + OP('operation'), + KIND('destination_kind'), + rq.Card8('ordering'), + rq.Pad(1), + rq.Window('destination_window'), + rq.Int16('x_offset'), + rq.Int16('y_offset'), + rq.List('rectangles', structs.Rectangle, pad=0), + ) + +class Mask(rq.Request): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + OP('operation'), + KIND('destination_kind'), + rq.Pad(2), + rq.Window('destination_window'), + rq.Int16('x_offset'), + rq.Int16('y_offset'), + rq.Pixmap('source_bitmap'), + ) + +class Combine(rq.Request): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + OP('operation'), + KIND('destination_kind'), + KIND('source_kind'), + rq.Pad(1), + rq.Window('destination_window'), + rq.Int16('x_offset'), + rq.Int16('y_offset'), + rq.Window('source_window'), + ) + +class Offset(rq.Request): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + KIND('destination_kind'), + rq.Pad(3), + rq.Window('destination_window'), + rq.Int16('x_offset'), + rq.Int16('y_offset'), + ) + +class QueryExtents(rq.ReplyRequest): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(5), + rq.RequestLength(), + rq.Window('destination_window'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card8('bounding_shaped'), + rq.Card8('clip_shaped'), + rq.Pad(2), + rq.Int16('bounding_shape_extents_x'), + rq.Int16('bounding_shape_extents_y'), + rq.Card16('bounding_shape_extents_width'), + rq.Card16('bounding_shape_extents_height'), + rq.Int16('clip_shape_extents_x'), + rq.Int16('clip_shape_extents_y'), + rq.Card16('clip_shape_extents_width'), + rq.Card16('clip_shape_extents_height'), + ) + +class SelectInput(rq.Request): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(6), + rq.RequestLength(), + rq.Window('destination_window'), + rq.Card8('enable'), + rq.Pad(3), + ) + +class InputSelected(rq.ReplyRequest): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(7), + rq.RequestLength(), + rq.Window('destination_window'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('enabled'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + ) + +class GetRectangles(rq.ReplyRequest): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(8), + rq.RequestLength(), + rq.Window('window'), + KIND('source_kind'), + rq.Pad(3), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('ordering'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('rectangles', 4), + rq.Pad(20), + rq.List('rectangles', structs.Rectangle, pad=0), + ) + +class Event: + # Sub events. + Notify = 0 + +def combine(self, operation, destination_kind, source_kind, x_offset, y_offset): + Combine( + display=self.display, + opcode=self.display.get_extension_major(extname), + source_window=self, + operation=operation, + destination_kind=destination_kind, + source_kind=source_kind, + x_offset=x_offset, + y_offset=y_offset, + ) + +def get_rectangles(self, source_kind): + return GetRectangles( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + source_kind=source_kind, + ) + +def input_selected(self, ): + return InputSelected( + display=self.display, + opcode=self.display.get_extension_major(extname), + destination_window=self, + ) + +def mask(self, operation, destination_kind, x_offset, y_offset, source_bitmap): + Mask( + display=self.display, + opcode=self.display.get_extension_major(extname), + destination_window=self, + operation=operation, + destination_kind=destination_kind, + x_offset=x_offset, + y_offset=y_offset, + source_bitmap=source_bitmap, + ) + +def offset(self, destination_kind, x_offset, y_offset): + Offset( + display=self.display, + opcode=self.display.get_extension_major(extname), + destination_window=self, + destination_kind=destination_kind, + x_offset=x_offset, + y_offset=y_offset, + ) + +def query_extents(self, ): + return QueryExtents( + display=self.display, + opcode=self.display.get_extension_major(extname), + destination_window=self, + ) + +def query_version(self, ): + return QueryVersion( + display=self.display, + opcode=self.display.get_extension_major(extname), + ) + +def rectangles(self, operation, destination_kind, ordering, x_offset, y_offset, rectangles): + Rectangles( + display=self.display, + opcode=self.display.get_extension_major(extname), + destination_window=self, + operation=operation, + destination_kind=destination_kind, + ordering=ordering, + x_offset=x_offset, + y_offset=y_offset, + rectangles=rectangles, + ) + +def select_input(self, enable): + SelectInput( + display=self.display, + opcode=self.display.get_extension_major(extname), + destination_window=self, + enable=enable, + ) + +def init(disp, info): + disp.extension_add_method('window', 'shape_combine', combine) + disp.extension_add_method('window', 'shape_get_rectangles', get_rectangles) + disp.extension_add_method('window', 'shape_input_selected', input_selected) + disp.extension_add_method('window', 'shape_mask', mask) + disp.extension_add_method('window', 'shape_offset', offset) + disp.extension_add_method('window', 'shape_query_extents', query_extents) + disp.extension_add_method('display', 'shape_query_version', query_version) + disp.extension_add_method('window', 'shape_rectangles', rectangles) + disp.extension_add_method('window', 'shape_select_input', select_input) + disp.extension_add_event(info.first_event + Event.Notify, NotifyEventData, 'ShapeNotify') + diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xfixes.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xfixes.py new file mode 100644 index 0000000..a7cf35f --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xfixes.py @@ -0,0 +1,200 @@ +# Xlib.ext.xfixes -- XFIXES extension module +# +# Copyright (C) 2010-2011 Outpost Embedded, LLC +# Forest Bond +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +''' +A partial implementation of the XFIXES extension. Only the HideCursor and +ShowCursor requests and SelectionNotify events are provided. +''' + +from Xlib.protocol import rq + +extname = 'XFIXES' + +XFixesSelectionNotify = 0 +XFixesCursorNotify = 1 + +XFixesSetSelectionOwnerNotifyMask = (1 << 0) +XFixesSelectionWindowDestroyNotifyMask = (1 << 1) +XFixesSelectionClientCloseNotifyMask = (1 << 2) +XFixesDisplayCursorNotifyMask = (1 << 0) + +XFixesSetSelectionOwnerNotify = 0 +XFixesSelectionWindowDestroyNotify = 1 +XFixesSelectionClientCloseNotify = 2 +XFixesDisplayCursorNotify = 0 + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card32('major_version'), + rq.Card32('minor_version') + ) + _reply = rq.Struct(rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('major_version'), + rq.Card32('minor_version'), + rq.Pad(16) + ) + + +def query_version(self): + return QueryVersion(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=4, + minor_version=0) + + +class HideCursor(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(29), + rq.RequestLength(), + rq.Window('window') + ) + +def hide_cursor(self): + HideCursor(display=self.display, + opcode=self.display.get_extension_major(extname), + window=self) + + +class ShowCursor(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(30), + rq.RequestLength(), + rq.Window('window') + ) + + +def show_cursor(self): + ShowCursor(display=self.display, + opcode=self.display.get_extension_major(extname), + window=self) + +class SelectSelectionInput(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('selection'), + rq.Card32('mask') + ) + +def select_selection_input(self, window, selection, mask): + return SelectSelectionInput(opcode=self.display.get_extension_major(extname), + display=self.display, + window=window, + selection=selection, + mask=mask) + + +class SelectionNotify(rq.Event): + _code = None + _fields = rq.Struct(rq.Card8('type'), + rq.Card8('sub_code'), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Window('owner'), + rq.Card32('selection'), + rq.Card32('timestamp'), + rq.Card32('selection_timestamp'), + rq.Pad(8)) + + +class SetSelectionOwnerNotify(SelectionNotify): + pass + + +class SelectionWindowDestroyNotify(SelectionNotify): + pass + + +class SelectionClientCloseNotify(SelectionNotify): + pass + + +class SelectCursorInput(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('mask') + ) + +def select_cursor_input(self, window, mask): + return SelectCursorInput(opcode=self.display.get_extension_major(extname), + display=self.display, + window=window, + cursor_serial=0, + mask=mask) + + +class GetCursorImage(rq.ReplyRequest): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength() + ) + _reply = rq.Struct(rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('xhot'), + rq.Card16('yhot'), + rq.Card32('cursor_serial'), + rq.Pad(8), + rq.List('cursor_image', rq.Card32) + ) + +def get_cursor_image(self, window): + return GetCursorImage(opcode=self.display.get_extension_major(extname), + display=self.display, + ) + + +class DisplayCursorNotify(rq.Event): + _code = None + _fields = rq.Struct(rq.Card8('type'), + rq.Card8('sub_code'), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card32('cursor_serial'), + rq.Card32('timestamp')) + + +def init(disp, info): + disp.extension_add_method('display', 'xfixes_select_selection_input', select_selection_input) + disp.extension_add_method('display', 'xfixes_query_version', query_version) + disp.extension_add_method('window', 'xfixes_hide_cursor', hide_cursor) + disp.extension_add_method('window', 'xfixes_show_cursor', show_cursor) + disp.extension_add_method('display', 'xfixes_select_cursor_input', select_cursor_input) + disp.extension_add_method('display', 'xfixes_get_cursor_image', get_cursor_image) + + disp.extension_add_subevent(info.first_event + XFixesSelectionNotify, XFixesSetSelectionOwnerNotify, SetSelectionOwnerNotify) + disp.extension_add_subevent(info.first_event + XFixesSelectionNotify, XFixesSelectionWindowDestroyNotify, SelectionWindowDestroyNotify) + disp.extension_add_subevent(info.first_event + XFixesSelectionNotify, XFixesSelectionClientCloseNotify, SelectionClientCloseNotify) + disp.extension_add_subevent(info.first_event + XFixesCursorNotify, XFixesDisplayCursorNotify, DisplayCursorNotify) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xinerama.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xinerama.py new file mode 100644 index 0000000..eff1acd --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xinerama.py @@ -0,0 +1,222 @@ +# Xlib.ext.xinerama -- Xinerama extension module +# +# Copyright (C) 2006 Mike Meyer +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +"""Xinerama - provide access to the Xinerama extension information. + +There are at least there different - and mutually incomparable - +Xinerama extensions available. This uses the one bundled with XFree86 +4.6 and/or Xorg 6.9 in the ati/radeon driver. It uses the include +files from that X distribution, so should work with it as well. I +provide code for the lone Sun 1.0 request that isn't part of 1.1, but +this is untested because I don't have a server that implements it. + +The functions loosely follow the libXineram functions. Mostly, they +return an rq.Struct in lieu of passing in pointers that get data from +the rq.Struct crammed into them. The exception is isActive, which +returns the state information - because that's what libXinerama does.""" + + +from Xlib.protocol import rq, structs + +extname = 'XINERAMA' + + +class QueryVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card8('major_version'), + rq.Card8('minor_version'), + rq.Pad(2), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + rq.Pad(20), + ) + +def query_version(self): + return QueryVersion(display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=1, + minor_version=1) + + +class GetState(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + rq.Window('window'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Bool('state'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('window'), + rq.Pad(20), + ) + +def get_state(self): + return GetState(display=self.display, + opcode=self.display.get_extension_major(extname), + window=self.id, + ) + + +class GetScreenCount(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Window('window'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('screen_count'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('window'), + rq.Pad(20), + ) + +def get_screen_count(self): + return GetScreenCount(display=self.display, + opcode=self.display.get_extension_major(extname), + window=self.id, + ) + + +class GetScreenSize(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('screen'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Card32('length'), + rq.Card32('width'), + rq.Card32('height'), + rq.Window('window'), + rq.Card32('screen'), + rq.Pad(8), + ) + +def get_screen_size(self, screen_no): + """Returns the size of the given screen number""" + return GetScreenSize(display=self.display, + opcode=self.display.get_extension_major(extname), + window=self.id, + screen=screen_no, + ) + + +# IsActive is only available from Xinerama 1.1 and later. +# It should be used in preference to GetState. +class IsActive(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('state'), + rq.Pad(20), + ) + +def is_active(self): + r = IsActive(display=self.display, + opcode=self.display.get_extension_major(extname), + ) + return r.state + + +# QueryScreens is only available from Xinerama 1.1 and later +class QueryScreens(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(5), + rq.RequestLength(), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('number'), + rq.Pad(20), + rq.List('screens', structs.Rectangle), + ) + +def query_screens(self): + # Hmm. This one needs to read the screen data from the socket. Ooops... + return QueryScreens(display=self.display, + opcode=self.display.get_extension_major(extname), + ) + + +# GetInfo is only available from some Xinerama 1.0, and *NOT* later! Untested +class GetInfo(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(4), + rq.RequestLength(), + rq.Card32('visual'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('window'), + # An array of subwindow slots goes here. Bah. + ) + +def get_info(self, visual): + r = GetInfo(display=self.display, + opcode=self.display.get_extension_major(extname), + visual=visual) + +def init(disp, info): + disp.extension_add_method('display', 'xinerama_query_version', query_version) + disp.extension_add_method('window', 'xinerama_get_state', get_state) + disp.extension_add_method('window', 'xinerama_get_screen_count', get_screen_count) + disp.extension_add_method('window', 'xinerama_get_screen_size', get_screen_size) + disp.extension_add_method('display', 'xinerama_is_active', is_active) + disp.extension_add_method('display', 'xinerama_query_screens', query_screens) + disp.extension_add_method('display', 'xinerama_get_info', get_info) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xinput.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xinput.py new file mode 100644 index 0000000..95560dd --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xinput.py @@ -0,0 +1,777 @@ +# Xlib.ext.xinput -- XInput extension module +# +# Copyright (C) 2012 Outpost Embedded, LLC +# Forest Bond +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +''' +A very incomplete implementation of the XInput extension. +''' + +import sys +import array +import struct + +# Python 2/3 compatibility. +from six import integer_types + +from Xlib.protocol import rq +from Xlib import X + + +extname = 'XInputExtension' + +PropertyDeleted = 0 +PropertyCreated = 1 +PropertyModified = 2 + +NotifyNormal = 0 +NotifyGrab = 1 +NotifyUngrab = 2 +NotifyWhileGrabbed = 3 +NotifyPassiveGrab = 4 +NotifyPassiveUngrab = 5 + +NotifyAncestor = 0 +NotifyVirtual = 1 +NotifyInferior = 2 +NotifyNonlinear = 3 +NotifyNonlinearVirtual = 4 +NotifyPointer = 5 +NotifyPointerRoot = 6 +NotifyDetailNone = 7 + +GrabtypeButton = 0 +GrabtypeKeycode = 1 +GrabtypeEnter = 2 +GrabtypeFocusIn = 3 +GrabtypeTouchBegin = 4 + +AnyModifier = (1 << 31) +AnyButton = 0 +AnyKeycode = 0 + +AsyncDevice = 0 +SyncDevice = 1 +ReplayDevice = 2 +AsyncPairedDevice = 3 +AsyncPair = 4 +SyncPair = 5 + +SlaveSwitch = 1 +DeviceChange = 2 + +MasterAdded = (1 << 0) +MasterRemoved = (1 << 1) +SlaveAdded = (1 << 2) +SlaveRemoved = (1 << 3) +SlaveAttached = (1 << 4) +SlaveDetached = (1 << 5) +DeviceEnabled = (1 << 6) +DeviceDisabled = (1 << 7) + +AddMaster = 1 +RemoveMaster = 2 +AttachSlave = 3 +DetachSlave = 4 + +AttachToMaster = 1 +Floating = 2 + +ModeRelative = 0 +ModeAbsolute = 1 + +MasterPointer = 1 +MasterKeyboard = 2 +SlavePointer = 3 +SlaveKeyboard = 4 +FloatingSlave = 5 + +KeyClass = 0 +ButtonClass = 1 +ValuatorClass = 2 +ScrollClass = 3 +TouchClass = 8 + +KeyRepeat = (1 << 16) + +AllDevices = 0 +AllMasterDevices = 1 + +DeviceChanged = 1 +KeyPress = 2 +KeyRelease = 3 +ButtonPress = 4 +ButtonRelease = 5 +Motion = 6 +Enter = 7 +Leave = 8 +FocusIn = 9 +FocusOut = 10 +HierarchyChanged = 11 +PropertyEvent = 12 +RawKeyPress = 13 +RawKeyRelease = 14 +RawButtonPress = 15 +RawButtonRelease = 16 +RawMotion = 17 + +DeviceChangedMask = (1 << DeviceChanged) +KeyPressMask = (1 << KeyPress) +KeyReleaseMask = (1 << KeyRelease) +ButtonPressMask = (1 << ButtonPress) +ButtonReleaseMask = (1 << ButtonRelease) +MotionMask = (1 << Motion) +EnterMask = (1 << Enter) +LeaveMask = (1 << Leave) +FocusInMask = (1 << FocusIn) +FocusOutMask = (1 << FocusOut) +HierarchyChangedMask = (1 << HierarchyChanged) +PropertyEventMask = (1 << PropertyEvent) +RawKeyPressMask = (1 << RawKeyPress) +RawKeyReleaseMask = (1 << RawKeyRelease) +RawButtonPressMask = (1 << RawButtonPress) +RawButtonReleaseMask = (1 << RawButtonRelease) +RawMotionMask = (1 << RawMotion) + +GrabModeSync = 0 +GrabModeAsync = 1 +GrabModeTouch = 2 + +DEVICEID = rq.Card16 +DEVICE = rq.Card16 +DEVICEUSE = rq.Card8 + +PROPERTY_TYPE_FLOAT = 'FLOAT' + +class FP1616(rq.Int32): + + def check_value(self, value): + return int(value * 65536.0) + + def parse_value(self, value, display): + return float(value) / float(1 << 16) + +class FP3232(rq.ValueField): + structcode = 'lL' + structvalues = 2 + + def check_value(self, value): + return value + + def parse_value(self, value, display): + integral, frac = value + ret = float(integral) + # optimised math.ldexp(float(frac), -32) + ret += float(frac) * (1.0 / (1 << 32)) + return ret + +class XIQueryVersion(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(47), + rq.RequestLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + ) + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('major_version'), + rq.Card16('minor_version'), + rq.Pad(20), + ) + + +def query_version(self): + return XIQueryVersion( + display=self.display, + opcode=self.display.get_extension_major(extname), + major_version=2, + minor_version=0, + ) + +class Mask(rq.List): + + def __init__(self, name): + rq.List.__init__(self, name, rq.Card32, pad=0) + + def pack_value(self, val): + + mask_seq = array.array(rq.struct_to_array_codes['L']) + + if isinstance(val, integer_types): + # We need to build a "binary mask" that (as far as I can tell) is + # encoded in native byte order from end to end. The simple case is + # with a single unsigned 32-bit value, for which we construct an + # array with just one item. For values too big to fit inside 4 + # bytes we build a longer array, being careful to maintain native + # byte order across the entire set of values. + if sys.byteorder == 'little': + def fun(val): + mask_seq.insert(0, val) + elif sys.byteorder == 'big': + fun = mask_seq.append + else: + raise AssertionError(sys.byteorder) + while val: + fun(val & 0xFFFFFFFF) + val = val >> 32 + else: + mask_seq.extend(val) + + return rq.encode_array(mask_seq), len(mask_seq), None + +EventMask = rq.Struct( + DEVICE('deviceid'), + rq.LengthOf('mask', 2), + Mask('mask'), +) + + +class XISelectEvents(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(46), + rq.RequestLength(), + rq.Window('window'), + rq.LengthOf('masks', 2), + rq.Pad(2), + rq.List('masks', EventMask), + ) + +def select_events(self, event_masks): + ''' + select_events(event_masks) + + event_masks: + Sequence of (deviceid, mask) pairs, where deviceid is a numerical device + ID, or AllDevices or AllMasterDevices, and mask is either an unsigned + integer or sequence of 32 bits unsigned values + ''' + return XISelectEvents( + display=self.display, + opcode=self.display.get_extension_major(extname), + window=self, + masks=event_masks, + ) + +AnyInfo = rq.Struct( + rq.Card16('type'), + rq.Card16('length'), + rq.Card16('sourceid'), + rq.Pad(2), +) + +class ButtonMask(object): + + def __init__(self, value, length): + self._value = value + self._length = length + + def __len__(self): + return self._length + + def __getitem__(self, key): + return self._value & (1 << key) + + def __str__(self): + return repr(self) + + def __repr__(self): + return '0b{value:0{width}b}'.format(value=self._value, + width=self._length) + +class ButtonState(rq.ValueField): + + structcode = None + + def __init__(self, name): + rq.ValueField.__init__(self, name) + + def parse_binary_value(self, data, display, length, fmt): + # Mask: bitfield of button states. + mask_len = 4 * ((((length + 7) >> 3) + 3) >> 2) + mask_data = data[:mask_len] + mask_value = 0 + for byte in reversed(struct.unpack('={0:d}B'.format(mask_len), mask_data)): + mask_value <<= 8 + mask_value |= byte + data = data[mask_len:] + assert (mask_value & 1) == 0 + return ButtonMask(mask_value >> 1, length), data + +ButtonInfo = rq.Struct( + rq.Card16('type'), + rq.Card16('length'), + rq.Card16('sourceid'), + rq.LengthOf(('state', 'labels'), 2), + ButtonState('state'), + rq.List('labels', rq.Card32), +) + +KeyInfo = rq.Struct( + rq.Card16('type'), + rq.Card16('length'), + rq.Card16('sourceid'), + rq.LengthOf('keycodes', 2), + rq.List('keycodes', rq.Card32), +) + +ValuatorInfo = rq.Struct( + rq.Card16('type'), + rq.Card16('length'), + rq.Card16('sourceid'), + rq.Card16('number'), + rq.Card32('label'), + FP3232('min'), + FP3232('max'), + FP3232('value'), + rq.Card32('resolution'), + rq.Card8('mode'), + rq.Pad(3), +) + +ScrollInfo = rq.Struct( + rq.Card16('type'), + rq.Card16('length'), + rq.Card16('sourceid'), + rq.Card16('number'), + rq.Card16('scroll_type'), + rq.Pad(2), + rq.Card32('flags'), + FP3232('increment'), +) + +TouchInfo = rq.Struct( + rq.Card16('type'), + rq.Card16('length'), + rq.Card16('sourceid'), + rq.Card8('mode'), + rq.Card8('num_touches'), +) + +INFO_CLASSES = { + KeyClass: KeyInfo, + ButtonClass: ButtonInfo, + ValuatorClass: ValuatorInfo, + ScrollClass: ScrollInfo, + TouchClass: TouchInfo, +} + +class ClassInfoClass(object): + + structcode = None + + def parse_binary(self, data, display): + class_type, length = struct.unpack('=HH', data[:4]) + class_struct = INFO_CLASSES.get(class_type, AnyInfo) + class_data, _ = class_struct.parse_binary(data, display) + data = data[length * 4:] + return class_data, data + +ClassInfo = ClassInfoClass() + +DeviceInfo = rq.Struct( + DEVICEID('deviceid'), + rq.Card16('use'), + rq.Card16('attachment'), + rq.LengthOf('classes', 2), + rq.LengthOf('name', 2), + rq.Bool('enabled'), + rq.Pad(1), + rq.String8('name', 4), + rq.List('classes', ClassInfo), +) + +class XIQueryDevice(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(48), + rq.RequestLength(), + DEVICEID('deviceid'), + rq.Pad(2), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('devices', 2), + rq.Pad(22), + rq.List('devices', DeviceInfo), + ) + +def query_device(self, deviceid): + return XIQueryDevice( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + ) + +class XIListProperties(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(56), + rq.RequestLength(), + DEVICEID('deviceid'), + rq.Pad(2), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('atoms', 2), + rq.Pad(22), + rq.List('atoms', rq.Card32Obj), + ) + +def list_device_properties(self, deviceid): + return XIListProperties( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + ) + +class XIGetProperty(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(59), + rq.RequestLength(), + DEVICEID('deviceid'), + rq.Card8('delete'), + rq.Pad(1), + rq.Card32('property'), + rq.Card32('type'), + rq.Card32('offset'), + rq.Card32('length'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('type'), + rq.Card32('bytes_after'), + rq.LengthOf('value', 4), + rq.Format('value', 1), + rq.Pad(11), + rq.PropertyData('value') + ) + +def get_device_property(self, deviceid, property, type, offset, length, delete=False): + return XIGetProperty( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + property=property, + type=type, + offset=offset, + length=length, + delete=delete, + ) + +class XIChangeProperty(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(57), + rq.RequestLength(), + DEVICEID('deviceid'), + rq.Card8('mode'), + rq.Format('value', 1), + rq.Card32('property'), + rq.Card32('type'), + rq.LengthOf('value', 4), + rq.PropertyData('value'), + ) + +def change_device_property(self, deviceid, property, type, mode, value): + return XIChangeProperty( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + property=property, + type=type, + mode=mode, + value=value, + ) + +class XIDeleteProperty(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(58), + rq.RequestLength(), + DEVICEID('deviceid'), + rq.Pad(2), + rq.Card32('property'), + ) + +def delete_device_property(self, deviceid, property): + return XIDeleteProperty( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + property=property, + ) + +class XIGrabDevice(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(51), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card32('time'), + rq.Cursor('cursor', (X.NONE, )), + DEVICEID('deviceid'), + rq.Set('grab_mode', 1, (GrabModeSync, GrabModeAsync)), + rq.Set('paired_device_mode', 1, (GrabModeSync, GrabModeAsync)), + rq.Bool('owner_events'), + rq.Pad(1), + rq.LengthOf('mask', 2), + Mask('mask'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card8('status'), + rq.Pad(23), + ) + +def grab_device(self, deviceid, time, grab_mode, paired_device_mode, owner_events, event_mask): + return XIGrabDevice( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + grab_window=self, + time=time, + cursor=X.NONE, + grab_mode=grab_mode, + paired_device_mode=paired_device_mode, + owner_events=owner_events, + mask=event_mask, + ) + +class XIUngrabDevice(rq.Request): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(52), + rq.RequestLength(), + rq.Card32('time'), + DEVICEID('deviceid'), + rq.Pad(2), + ) + +def ungrab_device(self, deviceid, time): + return XIUngrabDevice( + display=self.display, + opcode=self.display.get_extension_major(extname), + time=time, + deviceid=deviceid, + ) + +class XIPassiveGrabDevice(rq.ReplyRequest): + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(54), + rq.RequestLength(), + rq.Card32('time'), + rq.Window('grab_window'), + rq.Cursor('cursor', (X.NONE, )), + rq.Card32('detail'), + DEVICEID('deviceid'), + rq.LengthOf('modifiers', 2), + rq.LengthOf('mask', 2), + rq.Set('grab_type', 1, (GrabtypeButton, GrabtypeKeycode, GrabtypeEnter, + GrabtypeFocusIn, GrabtypeTouchBegin)), + rq.Set('grab_mode', 1, (GrabModeSync, GrabModeAsync)), + rq.Set('paired_device_mode', 1, (GrabModeSync, GrabModeAsync)), + rq.Bool('owner_events'), + rq.Pad(2), + Mask('mask'), + rq.List('modifiers', rq.Card32), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('modifiers', 2), + rq.Pad(22), + rq.List('modifiers', rq.Card32), + ) + +def passive_grab_device(self, deviceid, time, detail, + grab_type, grab_mode, paired_device_mode, + owner_events, event_mask, modifiers): + return XIPassiveGrabDevice( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + grab_window=self, + time=time, + cursor=X.NONE, + detail=detail, + grab_type=grab_type, + grab_mode=grab_mode, + paired_device_mode=paired_device_mode, + owner_events=owner_events, + mask=event_mask, + modifiers=modifiers, + ) + +def grab_keycode(self, deviceid, time, keycode, + grab_mode, paired_device_mode, + owner_events, event_mask, modifiers): + return passive_grab_device(self, deviceid, time, keycode, + GrabtypeKeycode, + grab_mode, paired_device_mode, + owner_events, event_mask, modifiers) + +class XIPassiveUngrabDevice(rq.Request): + + _request = rq.Struct( + rq.Card8('opcode'), + rq.Opcode(55), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card32('detail'), + DEVICEID('deviceid'), + rq.LengthOf('modifiers', 2), + rq.Set('grab_type', 1, (GrabtypeButton, GrabtypeKeycode, + GrabtypeEnter, GrabtypeFocusIn, + GrabtypeTouchBegin)), + rq.Pad(3), + rq.List('modifiers', rq.Card32), + ) + +def passive_ungrab_device(self, deviceid, detail, grab_type, modifiers): + return XIPassiveUngrabDevice( + display=self.display, + opcode=self.display.get_extension_major(extname), + deviceid=deviceid, + grab_window=self, + detail=detail, + grab_type=grab_type, + modifiers=modifiers, + ) + +def ungrab_keycode(self, deviceid, keycode, modifiers): + return passive_ungrab_device(self, deviceid, keycode, + GrabtypeKeycode, modifiers) + +HierarchyInfo = rq.Struct( + DEVICEID('deviceid'), + DEVICEID('attachment'), + DEVICEUSE('type'), + rq.Bool('enabled'), + rq.Pad(2), + rq.Card32('flags'), +) + + +HierarchyEventData = rq.Struct( + DEVICEID('deviceid'), + rq.Card32('time'), + rq.Card32('flags'), + rq.LengthOf('info', 2), + rq.Pad(10), + rq.List('info', HierarchyInfo), +) + +ModifierInfo = rq.Struct( + rq.Card32('base_mods'), + rq.Card32('latched_mods'), + rq.Card32('locked_mods'), + rq.Card32('effective_mods'), +) + +GroupInfo = rq.Struct( + rq.Card8('base_group'), + rq.Card8('latched_group'), + rq.Card8('locked_group'), + rq.Card8('effective_group'), +) + +DeviceEventData = rq.Struct( + DEVICEID('deviceid'), + rq.Card32('time'), + rq.Card32('detail'), + rq.Window('root'), + rq.Window('event'), + rq.Window('child'), + FP1616('root_x'), + FP1616('root_y'), + FP1616('event_x'), + FP1616('event_y'), + rq.LengthOf('buttons', 2), + rq.Card16('valulators_len'), + DEVICEID('sourceid'), + rq.Pad(2), + rq.Card32('flags'), + rq.Object('mods', ModifierInfo), + rq.Object('groups', GroupInfo), + ButtonState('buttons'), +) + +DeviceChangedEventData = rq.Struct( + DEVICEID('deviceid'), + rq.Card32('time'), + rq.LengthOf('classes', 2), + DEVICEID('sourceid'), + rq.Card8('reason'), + rq.Pad(11), + rq.List('classes', ClassInfo), +) + +PropertyEventData = rq.Struct( + DEVICEID('deviceid'), + rq.Card32('time'), + rq.Card32('property'), + rq.Card8('what'), + rq.Pad(11), +) + +def init(disp, info): + disp.extension_add_method('display', 'xinput_query_version', query_version) + disp.extension_add_method('window', 'xinput_select_events', select_events) + disp.extension_add_method('display', 'xinput_query_device', query_device) + disp.extension_add_method('window', 'xinput_grab_device', grab_device) + disp.extension_add_method('display', 'xinput_ungrab_device', ungrab_device) + disp.extension_add_method('window', 'xinput_grab_keycode', grab_keycode) + disp.extension_add_method('window', 'xinput_ungrab_keycode', ungrab_keycode) + disp.extension_add_method('display', 'xinput_get_device_property', get_device_property) + disp.extension_add_method('display', 'xinput_list_device_properties', list_device_properties) + disp.extension_add_method('display', 'xinput_change_device_property', change_device_property) + disp.extension_add_method('display', 'xinput_delete_device_property', delete_device_property) + if hasattr(disp,"ge_add_event_data"): + for device_event in (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion): + disp.ge_add_event_data(info.major_opcode, device_event, DeviceEventData) + disp.ge_add_event_data(info.major_opcode, DeviceChanged, DeviceEventData) + disp.ge_add_event_data(info.major_opcode, HierarchyChanged, HierarchyEventData) + disp.ge_add_event_data(info.major_opcode, PropertyEvent, PropertyEventData) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xtest.py b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xtest.py new file mode 100644 index 0000000..0b5d7da --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/ext/xtest.py @@ -0,0 +1,122 @@ +# Xlib.ext.xtest -- XTEST extension module +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib import X +from Xlib.protocol import rq + +extname = 'XTEST' + +CurrentCursor = 1 + +class GetVersion(rq.ReplyRequest): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(0), + rq.RequestLength(), + rq.Card8('major_version'), + rq.Pad(1), + rq.Card16('minor_version') + ) + + _reply = rq.Struct(rq.Pad(1), + rq.Card8('major_version'), + rq.Card16('sequence_number'), + rq.Pad(4), + rq.Card16('minor_version'), + rq.Pad(22) + ) + +def get_version(self, major, minor): + return GetVersion(display = self.display, + opcode = self.display.get_extension_major(extname), + major_version = major, + minor_version = minor) + + +class CompareCursor(rq.ReplyRequest): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(1), + rq.RequestLength(), + rq.Window('window'), + rq.Cursor('cursor', (X.NONE, CurrentCursor)), + ) + + _reply = rq.Struct(rq.Pad(1), + rq.Card8('same'), + rq.Card16('sequence_number'), + rq.Pad(28), + ) + +def compare_cursor(self, cursor): + r = CompareCursor(display = self.display, + opcode = self.display.get_extension_major(extname), + window = self.id, + cursor = cursor) + return r.same + +class FakeInput(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(2), + rq.RequestLength(), + rq.Set('event_type', 1, (X.KeyPress, + X.KeyRelease, + X.ButtonPress, + X.ButtonRelease, + X.MotionNotify)), + rq.Card8('detail'), + rq.Pad(2), + rq.Card32('time'), + rq.Window('root', (X.NONE, )), + rq.Pad(8), + rq.Int16('x'), + rq.Int16('y'), + rq.Pad(8) + ) + +def fake_input(self, event_type, detail = 0, time = X.CurrentTime, + root = X.NONE, x = 0, y = 0): + + FakeInput(display = self.display, + opcode = self.display.get_extension_major(extname), + event_type = event_type, + detail = detail, + time = time, + root = root, + x = x, + y = y) + +class GrabControl(rq.Request): + _request = rq.Struct(rq.Card8('opcode'), + rq.Opcode(3), + rq.RequestLength(), + rq.Bool('impervious'), + rq.Pad(3) + ) + +def grab_control(self, impervious): + GrabControl(display = self.display, + opcode = self.display.get_extension_major(extname), + impervious = impervious) + +def init(disp, info): + disp.extension_add_method('display', 'xtest_get_version', get_version) + disp.extension_add_method('window', 'xtest_compare_cursor', compare_cursor) + disp.extension_add_method('display', 'xtest_fake_input', fake_input) + disp.extension_add_method('display', 'xtest_grab_control', grab_control) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__init__.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__init__.py new file mode 100644 index 0000000..6c7ebb2 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__init__.py @@ -0,0 +1,42 @@ +# Xlib.keysymdef -- X keysym defs +# +# Copyright (C) 2001 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +__all__ = [ + 'apl', + 'arabic', + 'cyrillic', + 'greek', + 'hebrew', + 'katakana', + 'korean', + 'latin1', + 'latin2', + 'latin3', + 'latin4', + 'miscellany', + 'publishing', + 'special', + 'technical', + 'thai', + 'xf86', + 'xk3270', + 'xkb', + ] diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..b300551 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/apl.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/apl.cpython-312.pyc new file mode 100644 index 0000000..d723dda Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/apl.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/arabic.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/arabic.cpython-312.pyc new file mode 100644 index 0000000..a46e124 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/arabic.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/cyrillic.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/cyrillic.cpython-312.pyc new file mode 100644 index 0000000..12993fd Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/cyrillic.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/greek.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/greek.cpython-312.pyc new file mode 100644 index 0000000..a36e7c1 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/greek.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/hebrew.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/hebrew.cpython-312.pyc new file mode 100644 index 0000000..752d73e Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/hebrew.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/katakana.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/katakana.cpython-312.pyc new file mode 100644 index 0000000..0b5a98c Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/katakana.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/korean.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/korean.cpython-312.pyc new file mode 100644 index 0000000..f48e4b1 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/korean.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin1.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin1.cpython-312.pyc new file mode 100644 index 0000000..dd413c9 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin1.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin2.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin2.cpython-312.pyc new file mode 100644 index 0000000..c9c9b5c Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin2.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin3.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin3.cpython-312.pyc new file mode 100644 index 0000000..2f1903c Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin3.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin4.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin4.cpython-312.pyc new file mode 100644 index 0000000..abb5023 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/latin4.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/miscellany.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/miscellany.cpython-312.pyc new file mode 100644 index 0000000..b1f12cd Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/miscellany.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/publishing.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/publishing.cpython-312.pyc new file mode 100644 index 0000000..5c59299 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/publishing.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/special.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/special.cpython-312.pyc new file mode 100644 index 0000000..2165ffe Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/special.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/technical.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/technical.cpython-312.pyc new file mode 100644 index 0000000..d5ed1ba Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/technical.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/thai.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/thai.cpython-312.pyc new file mode 100644 index 0000000..9c1c262 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/thai.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xf86.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xf86.cpython-312.pyc new file mode 100644 index 0000000..63b2bdb Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xf86.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xk3270.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xk3270.cpython-312.pyc new file mode 100644 index 0000000..f590ceb Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xk3270.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xkb.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xkb.cpython-312.pyc new file mode 100644 index 0000000..c787a85 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/__pycache__/xkb.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/apl.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/apl.py new file mode 100644 index 0000000..f503d42 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/apl.py @@ -0,0 +1,19 @@ +XK_leftcaret = 0xba3 +XK_rightcaret = 0xba6 +XK_downcaret = 0xba8 +XK_upcaret = 0xba9 +XK_overbar = 0xbc0 +XK_downtack = 0xbc2 +XK_upshoe = 0xbc3 +XK_downstile = 0xbc4 +XK_underbar = 0xbc6 +XK_jot = 0xbca +XK_quad = 0xbcc +XK_uptack = 0xbce +XK_circle = 0xbcf +XK_upstile = 0xbd3 +XK_downshoe = 0xbd6 +XK_rightshoe = 0xbd8 +XK_leftshoe = 0xbda +XK_lefttack = 0xbdc +XK_righttack = 0xbfc diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/arabic.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/arabic.py new file mode 100644 index 0000000..2eedb71 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/arabic.py @@ -0,0 +1,50 @@ +XK_Arabic_comma = 0x5ac +XK_Arabic_semicolon = 0x5bb +XK_Arabic_question_mark = 0x5bf +XK_Arabic_hamza = 0x5c1 +XK_Arabic_maddaonalef = 0x5c2 +XK_Arabic_hamzaonalef = 0x5c3 +XK_Arabic_hamzaonwaw = 0x5c4 +XK_Arabic_hamzaunderalef = 0x5c5 +XK_Arabic_hamzaonyeh = 0x5c6 +XK_Arabic_alef = 0x5c7 +XK_Arabic_beh = 0x5c8 +XK_Arabic_tehmarbuta = 0x5c9 +XK_Arabic_teh = 0x5ca +XK_Arabic_theh = 0x5cb +XK_Arabic_jeem = 0x5cc +XK_Arabic_hah = 0x5cd +XK_Arabic_khah = 0x5ce +XK_Arabic_dal = 0x5cf +XK_Arabic_thal = 0x5d0 +XK_Arabic_ra = 0x5d1 +XK_Arabic_zain = 0x5d2 +XK_Arabic_seen = 0x5d3 +XK_Arabic_sheen = 0x5d4 +XK_Arabic_sad = 0x5d5 +XK_Arabic_dad = 0x5d6 +XK_Arabic_tah = 0x5d7 +XK_Arabic_zah = 0x5d8 +XK_Arabic_ain = 0x5d9 +XK_Arabic_ghain = 0x5da +XK_Arabic_tatweel = 0x5e0 +XK_Arabic_feh = 0x5e1 +XK_Arabic_qaf = 0x5e2 +XK_Arabic_kaf = 0x5e3 +XK_Arabic_lam = 0x5e4 +XK_Arabic_meem = 0x5e5 +XK_Arabic_noon = 0x5e6 +XK_Arabic_ha = 0x5e7 +XK_Arabic_heh = 0x5e7 +XK_Arabic_waw = 0x5e8 +XK_Arabic_alefmaksura = 0x5e9 +XK_Arabic_yeh = 0x5ea +XK_Arabic_fathatan = 0x5eb +XK_Arabic_dammatan = 0x5ec +XK_Arabic_kasratan = 0x5ed +XK_Arabic_fatha = 0x5ee +XK_Arabic_damma = 0x5ef +XK_Arabic_kasra = 0x5f0 +XK_Arabic_shadda = 0x5f1 +XK_Arabic_sukun = 0x5f2 +XK_Arabic_switch = 0xFF7E diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/cyrillic.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/cyrillic.py new file mode 100644 index 0000000..60f804d --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/cyrillic.py @@ -0,0 +1,107 @@ +XK_Serbian_dje = 0x6a1 +XK_Macedonia_gje = 0x6a2 +XK_Cyrillic_io = 0x6a3 +XK_Ukrainian_ie = 0x6a4 +XK_Ukranian_je = 0x6a4 +XK_Macedonia_dse = 0x6a5 +XK_Ukrainian_i = 0x6a6 +XK_Ukranian_i = 0x6a6 +XK_Ukrainian_yi = 0x6a7 +XK_Ukranian_yi = 0x6a7 +XK_Cyrillic_je = 0x6a8 +XK_Serbian_je = 0x6a8 +XK_Cyrillic_lje = 0x6a9 +XK_Serbian_lje = 0x6a9 +XK_Cyrillic_nje = 0x6aa +XK_Serbian_nje = 0x6aa +XK_Serbian_tshe = 0x6ab +XK_Macedonia_kje = 0x6ac +XK_Byelorussian_shortu = 0x6ae +XK_Cyrillic_dzhe = 0x6af +XK_Serbian_dze = 0x6af +XK_numerosign = 0x6b0 +XK_Serbian_DJE = 0x6b1 +XK_Macedonia_GJE = 0x6b2 +XK_Cyrillic_IO = 0x6b3 +XK_Ukrainian_IE = 0x6b4 +XK_Ukranian_JE = 0x6b4 +XK_Macedonia_DSE = 0x6b5 +XK_Ukrainian_I = 0x6b6 +XK_Ukranian_I = 0x6b6 +XK_Ukrainian_YI = 0x6b7 +XK_Ukranian_YI = 0x6b7 +XK_Cyrillic_JE = 0x6b8 +XK_Serbian_JE = 0x6b8 +XK_Cyrillic_LJE = 0x6b9 +XK_Serbian_LJE = 0x6b9 +XK_Cyrillic_NJE = 0x6ba +XK_Serbian_NJE = 0x6ba +XK_Serbian_TSHE = 0x6bb +XK_Macedonia_KJE = 0x6bc +XK_Byelorussian_SHORTU = 0x6be +XK_Cyrillic_DZHE = 0x6bf +XK_Serbian_DZE = 0x6bf +XK_Cyrillic_yu = 0x6c0 +XK_Cyrillic_a = 0x6c1 +XK_Cyrillic_be = 0x6c2 +XK_Cyrillic_tse = 0x6c3 +XK_Cyrillic_de = 0x6c4 +XK_Cyrillic_ie = 0x6c5 +XK_Cyrillic_ef = 0x6c6 +XK_Cyrillic_ghe = 0x6c7 +XK_Cyrillic_ha = 0x6c8 +XK_Cyrillic_i = 0x6c9 +XK_Cyrillic_shorti = 0x6ca +XK_Cyrillic_ka = 0x6cb +XK_Cyrillic_el = 0x6cc +XK_Cyrillic_em = 0x6cd +XK_Cyrillic_en = 0x6ce +XK_Cyrillic_o = 0x6cf +XK_Cyrillic_pe = 0x6d0 +XK_Cyrillic_ya = 0x6d1 +XK_Cyrillic_er = 0x6d2 +XK_Cyrillic_es = 0x6d3 +XK_Cyrillic_te = 0x6d4 +XK_Cyrillic_u = 0x6d5 +XK_Cyrillic_zhe = 0x6d6 +XK_Cyrillic_ve = 0x6d7 +XK_Cyrillic_softsign = 0x6d8 +XK_Cyrillic_yeru = 0x6d9 +XK_Cyrillic_ze = 0x6da +XK_Cyrillic_sha = 0x6db +XK_Cyrillic_e = 0x6dc +XK_Cyrillic_shcha = 0x6dd +XK_Cyrillic_che = 0x6de +XK_Cyrillic_hardsign = 0x6df +XK_Cyrillic_YU = 0x6e0 +XK_Cyrillic_A = 0x6e1 +XK_Cyrillic_BE = 0x6e2 +XK_Cyrillic_TSE = 0x6e3 +XK_Cyrillic_DE = 0x6e4 +XK_Cyrillic_IE = 0x6e5 +XK_Cyrillic_EF = 0x6e6 +XK_Cyrillic_GHE = 0x6e7 +XK_Cyrillic_HA = 0x6e8 +XK_Cyrillic_I = 0x6e9 +XK_Cyrillic_SHORTI = 0x6ea +XK_Cyrillic_KA = 0x6eb +XK_Cyrillic_EL = 0x6ec +XK_Cyrillic_EM = 0x6ed +XK_Cyrillic_EN = 0x6ee +XK_Cyrillic_O = 0x6ef +XK_Cyrillic_PE = 0x6f0 +XK_Cyrillic_YA = 0x6f1 +XK_Cyrillic_ER = 0x6f2 +XK_Cyrillic_ES = 0x6f3 +XK_Cyrillic_TE = 0x6f4 +XK_Cyrillic_U = 0x6f5 +XK_Cyrillic_ZHE = 0x6f6 +XK_Cyrillic_VE = 0x6f7 +XK_Cyrillic_SOFTSIGN = 0x6f8 +XK_Cyrillic_YERU = 0x6f9 +XK_Cyrillic_ZE = 0x6fa +XK_Cyrillic_SHA = 0x6fb +XK_Cyrillic_E = 0x6fc +XK_Cyrillic_SHCHA = 0x6fd +XK_Cyrillic_CHE = 0x6fe +XK_Cyrillic_HARDSIGN = 0x6ff diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/greek.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/greek.py new file mode 100644 index 0000000..8cb062a --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/greek.py @@ -0,0 +1,74 @@ +XK_Greek_ALPHAaccent = 0x7a1 +XK_Greek_EPSILONaccent = 0x7a2 +XK_Greek_ETAaccent = 0x7a3 +XK_Greek_IOTAaccent = 0x7a4 +XK_Greek_IOTAdiaeresis = 0x7a5 +XK_Greek_OMICRONaccent = 0x7a7 +XK_Greek_UPSILONaccent = 0x7a8 +XK_Greek_UPSILONdieresis = 0x7a9 +XK_Greek_OMEGAaccent = 0x7ab +XK_Greek_accentdieresis = 0x7ae +XK_Greek_horizbar = 0x7af +XK_Greek_alphaaccent = 0x7b1 +XK_Greek_epsilonaccent = 0x7b2 +XK_Greek_etaaccent = 0x7b3 +XK_Greek_iotaaccent = 0x7b4 +XK_Greek_iotadieresis = 0x7b5 +XK_Greek_iotaaccentdieresis = 0x7b6 +XK_Greek_omicronaccent = 0x7b7 +XK_Greek_upsilonaccent = 0x7b8 +XK_Greek_upsilondieresis = 0x7b9 +XK_Greek_upsilonaccentdieresis = 0x7ba +XK_Greek_omegaaccent = 0x7bb +XK_Greek_ALPHA = 0x7c1 +XK_Greek_BETA = 0x7c2 +XK_Greek_GAMMA = 0x7c3 +XK_Greek_DELTA = 0x7c4 +XK_Greek_EPSILON = 0x7c5 +XK_Greek_ZETA = 0x7c6 +XK_Greek_ETA = 0x7c7 +XK_Greek_THETA = 0x7c8 +XK_Greek_IOTA = 0x7c9 +XK_Greek_KAPPA = 0x7ca +XK_Greek_LAMDA = 0x7cb +XK_Greek_LAMBDA = 0x7cb +XK_Greek_MU = 0x7cc +XK_Greek_NU = 0x7cd +XK_Greek_XI = 0x7ce +XK_Greek_OMICRON = 0x7cf +XK_Greek_PI = 0x7d0 +XK_Greek_RHO = 0x7d1 +XK_Greek_SIGMA = 0x7d2 +XK_Greek_TAU = 0x7d4 +XK_Greek_UPSILON = 0x7d5 +XK_Greek_PHI = 0x7d6 +XK_Greek_CHI = 0x7d7 +XK_Greek_PSI = 0x7d8 +XK_Greek_OMEGA = 0x7d9 +XK_Greek_alpha = 0x7e1 +XK_Greek_beta = 0x7e2 +XK_Greek_gamma = 0x7e3 +XK_Greek_delta = 0x7e4 +XK_Greek_epsilon = 0x7e5 +XK_Greek_zeta = 0x7e6 +XK_Greek_eta = 0x7e7 +XK_Greek_theta = 0x7e8 +XK_Greek_iota = 0x7e9 +XK_Greek_kappa = 0x7ea +XK_Greek_lamda = 0x7eb +XK_Greek_lambda = 0x7eb +XK_Greek_mu = 0x7ec +XK_Greek_nu = 0x7ed +XK_Greek_xi = 0x7ee +XK_Greek_omicron = 0x7ef +XK_Greek_pi = 0x7f0 +XK_Greek_rho = 0x7f1 +XK_Greek_sigma = 0x7f2 +XK_Greek_finalsmallsigma = 0x7f3 +XK_Greek_tau = 0x7f4 +XK_Greek_upsilon = 0x7f5 +XK_Greek_phi = 0x7f6 +XK_Greek_chi = 0x7f7 +XK_Greek_psi = 0x7f8 +XK_Greek_omega = 0x7f9 +XK_Greek_switch = 0xFF7E diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/hebrew.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/hebrew.py new file mode 100644 index 0000000..94ce089 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/hebrew.py @@ -0,0 +1,40 @@ +XK_hebrew_doublelowline = 0xcdf +XK_hebrew_aleph = 0xce0 +XK_hebrew_bet = 0xce1 +XK_hebrew_beth = 0xce1 +XK_hebrew_gimel = 0xce2 +XK_hebrew_gimmel = 0xce2 +XK_hebrew_dalet = 0xce3 +XK_hebrew_daleth = 0xce3 +XK_hebrew_he = 0xce4 +XK_hebrew_waw = 0xce5 +XK_hebrew_zain = 0xce6 +XK_hebrew_zayin = 0xce6 +XK_hebrew_chet = 0xce7 +XK_hebrew_het = 0xce7 +XK_hebrew_tet = 0xce8 +XK_hebrew_teth = 0xce8 +XK_hebrew_yod = 0xce9 +XK_hebrew_finalkaph = 0xcea +XK_hebrew_kaph = 0xceb +XK_hebrew_lamed = 0xcec +XK_hebrew_finalmem = 0xced +XK_hebrew_mem = 0xcee +XK_hebrew_finalnun = 0xcef +XK_hebrew_nun = 0xcf0 +XK_hebrew_samech = 0xcf1 +XK_hebrew_samekh = 0xcf1 +XK_hebrew_ayin = 0xcf2 +XK_hebrew_finalpe = 0xcf3 +XK_hebrew_pe = 0xcf4 +XK_hebrew_finalzade = 0xcf5 +XK_hebrew_finalzadi = 0xcf5 +XK_hebrew_zade = 0xcf6 +XK_hebrew_zadi = 0xcf6 +XK_hebrew_qoph = 0xcf7 +XK_hebrew_kuf = 0xcf7 +XK_hebrew_resh = 0xcf8 +XK_hebrew_shin = 0xcf9 +XK_hebrew_taw = 0xcfa +XK_hebrew_taf = 0xcfa +XK_Hebrew_switch = 0xFF7E diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/katakana.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/katakana.py new file mode 100644 index 0000000..ca0428d --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/katakana.py @@ -0,0 +1,70 @@ +XK_overline = 0x47e +XK_kana_fullstop = 0x4a1 +XK_kana_openingbracket = 0x4a2 +XK_kana_closingbracket = 0x4a3 +XK_kana_comma = 0x4a4 +XK_kana_conjunctive = 0x4a5 +XK_kana_middledot = 0x4a5 +XK_kana_WO = 0x4a6 +XK_kana_a = 0x4a7 +XK_kana_i = 0x4a8 +XK_kana_u = 0x4a9 +XK_kana_e = 0x4aa +XK_kana_o = 0x4ab +XK_kana_ya = 0x4ac +XK_kana_yu = 0x4ad +XK_kana_yo = 0x4ae +XK_kana_tsu = 0x4af +XK_kana_tu = 0x4af +XK_prolongedsound = 0x4b0 +XK_kana_A = 0x4b1 +XK_kana_I = 0x4b2 +XK_kana_U = 0x4b3 +XK_kana_E = 0x4b4 +XK_kana_O = 0x4b5 +XK_kana_KA = 0x4b6 +XK_kana_KI = 0x4b7 +XK_kana_KU = 0x4b8 +XK_kana_KE = 0x4b9 +XK_kana_KO = 0x4ba +XK_kana_SA = 0x4bb +XK_kana_SHI = 0x4bc +XK_kana_SU = 0x4bd +XK_kana_SE = 0x4be +XK_kana_SO = 0x4bf +XK_kana_TA = 0x4c0 +XK_kana_CHI = 0x4c1 +XK_kana_TI = 0x4c1 +XK_kana_TSU = 0x4c2 +XK_kana_TU = 0x4c2 +XK_kana_TE = 0x4c3 +XK_kana_TO = 0x4c4 +XK_kana_NA = 0x4c5 +XK_kana_NI = 0x4c6 +XK_kana_NU = 0x4c7 +XK_kana_NE = 0x4c8 +XK_kana_NO = 0x4c9 +XK_kana_HA = 0x4ca +XK_kana_HI = 0x4cb +XK_kana_FU = 0x4cc +XK_kana_HU = 0x4cc +XK_kana_HE = 0x4cd +XK_kana_HO = 0x4ce +XK_kana_MA = 0x4cf +XK_kana_MI = 0x4d0 +XK_kana_MU = 0x4d1 +XK_kana_ME = 0x4d2 +XK_kana_MO = 0x4d3 +XK_kana_YA = 0x4d4 +XK_kana_YU = 0x4d5 +XK_kana_YO = 0x4d6 +XK_kana_RA = 0x4d7 +XK_kana_RI = 0x4d8 +XK_kana_RU = 0x4d9 +XK_kana_RE = 0x4da +XK_kana_RO = 0x4db +XK_kana_WA = 0x4dc +XK_kana_N = 0x4dd +XK_voicedsound = 0x4de +XK_semivoicedsound = 0x4df +XK_kana_switch = 0xFF7E diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/korean.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/korean.py new file mode 100644 index 0000000..86480d0 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/korean.py @@ -0,0 +1,107 @@ +XK_Hangul = 0xff31 +XK_Hangul_Start = 0xff32 +XK_Hangul_End = 0xff33 +XK_Hangul_Hanja = 0xff34 +XK_Hangul_Jamo = 0xff35 +XK_Hangul_Romaja = 0xff36 +XK_Hangul_Codeinput = 0xff37 +XK_Hangul_Jeonja = 0xff38 +XK_Hangul_Banja = 0xff39 +XK_Hangul_PreHanja = 0xff3a +XK_Hangul_PostHanja = 0xff3b +XK_Hangul_SingleCandidate = 0xff3c +XK_Hangul_MultipleCandidate = 0xff3d +XK_Hangul_PreviousCandidate = 0xff3e +XK_Hangul_Special = 0xff3f +XK_Hangul_switch = 0xFF7E +XK_Hangul_Kiyeog = 0xea1 +XK_Hangul_SsangKiyeog = 0xea2 +XK_Hangul_KiyeogSios = 0xea3 +XK_Hangul_Nieun = 0xea4 +XK_Hangul_NieunJieuj = 0xea5 +XK_Hangul_NieunHieuh = 0xea6 +XK_Hangul_Dikeud = 0xea7 +XK_Hangul_SsangDikeud = 0xea8 +XK_Hangul_Rieul = 0xea9 +XK_Hangul_RieulKiyeog = 0xeaa +XK_Hangul_RieulMieum = 0xeab +XK_Hangul_RieulPieub = 0xeac +XK_Hangul_RieulSios = 0xead +XK_Hangul_RieulTieut = 0xeae +XK_Hangul_RieulPhieuf = 0xeaf +XK_Hangul_RieulHieuh = 0xeb0 +XK_Hangul_Mieum = 0xeb1 +XK_Hangul_Pieub = 0xeb2 +XK_Hangul_SsangPieub = 0xeb3 +XK_Hangul_PieubSios = 0xeb4 +XK_Hangul_Sios = 0xeb5 +XK_Hangul_SsangSios = 0xeb6 +XK_Hangul_Ieung = 0xeb7 +XK_Hangul_Jieuj = 0xeb8 +XK_Hangul_SsangJieuj = 0xeb9 +XK_Hangul_Cieuc = 0xeba +XK_Hangul_Khieuq = 0xebb +XK_Hangul_Tieut = 0xebc +XK_Hangul_Phieuf = 0xebd +XK_Hangul_Hieuh = 0xebe +XK_Hangul_A = 0xebf +XK_Hangul_AE = 0xec0 +XK_Hangul_YA = 0xec1 +XK_Hangul_YAE = 0xec2 +XK_Hangul_EO = 0xec3 +XK_Hangul_E = 0xec4 +XK_Hangul_YEO = 0xec5 +XK_Hangul_YE = 0xec6 +XK_Hangul_O = 0xec7 +XK_Hangul_WA = 0xec8 +XK_Hangul_WAE = 0xec9 +XK_Hangul_OE = 0xeca +XK_Hangul_YO = 0xecb +XK_Hangul_U = 0xecc +XK_Hangul_WEO = 0xecd +XK_Hangul_WE = 0xece +XK_Hangul_WI = 0xecf +XK_Hangul_YU = 0xed0 +XK_Hangul_EU = 0xed1 +XK_Hangul_YI = 0xed2 +XK_Hangul_I = 0xed3 +XK_Hangul_J_Kiyeog = 0xed4 +XK_Hangul_J_SsangKiyeog = 0xed5 +XK_Hangul_J_KiyeogSios = 0xed6 +XK_Hangul_J_Nieun = 0xed7 +XK_Hangul_J_NieunJieuj = 0xed8 +XK_Hangul_J_NieunHieuh = 0xed9 +XK_Hangul_J_Dikeud = 0xeda +XK_Hangul_J_Rieul = 0xedb +XK_Hangul_J_RieulKiyeog = 0xedc +XK_Hangul_J_RieulMieum = 0xedd +XK_Hangul_J_RieulPieub = 0xede +XK_Hangul_J_RieulSios = 0xedf +XK_Hangul_J_RieulTieut = 0xee0 +XK_Hangul_J_RieulPhieuf = 0xee1 +XK_Hangul_J_RieulHieuh = 0xee2 +XK_Hangul_J_Mieum = 0xee3 +XK_Hangul_J_Pieub = 0xee4 +XK_Hangul_J_PieubSios = 0xee5 +XK_Hangul_J_Sios = 0xee6 +XK_Hangul_J_SsangSios = 0xee7 +XK_Hangul_J_Ieung = 0xee8 +XK_Hangul_J_Jieuj = 0xee9 +XK_Hangul_J_Cieuc = 0xeea +XK_Hangul_J_Khieuq = 0xeeb +XK_Hangul_J_Tieut = 0xeec +XK_Hangul_J_Phieuf = 0xeed +XK_Hangul_J_Hieuh = 0xeee +XK_Hangul_RieulYeorinHieuh = 0xeef +XK_Hangul_SunkyeongeumMieum = 0xef0 +XK_Hangul_SunkyeongeumPieub = 0xef1 +XK_Hangul_PanSios = 0xef2 +XK_Hangul_KkogjiDalrinIeung = 0xef3 +XK_Hangul_SunkyeongeumPhieuf = 0xef4 +XK_Hangul_YeorinHieuh = 0xef5 +XK_Hangul_AraeA = 0xef6 +XK_Hangul_AraeAE = 0xef7 +XK_Hangul_J_PanSios = 0xef8 +XK_Hangul_J_KkogjiDalrinIeung = 0xef9 +XK_Hangul_J_YeorinHieuh = 0xefa +XK_Korean_Won = 0xeff diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin1.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin1.py new file mode 100644 index 0000000..350ccff --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin1.py @@ -0,0 +1,195 @@ +XK_space = 0x020 +XK_exclam = 0x021 +XK_quotedbl = 0x022 +XK_numbersign = 0x023 +XK_dollar = 0x024 +XK_percent = 0x025 +XK_ampersand = 0x026 +XK_apostrophe = 0x027 +XK_quoteright = 0x027 +XK_parenleft = 0x028 +XK_parenright = 0x029 +XK_asterisk = 0x02a +XK_plus = 0x02b +XK_comma = 0x02c +XK_minus = 0x02d +XK_period = 0x02e +XK_slash = 0x02f +XK_0 = 0x030 +XK_1 = 0x031 +XK_2 = 0x032 +XK_3 = 0x033 +XK_4 = 0x034 +XK_5 = 0x035 +XK_6 = 0x036 +XK_7 = 0x037 +XK_8 = 0x038 +XK_9 = 0x039 +XK_colon = 0x03a +XK_semicolon = 0x03b +XK_less = 0x03c +XK_equal = 0x03d +XK_greater = 0x03e +XK_question = 0x03f +XK_at = 0x040 +XK_A = 0x041 +XK_B = 0x042 +XK_C = 0x043 +XK_D = 0x044 +XK_E = 0x045 +XK_F = 0x046 +XK_G = 0x047 +XK_H = 0x048 +XK_I = 0x049 +XK_J = 0x04a +XK_K = 0x04b +XK_L = 0x04c +XK_M = 0x04d +XK_N = 0x04e +XK_O = 0x04f +XK_P = 0x050 +XK_Q = 0x051 +XK_R = 0x052 +XK_S = 0x053 +XK_T = 0x054 +XK_U = 0x055 +XK_V = 0x056 +XK_W = 0x057 +XK_X = 0x058 +XK_Y = 0x059 +XK_Z = 0x05a +XK_bracketleft = 0x05b +XK_backslash = 0x05c +XK_bracketright = 0x05d +XK_asciicircum = 0x05e +XK_underscore = 0x05f +XK_grave = 0x060 +XK_quoteleft = 0x060 +XK_a = 0x061 +XK_b = 0x062 +XK_c = 0x063 +XK_d = 0x064 +XK_e = 0x065 +XK_f = 0x066 +XK_g = 0x067 +XK_h = 0x068 +XK_i = 0x069 +XK_j = 0x06a +XK_k = 0x06b +XK_l = 0x06c +XK_m = 0x06d +XK_n = 0x06e +XK_o = 0x06f +XK_p = 0x070 +XK_q = 0x071 +XK_r = 0x072 +XK_s = 0x073 +XK_t = 0x074 +XK_u = 0x075 +XK_v = 0x076 +XK_w = 0x077 +XK_x = 0x078 +XK_y = 0x079 +XK_z = 0x07a +XK_braceleft = 0x07b +XK_bar = 0x07c +XK_braceright = 0x07d +XK_asciitilde = 0x07e +XK_nobreakspace = 0x0a0 +XK_exclamdown = 0x0a1 +XK_cent = 0x0a2 +XK_sterling = 0x0a3 +XK_currency = 0x0a4 +XK_yen = 0x0a5 +XK_brokenbar = 0x0a6 +XK_section = 0x0a7 +XK_diaeresis = 0x0a8 +XK_copyright = 0x0a9 +XK_ordfeminine = 0x0aa +XK_guillemotleft = 0x0ab +XK_notsign = 0x0ac +XK_hyphen = 0x0ad +XK_registered = 0x0ae +XK_macron = 0x0af +XK_degree = 0x0b0 +XK_plusminus = 0x0b1 +XK_twosuperior = 0x0b2 +XK_threesuperior = 0x0b3 +XK_acute = 0x0b4 +XK_mu = 0x0b5 +XK_paragraph = 0x0b6 +XK_periodcentered = 0x0b7 +XK_cedilla = 0x0b8 +XK_onesuperior = 0x0b9 +XK_masculine = 0x0ba +XK_guillemotright = 0x0bb +XK_onequarter = 0x0bc +XK_onehalf = 0x0bd +XK_threequarters = 0x0be +XK_questiondown = 0x0bf +XK_Agrave = 0x0c0 +XK_Aacute = 0x0c1 +XK_Acircumflex = 0x0c2 +XK_Atilde = 0x0c3 +XK_Adiaeresis = 0x0c4 +XK_Aring = 0x0c5 +XK_AE = 0x0c6 +XK_Ccedilla = 0x0c7 +XK_Egrave = 0x0c8 +XK_Eacute = 0x0c9 +XK_Ecircumflex = 0x0ca +XK_Ediaeresis = 0x0cb +XK_Igrave = 0x0cc +XK_Iacute = 0x0cd +XK_Icircumflex = 0x0ce +XK_Idiaeresis = 0x0cf +XK_ETH = 0x0d0 +XK_Eth = 0x0d0 +XK_Ntilde = 0x0d1 +XK_Ograve = 0x0d2 +XK_Oacute = 0x0d3 +XK_Ocircumflex = 0x0d4 +XK_Otilde = 0x0d5 +XK_Odiaeresis = 0x0d6 +XK_multiply = 0x0d7 +XK_Ooblique = 0x0d8 +XK_Ugrave = 0x0d9 +XK_Uacute = 0x0da +XK_Ucircumflex = 0x0db +XK_Udiaeresis = 0x0dc +XK_Yacute = 0x0dd +XK_THORN = 0x0de +XK_Thorn = 0x0de +XK_ssharp = 0x0df +XK_agrave = 0x0e0 +XK_aacute = 0x0e1 +XK_acircumflex = 0x0e2 +XK_atilde = 0x0e3 +XK_adiaeresis = 0x0e4 +XK_aring = 0x0e5 +XK_ae = 0x0e6 +XK_ccedilla = 0x0e7 +XK_egrave = 0x0e8 +XK_eacute = 0x0e9 +XK_ecircumflex = 0x0ea +XK_ediaeresis = 0x0eb +XK_igrave = 0x0ec +XK_iacute = 0x0ed +XK_icircumflex = 0x0ee +XK_idiaeresis = 0x0ef +XK_eth = 0x0f0 +XK_ntilde = 0x0f1 +XK_ograve = 0x0f2 +XK_oacute = 0x0f3 +XK_ocircumflex = 0x0f4 +XK_otilde = 0x0f5 +XK_odiaeresis = 0x0f6 +XK_division = 0x0f7 +XK_oslash = 0x0f8 +XK_ugrave = 0x0f9 +XK_uacute = 0x0fa +XK_ucircumflex = 0x0fb +XK_udiaeresis = 0x0fc +XK_yacute = 0x0fd +XK_thorn = 0x0fe +XK_ydiaeresis = 0x0ff diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin2.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin2.py new file mode 100644 index 0000000..f0d9a15 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin2.py @@ -0,0 +1,57 @@ +XK_Aogonek = 0x1a1 +XK_breve = 0x1a2 +XK_Lstroke = 0x1a3 +XK_Lcaron = 0x1a5 +XK_Sacute = 0x1a6 +XK_Scaron = 0x1a9 +XK_Scedilla = 0x1aa +XK_Tcaron = 0x1ab +XK_Zacute = 0x1ac +XK_Zcaron = 0x1ae +XK_Zabovedot = 0x1af +XK_aogonek = 0x1b1 +XK_ogonek = 0x1b2 +XK_lstroke = 0x1b3 +XK_lcaron = 0x1b5 +XK_sacute = 0x1b6 +XK_caron = 0x1b7 +XK_scaron = 0x1b9 +XK_scedilla = 0x1ba +XK_tcaron = 0x1bb +XK_zacute = 0x1bc +XK_doubleacute = 0x1bd +XK_zcaron = 0x1be +XK_zabovedot = 0x1bf +XK_Racute = 0x1c0 +XK_Abreve = 0x1c3 +XK_Lacute = 0x1c5 +XK_Cacute = 0x1c6 +XK_Ccaron = 0x1c8 +XK_Eogonek = 0x1ca +XK_Ecaron = 0x1cc +XK_Dcaron = 0x1cf +XK_Dstroke = 0x1d0 +XK_Nacute = 0x1d1 +XK_Ncaron = 0x1d2 +XK_Odoubleacute = 0x1d5 +XK_Rcaron = 0x1d8 +XK_Uring = 0x1d9 +XK_Udoubleacute = 0x1db +XK_Tcedilla = 0x1de +XK_racute = 0x1e0 +XK_abreve = 0x1e3 +XK_lacute = 0x1e5 +XK_cacute = 0x1e6 +XK_ccaron = 0x1e8 +XK_eogonek = 0x1ea +XK_ecaron = 0x1ec +XK_dcaron = 0x1ef +XK_dstroke = 0x1f0 +XK_nacute = 0x1f1 +XK_ncaron = 0x1f2 +XK_odoubleacute = 0x1f5 +XK_udoubleacute = 0x1fb +XK_rcaron = 0x1f8 +XK_uring = 0x1f9 +XK_tcedilla = 0x1fe +XK_abovedot = 0x1ff diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin3.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin3.py new file mode 100644 index 0000000..a14c562 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin3.py @@ -0,0 +1,22 @@ +XK_Hstroke = 0x2a1 +XK_Hcircumflex = 0x2a6 +XK_Iabovedot = 0x2a9 +XK_Gbreve = 0x2ab +XK_Jcircumflex = 0x2ac +XK_hstroke = 0x2b1 +XK_hcircumflex = 0x2b6 +XK_idotless = 0x2b9 +XK_gbreve = 0x2bb +XK_jcircumflex = 0x2bc +XK_Cabovedot = 0x2c5 +XK_Ccircumflex = 0x2c6 +XK_Gabovedot = 0x2d5 +XK_Gcircumflex = 0x2d8 +XK_Ubreve = 0x2dd +XK_Scircumflex = 0x2de +XK_cabovedot = 0x2e5 +XK_ccircumflex = 0x2e6 +XK_gabovedot = 0x2f5 +XK_gcircumflex = 0x2f8 +XK_ubreve = 0x2fd +XK_scircumflex = 0x2fe diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin4.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin4.py new file mode 100644 index 0000000..4ee1d80 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/latin4.py @@ -0,0 +1,36 @@ +XK_kra = 0x3a2 +XK_kappa = 0x3a2 +XK_Rcedilla = 0x3a3 +XK_Itilde = 0x3a5 +XK_Lcedilla = 0x3a6 +XK_Emacron = 0x3aa +XK_Gcedilla = 0x3ab +XK_Tslash = 0x3ac +XK_rcedilla = 0x3b3 +XK_itilde = 0x3b5 +XK_lcedilla = 0x3b6 +XK_emacron = 0x3ba +XK_gcedilla = 0x3bb +XK_tslash = 0x3bc +XK_ENG = 0x3bd +XK_eng = 0x3bf +XK_Amacron = 0x3c0 +XK_Iogonek = 0x3c7 +XK_Eabovedot = 0x3cc +XK_Imacron = 0x3cf +XK_Ncedilla = 0x3d1 +XK_Omacron = 0x3d2 +XK_Kcedilla = 0x3d3 +XK_Uogonek = 0x3d9 +XK_Utilde = 0x3dd +XK_Umacron = 0x3de +XK_amacron = 0x3e0 +XK_iogonek = 0x3e7 +XK_eabovedot = 0x3ec +XK_imacron = 0x3ef +XK_ncedilla = 0x3f1 +XK_omacron = 0x3f2 +XK_kcedilla = 0x3f3 +XK_uogonek = 0x3f9 +XK_utilde = 0x3fd +XK_umacron = 0x3fe diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/miscellany.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/miscellany.py new file mode 100644 index 0000000..9bcb578 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/miscellany.py @@ -0,0 +1,169 @@ +XK_BackSpace = 0xFF08 +XK_Tab = 0xFF09 +XK_Linefeed = 0xFF0A +XK_Clear = 0xFF0B +XK_Return = 0xFF0D +XK_Pause = 0xFF13 +XK_Scroll_Lock = 0xFF14 +XK_Sys_Req = 0xFF15 +XK_Escape = 0xFF1B +XK_Delete = 0xFFFF +XK_Multi_key = 0xFF20 +XK_SingleCandidate = 0xFF3C +XK_MultipleCandidate = 0xFF3D +XK_PreviousCandidate = 0xFF3E +XK_Kanji = 0xFF21 +XK_Muhenkan = 0xFF22 +XK_Henkan_Mode = 0xFF23 +XK_Henkan = 0xFF23 +XK_Romaji = 0xFF24 +XK_Hiragana = 0xFF25 +XK_Katakana = 0xFF26 +XK_Hiragana_Katakana = 0xFF27 +XK_Zenkaku = 0xFF28 +XK_Hankaku = 0xFF29 +XK_Zenkaku_Hankaku = 0xFF2A +XK_Touroku = 0xFF2B +XK_Massyo = 0xFF2C +XK_Kana_Lock = 0xFF2D +XK_Kana_Shift = 0xFF2E +XK_Eisu_Shift = 0xFF2F +XK_Eisu_toggle = 0xFF30 +XK_Zen_Koho = 0xFF3D +XK_Mae_Koho = 0xFF3E +XK_Home = 0xFF50 +XK_Left = 0xFF51 +XK_Up = 0xFF52 +XK_Right = 0xFF53 +XK_Down = 0xFF54 +XK_Prior = 0xFF55 +XK_Page_Up = 0xFF55 +XK_Next = 0xFF56 +XK_Page_Down = 0xFF56 +XK_End = 0xFF57 +XK_Begin = 0xFF58 +XK_Select = 0xFF60 +XK_Print = 0xFF61 +XK_Execute = 0xFF62 +XK_Insert = 0xFF63 +XK_Undo = 0xFF65 +XK_Redo = 0xFF66 +XK_Menu = 0xFF67 +XK_Find = 0xFF68 +XK_Cancel = 0xFF69 +XK_Help = 0xFF6A +XK_Break = 0xFF6B +XK_Mode_switch = 0xFF7E +XK_script_switch = 0xFF7E +XK_Num_Lock = 0xFF7F +XK_KP_Space = 0xFF80 +XK_KP_Tab = 0xFF89 +XK_KP_Enter = 0xFF8D +XK_KP_F1 = 0xFF91 +XK_KP_F2 = 0xFF92 +XK_KP_F3 = 0xFF93 +XK_KP_F4 = 0xFF94 +XK_KP_Home = 0xFF95 +XK_KP_Left = 0xFF96 +XK_KP_Up = 0xFF97 +XK_KP_Right = 0xFF98 +XK_KP_Down = 0xFF99 +XK_KP_Prior = 0xFF9A +XK_KP_Page_Up = 0xFF9A +XK_KP_Next = 0xFF9B +XK_KP_Page_Down = 0xFF9B +XK_KP_End = 0xFF9C +XK_KP_Begin = 0xFF9D +XK_KP_Insert = 0xFF9E +XK_KP_Delete = 0xFF9F +XK_KP_Equal = 0xFFBD +XK_KP_Multiply = 0xFFAA +XK_KP_Add = 0xFFAB +XK_KP_Separator = 0xFFAC +XK_KP_Subtract = 0xFFAD +XK_KP_Decimal = 0xFFAE +XK_KP_Divide = 0xFFAF +XK_KP_0 = 0xFFB0 +XK_KP_1 = 0xFFB1 +XK_KP_2 = 0xFFB2 +XK_KP_3 = 0xFFB3 +XK_KP_4 = 0xFFB4 +XK_KP_5 = 0xFFB5 +XK_KP_6 = 0xFFB6 +XK_KP_7 = 0xFFB7 +XK_KP_8 = 0xFFB8 +XK_KP_9 = 0xFFB9 +XK_F1 = 0xFFBE +XK_F2 = 0xFFBF +XK_F3 = 0xFFC0 +XK_F4 = 0xFFC1 +XK_F5 = 0xFFC2 +XK_F6 = 0xFFC3 +XK_F7 = 0xFFC4 +XK_F8 = 0xFFC5 +XK_F9 = 0xFFC6 +XK_F10 = 0xFFC7 +XK_F11 = 0xFFC8 +XK_L1 = 0xFFC8 +XK_F12 = 0xFFC9 +XK_L2 = 0xFFC9 +XK_F13 = 0xFFCA +XK_L3 = 0xFFCA +XK_F14 = 0xFFCB +XK_L4 = 0xFFCB +XK_F15 = 0xFFCC +XK_L5 = 0xFFCC +XK_F16 = 0xFFCD +XK_L6 = 0xFFCD +XK_F17 = 0xFFCE +XK_L7 = 0xFFCE +XK_F18 = 0xFFCF +XK_L8 = 0xFFCF +XK_F19 = 0xFFD0 +XK_L9 = 0xFFD0 +XK_F20 = 0xFFD1 +XK_L10 = 0xFFD1 +XK_F21 = 0xFFD2 +XK_R1 = 0xFFD2 +XK_F22 = 0xFFD3 +XK_R2 = 0xFFD3 +XK_F23 = 0xFFD4 +XK_R3 = 0xFFD4 +XK_F24 = 0xFFD5 +XK_R4 = 0xFFD5 +XK_F25 = 0xFFD6 +XK_R5 = 0xFFD6 +XK_F26 = 0xFFD7 +XK_R6 = 0xFFD7 +XK_F27 = 0xFFD8 +XK_R7 = 0xFFD8 +XK_F28 = 0xFFD9 +XK_R8 = 0xFFD9 +XK_F29 = 0xFFDA +XK_R9 = 0xFFDA +XK_F30 = 0xFFDB +XK_R10 = 0xFFDB +XK_F31 = 0xFFDC +XK_R11 = 0xFFDC +XK_F32 = 0xFFDD +XK_R12 = 0xFFDD +XK_F33 = 0xFFDE +XK_R13 = 0xFFDE +XK_F34 = 0xFFDF +XK_R14 = 0xFFDF +XK_F35 = 0xFFE0 +XK_R15 = 0xFFE0 +XK_Shift_L = 0xFFE1 +XK_Shift_R = 0xFFE2 +XK_Control_L = 0xFFE3 +XK_Control_R = 0xFFE4 +XK_Caps_Lock = 0xFFE5 +XK_Shift_Lock = 0xFFE6 +XK_Meta_L = 0xFFE7 +XK_Meta_R = 0xFFE8 +XK_Alt_L = 0xFFE9 +XK_Alt_R = 0xFFEA +XK_Super_L = 0xFFEB +XK_Super_R = 0xFFEC +XK_Hyper_L = 0xFFED +XK_Hyper_R = 0xFFEE diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/publishing.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/publishing.py new file mode 100644 index 0000000..45b4138 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/publishing.py @@ -0,0 +1,83 @@ +XK_emspace = 0xaa1 +XK_enspace = 0xaa2 +XK_em3space = 0xaa3 +XK_em4space = 0xaa4 +XK_digitspace = 0xaa5 +XK_punctspace = 0xaa6 +XK_thinspace = 0xaa7 +XK_hairspace = 0xaa8 +XK_emdash = 0xaa9 +XK_endash = 0xaaa +XK_signifblank = 0xaac +XK_ellipsis = 0xaae +XK_doubbaselinedot = 0xaaf +XK_onethird = 0xab0 +XK_twothirds = 0xab1 +XK_onefifth = 0xab2 +XK_twofifths = 0xab3 +XK_threefifths = 0xab4 +XK_fourfifths = 0xab5 +XK_onesixth = 0xab6 +XK_fivesixths = 0xab7 +XK_careof = 0xab8 +XK_figdash = 0xabb +XK_leftanglebracket = 0xabc +XK_decimalpoint = 0xabd +XK_rightanglebracket = 0xabe +XK_marker = 0xabf +XK_oneeighth = 0xac3 +XK_threeeighths = 0xac4 +XK_fiveeighths = 0xac5 +XK_seveneighths = 0xac6 +XK_trademark = 0xac9 +XK_signaturemark = 0xaca +XK_trademarkincircle = 0xacb +XK_leftopentriangle = 0xacc +XK_rightopentriangle = 0xacd +XK_emopencircle = 0xace +XK_emopenrectangle = 0xacf +XK_leftsinglequotemark = 0xad0 +XK_rightsinglequotemark = 0xad1 +XK_leftdoublequotemark = 0xad2 +XK_rightdoublequotemark = 0xad3 +XK_prescription = 0xad4 +XK_minutes = 0xad6 +XK_seconds = 0xad7 +XK_latincross = 0xad9 +XK_hexagram = 0xada +XK_filledrectbullet = 0xadb +XK_filledlefttribullet = 0xadc +XK_filledrighttribullet = 0xadd +XK_emfilledcircle = 0xade +XK_emfilledrect = 0xadf +XK_enopencircbullet = 0xae0 +XK_enopensquarebullet = 0xae1 +XK_openrectbullet = 0xae2 +XK_opentribulletup = 0xae3 +XK_opentribulletdown = 0xae4 +XK_openstar = 0xae5 +XK_enfilledcircbullet = 0xae6 +XK_enfilledsqbullet = 0xae7 +XK_filledtribulletup = 0xae8 +XK_filledtribulletdown = 0xae9 +XK_leftpointer = 0xaea +XK_rightpointer = 0xaeb +XK_club = 0xaec +XK_diamond = 0xaed +XK_heart = 0xaee +XK_maltesecross = 0xaf0 +XK_dagger = 0xaf1 +XK_doubledagger = 0xaf2 +XK_checkmark = 0xaf3 +XK_ballotcross = 0xaf4 +XK_musicalsharp = 0xaf5 +XK_musicalflat = 0xaf6 +XK_malesymbol = 0xaf7 +XK_femalesymbol = 0xaf8 +XK_telephone = 0xaf9 +XK_telephonerecorder = 0xafa +XK_phonographcopyright = 0xafb +XK_caret = 0xafc +XK_singlelowquotemark = 0xafd +XK_doublelowquotemark = 0xafe +XK_cursor = 0xaff diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/special.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/special.py new file mode 100644 index 0000000..8a27d4e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/special.py @@ -0,0 +1,24 @@ +XK_blank = 0x9df +XK_soliddiamond = 0x9e0 +XK_checkerboard = 0x9e1 +XK_ht = 0x9e2 +XK_ff = 0x9e3 +XK_cr = 0x9e4 +XK_lf = 0x9e5 +XK_nl = 0x9e8 +XK_vt = 0x9e9 +XK_lowrightcorner = 0x9ea +XK_uprightcorner = 0x9eb +XK_upleftcorner = 0x9ec +XK_lowleftcorner = 0x9ed +XK_crossinglines = 0x9ee +XK_horizlinescan1 = 0x9ef +XK_horizlinescan3 = 0x9f0 +XK_horizlinescan5 = 0x9f1 +XK_horizlinescan7 = 0x9f2 +XK_horizlinescan9 = 0x9f3 +XK_leftt = 0x9f4 +XK_rightt = 0x9f5 +XK_bott = 0x9f6 +XK_topt = 0x9f7 +XK_vertbar = 0x9f8 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/technical.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/technical.py new file mode 100644 index 0000000..4f75a97 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/technical.py @@ -0,0 +1,49 @@ +XK_leftradical = 0x8a1 +XK_topleftradical = 0x8a2 +XK_horizconnector = 0x8a3 +XK_topintegral = 0x8a4 +XK_botintegral = 0x8a5 +XK_vertconnector = 0x8a6 +XK_topleftsqbracket = 0x8a7 +XK_botleftsqbracket = 0x8a8 +XK_toprightsqbracket = 0x8a9 +XK_botrightsqbracket = 0x8aa +XK_topleftparens = 0x8ab +XK_botleftparens = 0x8ac +XK_toprightparens = 0x8ad +XK_botrightparens = 0x8ae +XK_leftmiddlecurlybrace = 0x8af +XK_rightmiddlecurlybrace = 0x8b0 +XK_topleftsummation = 0x8b1 +XK_botleftsummation = 0x8b2 +XK_topvertsummationconnector = 0x8b3 +XK_botvertsummationconnector = 0x8b4 +XK_toprightsummation = 0x8b5 +XK_botrightsummation = 0x8b6 +XK_rightmiddlesummation = 0x8b7 +XK_lessthanequal = 0x8bc +XK_notequal = 0x8bd +XK_greaterthanequal = 0x8be +XK_integral = 0x8bf +XK_therefore = 0x8c0 +XK_variation = 0x8c1 +XK_infinity = 0x8c2 +XK_nabla = 0x8c5 +XK_approximate = 0x8c8 +XK_similarequal = 0x8c9 +XK_ifonlyif = 0x8cd +XK_implies = 0x8ce +XK_identical = 0x8cf +XK_radical = 0x8d6 +XK_includedin = 0x8da +XK_includes = 0x8db +XK_intersection = 0x8dc +XK_union = 0x8dd +XK_logicaland = 0x8de +XK_logicalor = 0x8df +XK_partialderivative = 0x8ef +XK_function = 0x8f6 +XK_leftarrow = 0x8fb +XK_uparrow = 0x8fc +XK_rightarrow = 0x8fd +XK_downarrow = 0x8fe diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/thai.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/thai.py new file mode 100644 index 0000000..9837ae5 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/thai.py @@ -0,0 +1,84 @@ +XK_Thai_kokai = 0xda1 +XK_Thai_khokhai = 0xda2 +XK_Thai_khokhuat = 0xda3 +XK_Thai_khokhwai = 0xda4 +XK_Thai_khokhon = 0xda5 +XK_Thai_khorakhang = 0xda6 +XK_Thai_ngongu = 0xda7 +XK_Thai_chochan = 0xda8 +XK_Thai_choching = 0xda9 +XK_Thai_chochang = 0xdaa +XK_Thai_soso = 0xdab +XK_Thai_chochoe = 0xdac +XK_Thai_yoying = 0xdad +XK_Thai_dochada = 0xdae +XK_Thai_topatak = 0xdaf +XK_Thai_thothan = 0xdb0 +XK_Thai_thonangmontho = 0xdb1 +XK_Thai_thophuthao = 0xdb2 +XK_Thai_nonen = 0xdb3 +XK_Thai_dodek = 0xdb4 +XK_Thai_totao = 0xdb5 +XK_Thai_thothung = 0xdb6 +XK_Thai_thothahan = 0xdb7 +XK_Thai_thothong = 0xdb8 +XK_Thai_nonu = 0xdb9 +XK_Thai_bobaimai = 0xdba +XK_Thai_popla = 0xdbb +XK_Thai_phophung = 0xdbc +XK_Thai_fofa = 0xdbd +XK_Thai_phophan = 0xdbe +XK_Thai_fofan = 0xdbf +XK_Thai_phosamphao = 0xdc0 +XK_Thai_moma = 0xdc1 +XK_Thai_yoyak = 0xdc2 +XK_Thai_rorua = 0xdc3 +XK_Thai_ru = 0xdc4 +XK_Thai_loling = 0xdc5 +XK_Thai_lu = 0xdc6 +XK_Thai_wowaen = 0xdc7 +XK_Thai_sosala = 0xdc8 +XK_Thai_sorusi = 0xdc9 +XK_Thai_sosua = 0xdca +XK_Thai_hohip = 0xdcb +XK_Thai_lochula = 0xdcc +XK_Thai_oang = 0xdcd +XK_Thai_honokhuk = 0xdce +XK_Thai_paiyannoi = 0xdcf +XK_Thai_saraa = 0xdd0 +XK_Thai_maihanakat = 0xdd1 +XK_Thai_saraaa = 0xdd2 +XK_Thai_saraam = 0xdd3 +XK_Thai_sarai = 0xdd4 +XK_Thai_saraii = 0xdd5 +XK_Thai_saraue = 0xdd6 +XK_Thai_sarauee = 0xdd7 +XK_Thai_sarau = 0xdd8 +XK_Thai_sarauu = 0xdd9 +XK_Thai_phinthu = 0xdda +XK_Thai_maihanakat_maitho = 0xdde +XK_Thai_baht = 0xddf +XK_Thai_sarae = 0xde0 +XK_Thai_saraae = 0xde1 +XK_Thai_sarao = 0xde2 +XK_Thai_saraaimaimuan = 0xde3 +XK_Thai_saraaimaimalai = 0xde4 +XK_Thai_lakkhangyao = 0xde5 +XK_Thai_maiyamok = 0xde6 +XK_Thai_maitaikhu = 0xde7 +XK_Thai_maiek = 0xde8 +XK_Thai_maitho = 0xde9 +XK_Thai_maitri = 0xdea +XK_Thai_maichattawa = 0xdeb +XK_Thai_thanthakhat = 0xdec +XK_Thai_nikhahit = 0xded +XK_Thai_leksun = 0xdf0 +XK_Thai_leknung = 0xdf1 +XK_Thai_leksong = 0xdf2 +XK_Thai_leksam = 0xdf3 +XK_Thai_leksi = 0xdf4 +XK_Thai_lekha = 0xdf5 +XK_Thai_lekhok = 0xdf6 +XK_Thai_lekchet = 0xdf7 +XK_Thai_lekpaet = 0xdf8 +XK_Thai_lekkao = 0xdf9 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xf86.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xf86.py new file mode 100644 index 0000000..8b98852 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xf86.py @@ -0,0 +1,202 @@ +XK_XF86_ModeLock = 0x1008FF01 + +XK_XF86_MonBrightnessUp = 0x1008FF02 +XK_XF86_MonBrightnessDown = 0x1008FF03 +XK_XF86_KbdLightOnOff = 0x1008FF04 +XK_XF86_KbdBrightnessUp = 0x1008FF05 +XK_XF86_KbdBrightnessDown = 0x1008FF06 +XK_XF86_MonBrightnessCycle = 0x1008FF07 + +XK_XF86_Standby = 0x1008FF10 +XK_XF86_AudioLowerVolume = 0x1008FF11 +XK_XF86_AudioMute = 0x1008FF12 +XK_XF86_AudioRaiseVolume = 0x1008FF13 +XK_XF86_AudioPlay = 0x1008FF14 +XK_XF86_AudioStop = 0x1008FF15 +XK_XF86_AudioPrev = 0x1008FF16 +XK_XF86_AudioNext = 0x1008FF17 +XK_XF86_HomePage = 0x1008FF18 +XK_XF86_Mail = 0x1008FF19 +XK_XF86_Start = 0x1008FF1A +XK_XF86_Search = 0x1008FF1B +XK_XF86_AudioRecord = 0x1008FF1C + +XK_XF86_Calculator = 0x1008FF1D +XK_XF86_Memo = 0x1008FF1E +XK_XF86_ToDoList = 0x1008FF1F +XK_XF86_Calendar = 0x1008FF20 +XK_XF86_PowerDown = 0x1008FF21 +XK_XF86_ContrastAdjust = 0x1008FF22 +XK_XF86_RockerUp = 0x1008FF23 +XK_XF86_RockerDown = 0x1008FF24 +XK_XF86_RockerEnter = 0x1008FF25 + +XK_XF86_Back = 0x1008FF26 +XK_XF86_Forward = 0x1008FF27 +XK_XF86_Stop = 0x1008FF28 +XK_XF86_Refresh = 0x1008FF29 +XK_XF86_PowerOff = 0x1008FF2A +XK_XF86_WakeUp = 0x1008FF2B +XK_XF86_Eject = 0x1008FF2C +XK_XF86_ScreenSaver = 0x1008FF2D +XK_XF86_WWW = 0x1008FF2E +XK_XF86_Sleep = 0x1008FF2F +XK_XF86_Favorites = 0x1008FF30 +XK_XF86_AudioPause = 0x1008FF31 +XK_XF86_AudioMedia = 0x1008FF32 +XK_XF86_MyComputer = 0x1008FF33 +XK_XF86_VendorHome = 0x1008FF34 +XK_XF86_LightBulb = 0x1008FF35 +XK_XF86_Shop = 0x1008FF36 +XK_XF86_History = 0x1008FF37 +XK_XF86_OpenURL = 0x1008FF38 +XK_XF86_AddFavorite = 0x1008FF39 +XK_XF86_HotLinks = 0x1008FF3A +XK_XF86_BrightnessAdjust = 0x1008FF3B +XK_XF86_Finance = 0x1008FF3C +XK_XF86_Community = 0x1008FF3D +XK_XF86_AudioRewind = 0x1008FF3E +XK_XF86_XF86BackForward = 0x1008FF3F +XK_XF86_Launch0 = 0x1008FF40 +XK_XF86_Launch1 = 0x1008FF41 +XK_XF86_Launch2 = 0x1008FF42 +XK_XF86_Launch3 = 0x1008FF43 +XK_XF86_Launch4 = 0x1008FF44 +XK_XF86_Launch5 = 0x1008FF45 +XK_XF86_Launch6 = 0x1008FF46 +XK_XF86_Launch7 = 0x1008FF47 +XK_XF86_Launch8 = 0x1008FF48 +XK_XF86_Launch9 = 0x1008FF49 +XK_XF86_LaunchA = 0x1008FF4A +XK_XF86_LaunchB = 0x1008FF4B +XK_XF86_LaunchC = 0x1008FF4C +XK_XF86_LaunchD = 0x1008FF4D +XK_XF86_LaunchE = 0x1008FF4E +XK_XF86_LaunchF = 0x1008FF4F + +XK_XF86_ApplicationLeft = 0x1008FF50 +XK_XF86_ApplicationRight = 0x1008FF51 +XK_XF86_Book = 0x1008FF52 +XK_XF86_CD = 0x1008FF53 +XK_XF86_Calculater = 0x1008FF54 +XK_XF86_Clear = 0x1008FF55 +XK_XF86_Close = 0x1008FF56 +XK_XF86_Copy = 0x1008FF57 +XK_XF86_Cut = 0x1008FF58 +XK_XF86_Display = 0x1008FF59 +XK_XF86_DOS = 0x1008FF5A +XK_XF86_Documents = 0x1008FF5B +XK_XF86_Excel = 0x1008FF5C +XK_XF86_Explorer = 0x1008FF5D +XK_XF86_Game = 0x1008FF5E +XK_XF86_Go = 0x1008FF5F +XK_XF86_iTouch = 0x1008FF60 +XK_XF86_LogOff = 0x1008FF61 +XK_XF86_Market = 0x1008FF62 +XK_XF86_Meeting = 0x1008FF63 +XK_XF86_MenuKB = 0x1008FF65 +XK_XF86_MenuPB = 0x1008FF66 +XK_XF86_MySites = 0x1008FF67 +XK_XF86_New = 0x1008FF68 +XK_XF86_News = 0x1008FF69 +XK_XF86_OfficeHome = 0x1008FF6A +XK_XF86_Open = 0x1008FF6B +XK_XF86_Option = 0x1008FF6C +XK_XF86_Paste = 0x1008FF6D +XK_XF86_Phone = 0x1008FF6E +XK_XF86_Q = 0x1008FF70 +XK_XF86_Reply = 0x1008FF72 +XK_XF86_Reload = 0x1008FF73 +XK_XF86_RotateWindows = 0x1008FF74 +XK_XF86_RotationPB = 0x1008FF75 +XK_XF86_RotationKB = 0x1008FF76 +XK_XF86_Save = 0x1008FF77 +XK_XF86_ScrollUp = 0x1008FF78 +XK_XF86_ScrollDown = 0x1008FF79 +XK_XF86_ScrollClick = 0x1008FF7A +XK_XF86_Send = 0x1008FF7B +XK_XF86_Spell = 0x1008FF7C +XK_XF86_SplitScreen = 0x1008FF7D +XK_XF86_Support = 0x1008FF7E +XK_XF86_TaskPane = 0x1008FF7F +XK_XF86_Terminal = 0x1008FF80 +XK_XF86_Tools = 0x1008FF81 +XK_XF86_Travel = 0x1008FF82 +XK_XF86_UserPB = 0x1008FF84 +XK_XF86_User1KB = 0x1008FF85 +XK_XF86_User2KB = 0x1008FF86 +XK_XF86_Video = 0x1008FF87 +XK_XF86_WheelButton = 0x1008FF88 +XK_XF86_Word = 0x1008FF89 +XK_XF86_Xfer = 0x1008FF8A +XK_XF86_ZoomIn = 0x1008FF8B +XK_XF86_ZoomOut = 0x1008FF8C + +XK_XF86_Away = 0x1008FF8D +XK_XF86_Messenger = 0x1008FF8E +XK_XF86_WebCam = 0x1008FF8F +XK_XF86_MailForward = 0x1008FF90 +XK_XF86_Pictures = 0x1008FF91 +XK_XF86_Music = 0x1008FF92 + +XK_XF86_Battery = 0x1008FF93 +XK_XF86_Bluetooth = 0x1008FF94 +XK_XF86_WLAN = 0x1008FF95 +XK_XF86_UWB = 0x1008FF96 + +XK_XF86_AudioForward = 0x1008FF97 +XK_XF86_AudioRepeat = 0x1008FF98 +XK_XF86_AudioRandomPlay = 0x1008FF99 +XK_XF86_Subtitle = 0x1008FF9A +XK_XF86_AudioCycleTrack = 0x1008FF9B +XK_XF86_CycleAngle = 0x1008FF9C +XK_XF86_FrameBack = 0x1008FF9D +XK_XF86_FrameForward = 0x1008FF9E +XK_XF86_Time = 0x1008FF9F +XK_XF86_Select = 0x1008FFA0 +XK_XF86_View = 0x1008FFA1 +XK_XF86_TopMenu = 0x1008FFA2 + +XK_XF86_Red = 0x1008FFA3 +XK_XF86_Green = 0x1008FFA4 +XK_XF86_Yellow = 0x1008FFA5 +XK_XF86_Blue = 0x1008FFA6 + +XK_XF86_Suspend = 0x1008FFA7 +XK_XF86_Hibernate = 0x1008FFA8 +XK_XF86_TouchpadToggle = 0x1008FFA9 +XK_XF86_TouchpadOn = 0x1008FFB0 +XK_XF86_TouchpadOff = 0x1008FFB1 + +XK_XF86_AudioMicMute = 0x1008FFB2 + +XK_XF86_Keyboard = 0x1008FFB3 + +XK_XF86_WWAN = 0x1008FFB4 +XK_XF86_RFKill = 0x1008FFB5 + +XK_XF86_AudioPreset = 0x1008FFB6 + +XK_XF86_RotationLockToggle = 0x1008FFB7 + +XK_XF86_FullScreen = 0x1008FFB8 + +XK_XF86_Switch_VT_1 = 0x1008FE01 +XK_XF86_Switch_VT_2 = 0x1008FE02 +XK_XF86_Switch_VT_3 = 0x1008FE03 +XK_XF86_Switch_VT_4 = 0x1008FE04 +XK_XF86_Switch_VT_5 = 0x1008FE05 +XK_XF86_Switch_VT_6 = 0x1008FE06 +XK_XF86_Switch_VT_7 = 0x1008FE07 +XK_XF86_Switch_VT_8 = 0x1008FE08 +XK_XF86_Switch_VT_9 = 0x1008FE09 +XK_XF86_Switch_VT_10 = 0x1008FE0A +XK_XF86_Switch_VT_11 = 0x1008FE0B +XK_XF86_Switch_VT_12 = 0x1008FE0C + +XK_XF86_Ungrab = 0x1008FE20 +XK_XF86_ClearGrab = 0x1008FE21 +XK_XF86_Next_VMode = 0x1008FE22 +XK_XF86_Prev_VMode = 0x1008FE23 +XK_XF86_LogWindowTree = 0x1008FE24 +XK_XF86_LogGrabInfo = 0x1008FE25 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xk3270.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xk3270.py new file mode 100644 index 0000000..b9395eb --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xk3270.py @@ -0,0 +1,30 @@ +XK_3270_Duplicate = 0xFD01 +XK_3270_FieldMark = 0xFD02 +XK_3270_Right2 = 0xFD03 +XK_3270_Left2 = 0xFD04 +XK_3270_BackTab = 0xFD05 +XK_3270_EraseEOF = 0xFD06 +XK_3270_EraseInput = 0xFD07 +XK_3270_Reset = 0xFD08 +XK_3270_Quit = 0xFD09 +XK_3270_PA1 = 0xFD0A +XK_3270_PA2 = 0xFD0B +XK_3270_PA3 = 0xFD0C +XK_3270_Test = 0xFD0D +XK_3270_Attn = 0xFD0E +XK_3270_CursorBlink = 0xFD0F +XK_3270_AltCursor = 0xFD10 +XK_3270_KeyClick = 0xFD11 +XK_3270_Jump = 0xFD12 +XK_3270_Ident = 0xFD13 +XK_3270_Rule = 0xFD14 +XK_3270_Copy = 0xFD15 +XK_3270_Play = 0xFD16 +XK_3270_Setup = 0xFD17 +XK_3270_Record = 0xFD18 +XK_3270_ChangeScreen = 0xFD19 +XK_3270_DeleteWord = 0xFD1A +XK_3270_ExSelect = 0xFD1B +XK_3270_CursorSelect = 0xFD1C +XK_3270_PrintScreen = 0xFD1D +XK_3270_Enter = 0xFD1E diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xkb.py b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xkb.py new file mode 100644 index 0000000..3be1f3d --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/keysymdef/xkb.py @@ -0,0 +1,100 @@ +XK_ISO_Lock = 0xFE01 +XK_ISO_Level2_Latch = 0xFE02 +XK_ISO_Level3_Shift = 0xFE03 +XK_ISO_Level3_Latch = 0xFE04 +XK_ISO_Level3_Lock = 0xFE05 +XK_ISO_Group_Shift = 0xFF7E +XK_ISO_Group_Latch = 0xFE06 +XK_ISO_Group_Lock = 0xFE07 +XK_ISO_Next_Group = 0xFE08 +XK_ISO_Next_Group_Lock = 0xFE09 +XK_ISO_Prev_Group = 0xFE0A +XK_ISO_Prev_Group_Lock = 0xFE0B +XK_ISO_First_Group = 0xFE0C +XK_ISO_First_Group_Lock = 0xFE0D +XK_ISO_Last_Group = 0xFE0E +XK_ISO_Last_Group_Lock = 0xFE0F +XK_ISO_Left_Tab = 0xFE20 +XK_ISO_Move_Line_Up = 0xFE21 +XK_ISO_Move_Line_Down = 0xFE22 +XK_ISO_Partial_Line_Up = 0xFE23 +XK_ISO_Partial_Line_Down = 0xFE24 +XK_ISO_Partial_Space_Left = 0xFE25 +XK_ISO_Partial_Space_Right = 0xFE26 +XK_ISO_Set_Margin_Left = 0xFE27 +XK_ISO_Set_Margin_Right = 0xFE28 +XK_ISO_Release_Margin_Left = 0xFE29 +XK_ISO_Release_Margin_Right = 0xFE2A +XK_ISO_Release_Both_Margins = 0xFE2B +XK_ISO_Fast_Cursor_Left = 0xFE2C +XK_ISO_Fast_Cursor_Right = 0xFE2D +XK_ISO_Fast_Cursor_Up = 0xFE2E +XK_ISO_Fast_Cursor_Down = 0xFE2F +XK_ISO_Continuous_Underline = 0xFE30 +XK_ISO_Discontinuous_Underline = 0xFE31 +XK_ISO_Emphasize = 0xFE32 +XK_ISO_Center_Object = 0xFE33 +XK_ISO_Enter = 0xFE34 +XK_dead_grave = 0xFE50 +XK_dead_acute = 0xFE51 +XK_dead_circumflex = 0xFE52 +XK_dead_tilde = 0xFE53 +XK_dead_macron = 0xFE54 +XK_dead_breve = 0xFE55 +XK_dead_abovedot = 0xFE56 +XK_dead_diaeresis = 0xFE57 +XK_dead_abovering = 0xFE58 +XK_dead_doubleacute = 0xFE59 +XK_dead_caron = 0xFE5A +XK_dead_cedilla = 0xFE5B +XK_dead_ogonek = 0xFE5C +XK_dead_iota = 0xFE5D +XK_dead_voiced_sound = 0xFE5E +XK_dead_semivoiced_sound = 0xFE5F +XK_dead_belowdot = 0xFE60 +XK_First_Virtual_Screen = 0xFED0 +XK_Prev_Virtual_Screen = 0xFED1 +XK_Next_Virtual_Screen = 0xFED2 +XK_Last_Virtual_Screen = 0xFED4 +XK_Terminate_Server = 0xFED5 +XK_AccessX_Enable = 0xFE70 +XK_AccessX_Feedback_Enable = 0xFE71 +XK_RepeatKeys_Enable = 0xFE72 +XK_SlowKeys_Enable = 0xFE73 +XK_BounceKeys_Enable = 0xFE74 +XK_StickyKeys_Enable = 0xFE75 +XK_MouseKeys_Enable = 0xFE76 +XK_MouseKeys_Accel_Enable = 0xFE77 +XK_Overlay1_Enable = 0xFE78 +XK_Overlay2_Enable = 0xFE79 +XK_AudibleBell_Enable = 0xFE7A +XK_Pointer_Left = 0xFEE0 +XK_Pointer_Right = 0xFEE1 +XK_Pointer_Up = 0xFEE2 +XK_Pointer_Down = 0xFEE3 +XK_Pointer_UpLeft = 0xFEE4 +XK_Pointer_UpRight = 0xFEE5 +XK_Pointer_DownLeft = 0xFEE6 +XK_Pointer_DownRight = 0xFEE7 +XK_Pointer_Button_Dflt = 0xFEE8 +XK_Pointer_Button1 = 0xFEE9 +XK_Pointer_Button2 = 0xFEEA +XK_Pointer_Button3 = 0xFEEB +XK_Pointer_Button4 = 0xFEEC +XK_Pointer_Button5 = 0xFEED +XK_Pointer_DblClick_Dflt = 0xFEEE +XK_Pointer_DblClick1 = 0xFEEF +XK_Pointer_DblClick2 = 0xFEF0 +XK_Pointer_DblClick3 = 0xFEF1 +XK_Pointer_DblClick4 = 0xFEF2 +XK_Pointer_DblClick5 = 0xFEF3 +XK_Pointer_Drag_Dflt = 0xFEF4 +XK_Pointer_Drag1 = 0xFEF5 +XK_Pointer_Drag2 = 0xFEF6 +XK_Pointer_Drag3 = 0xFEF7 +XK_Pointer_Drag4 = 0xFEF8 +XK_Pointer_Drag5 = 0xFEFD +XK_Pointer_EnableKeys = 0xFEF9 +XK_Pointer_Accelerate = 0xFEFA +XK_Pointer_DfltBtnNext = 0xFEFB +XK_Pointer_DfltBtnPrev = 0xFEFC diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__init__.py b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__init__.py new file mode 100644 index 0000000..5fa7fcb --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__init__.py @@ -0,0 +1,28 @@ +# Xlib.protocol.__init__ -- glue for Xlib.protocol package +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +__all__ = [ + 'display', + 'event', + 'request', + 'rq', + 'structs', + ] diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..4e81df6 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/display.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/display.cpython-312.pyc new file mode 100644 index 0000000..7a9f9e2 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/display.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/event.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/event.cpython-312.pyc new file mode 100644 index 0000000..b51a88b Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/event.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/request.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/request.cpython-312.pyc new file mode 100644 index 0000000..a20bfbb Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/request.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/rq.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/rq.cpython-312.pyc new file mode 100644 index 0000000..177c725 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/rq.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/structs.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/structs.cpython-312.pyc new file mode 100644 index 0000000..c4fc5cf Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/__pycache__/structs.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/display.py b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/display.py new file mode 100644 index 0000000..8531ee3 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/display.py @@ -0,0 +1,1075 @@ +# -*- coding: utf-8 -*- +# +# Xlib.protocol.display -- core display communication +# +# Copyright (C) 2000-2002 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +# Standard modules +import errno +import math +import select +import socket +import struct +import sys + +# Python 2/3 compatibility. +from six import PY3, byte2int, indexbytes + +# Xlib modules +from .. import error +from ..ext import ge + +from ..support import lock, connect + +# Xlib.protocol modules +from . import rq +from . import event + +if PY3: + + class bytesview(object): + + def __init__(self, data, offset=0, size=None): + if size is None: + size = len(data)-offset + if isinstance(data, bytes): + view = memoryview(data) + elif isinstance(data, bytesview): + view = data.view + else: + raise TypeError('unsupported type: {}'.format(type(data))) + self.view = view[offset:offset+size] + + def __len__(self): + return len(self.view) + + def __getitem__(self, key): + if isinstance(key, slice): + return bytes(self.view[key]) + return self.view[key] + +else: + + def bytesview(data, offset=0, size=None): + if not isinstance(data, (bytes, buffer)): + raise TypeError('unsupported type: {}'.format(type(data))) + if size is None: + size = len(data)-offset + return buffer(data, offset, size) + + +class Display(object): + extension_major_opcodes = {} + error_classes = error.xerror_class.copy() + event_classes = event.event_class.copy() + + def __init__(self, display = None): + name, protocol, host, displayno, screenno = connect.get_display(display) + + self.display_name = name + self.default_screen = screenno + + self.socket = connect.get_socket(name, protocol, host, displayno) + + auth_name, auth_data = connect.get_auth(self.socket, name, + protocol, host, displayno) + + # Internal structures for communication, grouped + # by their function and locks + + # Socket error indicator, set when the socket is closed + # in one way or another + self.socket_error_lock = lock.allocate_lock() + self.socket_error = None + + # Event queue + self.event_queue_read_lock = lock.allocate_lock() + self.event_queue_write_lock = lock.allocate_lock() + self.event_queue = [] + + # Unsent request queue and sequence number counter + self.request_queue_lock = lock.allocate_lock() + self.request_serial = 1 + self.request_queue = [] + + # Send-and-receive loop, see function send_and_receive + # for a detailed explanation + self.send_recv_lock = lock.allocate_lock() + self.send_active = 0 + self.recv_active = 0 + + self.event_waiting = 0 + self.event_wait_lock = lock.allocate_lock() + self.request_waiting = 0 + self.request_wait_lock = lock.allocate_lock() + + # Calculate optimal default buffer size for recv. + buffer_size = self.socket.getsockopt(socket.SOL_SOCKET, + socket.SO_RCVBUF) + buffer_size = math.pow(2, math.floor(math.log(buffer_size, 2))) + self.recv_buffer_size = int(buffer_size) + + # Data used by the send-and-receive loop + self.sent_requests = [] + self.recv_packet_len = 0 + self.data_send = b'' + self.data_recv = b'' + self.data_sent_bytes = 0 + + # Resource ID structures + self.resource_id_lock = lock.allocate_lock() + self.resource_ids = {} + self.last_resource_id = 0 + + # Use an default error handler, one which just prints the error + self.error_handler = None + + + # Right, now we're all set up for the connection setup + # request with the server. + + # Figure out which endianness the hardware uses + self.big_endian = struct.unpack('BB', struct.pack('H', 0x0100))[0] + + if self.big_endian: + order = 0x42 + else: + order = 0x6c + + # Send connection setup + r = ConnectionSetupRequest(self, + byte_order = order, + protocol_major = 11, + protocol_minor = 0, + auth_prot_name = auth_name, + auth_prot_data = auth_data) + + # Did connection fail? + if r.status != 1: + raise error.DisplayConnectionError(self.display_name, r.reason) + + # Set up remaining info + self.info = r + self.default_screen = min(self.default_screen, len(self.info.roots) - 1) + + + # + # Public interface + # + + def get_display_name(self): + return self.display_name + + def get_default_screen(self): + return self.default_screen + + def fileno(self): + self.check_for_error() + return self.socket.fileno() + + def next_event(self): + self.check_for_error() + + # Main lock, so that only one thread at a time performs the + # event waiting code. This at least guarantees that the first + # thread calling next_event() will get the next event, although + # no order is guaranteed among other threads calling next_event() + # while the first is blocking. + + self.event_queue_read_lock.acquire() + + # Lock event queue, so we can check if it is empty + self.event_queue_write_lock.acquire() + + # We have too loop until we get an event, as + # we might be woken up when there is no event. + + while not self.event_queue: + + # Lock send_recv so no send_and_receive + # can start or stop while we're checking + # whether there are one active. + self.send_recv_lock.acquire() + + # Release event queue to allow an send_and_recv to + # insert any now. + self.event_queue_write_lock.release() + + # Call send_and_recv, which will return when + # something has occured + self.send_and_recv(event = True) + + # Before looping around, lock the event queue against + # modifications. + self.event_queue_write_lock.acquire() + + # Whiew, we have an event! Remove it from + # the event queue and relaese its write lock. + + event = self.event_queue[0] + del self.event_queue[0] + self.event_queue_write_lock.release() + + # Finally, allow any other threads which have called next_event() + # while we were waiting to proceed. + + self.event_queue_read_lock.release() + + # And return the event! + return event + + def pending_events(self): + self.check_for_error() + + # Make a send_and_recv pass, receiving any events + self.send_recv_lock.acquire() + self.send_and_recv(recv = True) + + # Lock the queue, get the event count, and unlock again. + self.event_queue_write_lock.acquire() + count = len(self.event_queue) + self.event_queue_write_lock.release() + + return count + + def flush(self): + self.check_for_error() + self.send_recv_lock.acquire() + self.send_and_recv(flush = True) + + def close(self): + self.flush() + self.close_internal('client') + + def set_error_handler(self, handler): + self.error_handler = handler + + + def allocate_resource_id(self): + """id = d.allocate_resource_id() + + Allocate a new X resource id number ID. + + Raises ResourceIDError if there are no free resource ids. + """ + + self.resource_id_lock.acquire() + try: + i = self.last_resource_id + while i in self.resource_ids: + i = i + 1 + if i > self.info.resource_id_mask: + i = 0 + if i == self.last_resource_id: + raise error.ResourceIDError('out of resource ids') + + self.resource_ids[i] = None + self.last_resource_id = i + return self.info.resource_id_base | i + finally: + self.resource_id_lock.release() + + def free_resource_id(self, rid): + """d.free_resource_id(rid) + + Free resource id RID. Attempts to free a resource id which + isn't allocated by us are ignored. + """ + + self.resource_id_lock.acquire() + try: + i = rid & self.info.resource_id_mask + + # Attempting to free a resource id outside our range + if rid - i != self.info.resource_id_base: + return None + + try: + del self.resource_ids[i] + except KeyError: + pass + finally: + self.resource_id_lock.release() + + + + def get_resource_class(self, class_name, default = None): + """class = d.get_resource_class(class_name, default = None) + + Return the class to be used for X resource objects of type + CLASS_NAME, or DEFAULT if no such class is set. + """ + + return self.resource_classes.get(class_name, default) + + def set_extension_major(self, extname, major): + self.extension_major_opcodes[extname] = major + + def get_extension_major(self, extname): + return self.extension_major_opcodes[extname] + + def add_extension_event(self, code, evt, subcode=None): + if subcode == None: + self.event_classes[code] = evt + else: + if not code in self.event_classes: + self.event_classes[code] = {subcode: evt} + else: + self.event_classes[code][subcode] = evt + + def add_extension_error(self, code, err): + self.error_classes[code] = err + + + # + # Private functions + # + + def check_for_error(self): + self.socket_error_lock.acquire() + err = self.socket_error + self.socket_error_lock.release() + + if err: + raise err + + def send_request(self, request, wait_for_response): + if self.socket_error: + raise self.socket_error + + self.request_queue_lock.acquire() + + request._serial = self.request_serial + self.request_serial = (self.request_serial + 1) % 65536 + + self.request_queue.append((request, wait_for_response)) + qlen = len(self.request_queue) + + self.request_queue_lock.release() + +# if qlen > 10: +# self.flush() + + def close_internal(self, whom): + # Clear out data structures + self.request_queue = None + self.sent_requests = None + self.event_queue = None + self.data_send = None + self.data_recv = None + + # Close the connection + self.socket.close() + + # Set a connection closed indicator + self.socket_error_lock.acquire() + self.socket_error = error.ConnectionClosedError(whom) + self.socket_error_lock.release() + + + def send_and_recv(self, flush = False, event = False, request = None, recv = False): + """send_and_recv(flush = None, event = None, request = None, recv = None) + + Perform I/O, or wait for some other thread to do it for us. + + send_recv_lock MUST be LOCKED when send_and_recv is called. + It will be UNLOCKED at return. + + Exactly or one of the parameters flush, event, request and recv must + be set to control the return condition. + + To attempt to send all requests in the queue, flush should + be true. Will return immediately if another thread is + already doing send_and_recv. + + To wait for an event to be received, event should be true. + + To wait for a response to a certain request (either an error + or a response), request should be set to that request's + serial number. + + To just read any pending data from the server, recv should be true. + + It is not guaranteed that the return condition has been + fulfilled when the function returns, so the caller has to loop + until it is finished. + """ + + # We go to sleep if there is already a thread doing what we + # want to do: + + # If flushing, we want to send + # If waiting for a response to a request, we want to send + # (to ensure that the request was sent - we alway recv + # when we get to the main loop, but sending is the important + # thing here) + # If waiting for an event, we want to recv + # If just trying to receive anything we can, we want to recv + + # FIXME: It would be good if we could also sleep when we're waiting on + # a response to a request that has already been sent. + + if (((flush or request is not None) and self.send_active) + or ((event or recv) and self.recv_active)): + + # Signal that we are waiting for something. These locks + # together with the *_waiting variables are used as + # semaphores. When an event or a request response arrives, + # it will zero the *_waiting and unlock the lock. The + # locks will also be unlocked when an active send_and_recv + # finishes to signal the other waiting threads that one of + # them has to take over the send_and_recv function. + + # All this makes these locks and variables a part of the + # send_and_recv control logic, and hence must be modified + # only when we have the send_recv_lock locked. + if event: + wait_lock = self.event_wait_lock + if not self.event_waiting: + self.event_waiting = 1 + wait_lock.acquire() + + elif request is not None: + wait_lock = self.request_wait_lock + if not self.request_waiting: + self.request_waiting = 1 + wait_lock.acquire() + + # Release send_recv, allowing a send_and_recive + # to terminate or other threads to queue up + self.send_recv_lock.release() + + # Return immediately if flushing, even if that + # might mean that not necessarily all requests + # have been sent. + if flush or recv: + return + + # Wait for something to happen, as the wait locks are + # unlocked either when what we wait for has arrived (not + # necessarily the exact object we're waiting for, though), + # or when an active send_and_recv exits. + + # Release it immediately afterwards as we're only using + # the lock for synchonization. Since we're not modifying + # event_waiting or request_waiting here we don't have + # to lock send_and_recv_lock. In fact, we can't do that + # or we trigger a dead-lock. + + wait_lock.acquire() + wait_lock.release() + + # Return to caller to let it check whether it has + # got the data it was waiting for + return + + + # There's no thread doing what we need to do. Find out exactly + # what to do + + # There must always be some thread receiving data, but it must not + # necessarily be us + + if not self.recv_active: + receiving = 1 + self.recv_active = 1 + else: + receiving = 0 + + flush_bytes = None + sending = 0 + + # Loop, receiving and sending data. + while 1: + + # We might want to start sending data + if sending or not self.send_active: + + # Turn all requests on request queue into binary form + # and append them to self.data_send + + self.request_queue_lock.acquire() + for req, wait in self.request_queue: + self.data_send = self.data_send + req._binary + if wait: + self.sent_requests.append(req) + + del self.request_queue[:] + self.request_queue_lock.release() + + # If there now is data to send, mark us as senders + + if self.data_send: + self.send_active = 1 + sending = 1 + else: + self.send_active = 0 + sending = 0 + + # We've done all setup, so release the lock and start waiting + # for the network to fire up + self.send_recv_lock.release() + + # There's no longer anything useful we can do here. + if not (sending or receiving): + break + + # If we're flushing, figure out how many bytes we + # have to send so that we're not caught in an interminable + # loop if other threads continuously append requests. + if flush and flush_bytes is None: + flush_bytes = self.data_sent_bytes + len(self.data_send) + + + try: + # We're only checking for the socket to be writable + # if we're the sending thread. We always check for it + # to become readable: either we are the receiving thread + # and should take care of the data, or the receiving thread + # might finish receiving after having read the data + + if sending: + writeset = [self.socket] + else: + writeset = [] + + # Timeout immediately if we're only checking for + # something to read or if we're flushing, otherwise block + + if recv or flush: + timeout = 0 + else: + timeout = None + + rs, ws, es = select.select([self.socket], writeset, [], timeout) + + # Ignore errors caused by a signal received while blocking. + # All other errors are re-raised. + except select.error as err: + if isinstance(err, OSError): + code = err.errno + else: + code = err[0] + if code != errno.EINTR: + raise + + # We must lock send_and_recv before we can loop to + # the start of the loop + + self.send_recv_lock.acquire() + continue + + + # Socket is ready for sending data, send as much as possible. + if ws: + try: + i = self.socket.send(self.data_send) + except socket.error as err: + self.close_internal('server: %s' % err) + raise self.socket_error + + self.data_send = self.data_send[i:] + self.data_sent_bytes = self.data_sent_bytes + i + + + # There is data to read + gotreq = 0 + if rs: + + # We're the receiving thread, parse the data + if receiving: + try: + count = self.recv_packet_len - len(self.data_recv) + count = max(self.recv_buffer_size, count) + bytes_recv = self.socket.recv(count) + except socket.error as err: + self.close_internal('server: %s' % err) + raise self.socket_error + + if not bytes_recv: + # Clear up, set a connection closed indicator and raise it + self.close_internal('server') + raise self.socket_error + + self.data_recv = bytes(self.data_recv) + bytes_recv + gotreq = self.parse_response(request) + + # Otherwise return, allowing the calling thread to figure + # out if it has got the data it needs + else: + # We must be a sending thread if we're here, so reset + # that indicator. + self.send_recv_lock.acquire() + self.send_active = 0 + self.send_recv_lock.release() + + # And return to the caller + return + + + # There are three different end of send-recv-loop conditions. + # However, we don't leave the loop immediately, instead we + # try to send and receive any data that might be left. We + # do this by giving a timeout of 0 to select to poll + # the socket. + + # When flushing: all requests have been sent + if flush and flush_bytes >= self.data_sent_bytes: + break + + # When waiting for an event: an event has been read + if event and self.event_queue: + break + + # When processing a certain request: got its reply + if request is not None and gotreq: + break + + # Always break if we just want to receive as much as possible + if recv: + break + + # Else there's may still data which must be sent, or + # we haven't got the data we waited for. Lock and loop + + self.send_recv_lock.acquire() + + + # We have accomplished the callers request. + # Record that there are now no active send_and_recv, + # and wake up all waiting thread + + self.send_recv_lock.acquire() + + if sending: + self.send_active = 0 + if receiving: + self.recv_active = 0 + + if self.event_waiting: + self.event_waiting = 0 + self.event_wait_lock.release() + + if self.request_waiting: + self.request_waiting = 0 + self.request_wait_lock.release() + + self.send_recv_lock.release() + + + def parse_response(self, request): + """Internal method. + + Parse data received from server. If REQUEST is not None + true is returned if the request with that serial number + was received, otherwise false is returned. + + If REQUEST is -1, we're parsing the server connection setup + response. + """ + + if request == -1: + return self.parse_connection_setup() + + # Parse ordinary server response + gotreq = False + while True: + if self.data_recv: + # Check the first byte to find out what kind of response it is + rtype = byte2int(self.data_recv) + + # Are we're waiting for additional data for the current packet? + if self.recv_packet_len: + if len(self.data_recv) < self.recv_packet_len: + return gotreq + + if rtype == 1: + gotreq = self.parse_request_response(request) or gotreq + continue + elif rtype & 0x7f == ge.GenericEventCode: + self.parse_event_response(rtype) + continue + else: + raise AssertionError(rtype) + + # Every response is at least 32 bytes long, so don't bother + # until we have received that much + if len(self.data_recv) < 32: + return gotreq + + # Error response + if rtype == 0: + gotreq = self.parse_error_response(request) or gotreq + + # Request response or generic event. + elif rtype == 1 or rtype & 0x7f == ge.GenericEventCode: + # Set reply length, and loop around to see if + # we have got the full response + rlen = int(struct.unpack('=L', self.data_recv[4:8])[0]) + self.recv_packet_len = 32 + rlen * 4 + + # Else non-generic event + else: + self.parse_event_response(rtype) + + + def parse_error_response(self, request): + # Code is second byte + code = indexbytes(self.data_recv, 1) + + # Fetch error class + estruct = self.error_classes.get(code, error.XError) + + e = estruct(self, self.data_recv[:32]) + self.data_recv = bytesview(self.data_recv, 32) + + # print 'recv Error:', e + + req = self.get_waiting_request(e.sequence_number) + + # Error for a request whose response we are waiting for, + # or which have an error handler. However, if the error + # handler indicates that it hasn't taken care of the + # error, pass it on to the default error handler + + if req and req._set_error(e): + + # If this was a ReplyRequest, unlock any threads waiting + # for a request to finish + + if isinstance(req, rq.ReplyRequest): + self.send_recv_lock.acquire() + + if self.request_waiting: + self.request_waiting = 0 + self.request_wait_lock.release() + + self.send_recv_lock.release() + + return request == e.sequence_number + + # Else call the error handler + else: + if self.error_handler: + rq.call_error_handler(self.error_handler, e, None) + else: + self.default_error_handler(e) + + return False + + + def default_error_handler(self, err): + sys.stderr.write('X protocol error:\n%s\n' % err) + + + def parse_request_response(self, request): + req = self.get_waiting_replyrequest() + + # Sequence number is always data[2:4] + # Do sanity check before trying to parse the data + sno = struct.unpack('=H', self.data_recv[2:4])[0] + if sno != req._serial: + raise RuntimeError("Expected reply for request %s, but got %s. Can't happen!" + % (req._serial, sno)) + + req._parse_response(self.data_recv[:self.recv_packet_len]) + # print 'recv Request:', req + + self.data_recv = bytesview(self.data_recv, self.recv_packet_len) + self.recv_packet_len = 0 + + + # Unlock any response waiting threads + + self.send_recv_lock.acquire() + + if self.request_waiting: + self.request_waiting = 0 + self.request_wait_lock.release() + + self.send_recv_lock.release() + + + return req.sequence_number == request + + + def parse_event_response(self, etype): + # Skip bit 8, that is set if this event came from an SendEvent + etype = etype & 0x7f + + if etype == ge.GenericEventCode: + length = self.recv_packet_len + else: + length = 32 + + estruct = self.event_classes.get(etype, event.AnyEvent) + if type(estruct) == dict: + subcode = self.data_recv[1] + + # Python2 compatibility + if type(subcode) == str: + subcode = ord(subcode) + + # this etype refers to a set of sub-events with individual subcodes + estruct = estruct[subcode] + + e = estruct(display = self, binarydata = self.data_recv[:length]) + + if etype == ge.GenericEventCode: + self.recv_packet_len = 0 + + self.data_recv = bytesview(self.data_recv, length) + + # Drop all requests having an error handler, + # but which obviously succeded. + + # Decrement it by one, so that we don't remove the request + # that generated these events, if there is such a one. + # Bug reported by Ilpo Nyyssönen + # Note: not all events have a sequence_number field! + # (e.g. KeymapNotify). + if hasattr(e, 'sequence_number'): + self.get_waiting_request((e.sequence_number - 1) % 65536) + + # print 'recv Event:', e + + # Insert the event into the queue + self.event_queue_write_lock.acquire() + self.event_queue.append(e) + self.event_queue_write_lock.release() + + # Unlock any event waiting threads + self.send_recv_lock.acquire() + + if self.event_waiting: + self.event_waiting = 0 + self.event_wait_lock.release() + + self.send_recv_lock.release() + + + def get_waiting_request(self, sno): + if not self.sent_requests: + return None + + # Normalize sequence numbers, even if they have wrapped. + # This ensures that + # sno <= last_serial + # and + # self.sent_requests[0]._serial <= last_serial + + if self.sent_requests[0]._serial > self.request_serial: + last_serial = self.request_serial + 65536 + if sno < self.request_serial: + sno = sno + 65536 + + else: + last_serial = self.request_serial + if sno > self.request_serial: + sno = sno - 65536 + + # No matching events at all + if sno < self.sent_requests[0]._serial: + return None + + # Find last req <= sno + req = None + reqpos = len(self.sent_requests) + adj = 0 + last = 0 + + for i in range(0, len(self.sent_requests)): + rno = self.sent_requests[i]._serial + adj + + # Did serial numbers just wrap around? + if rno < last: + adj = 65536 + rno = rno + adj + + last = rno + + if sno == rno: + req = self.sent_requests[i] + reqpos = i + 1 + break + elif sno < rno: + req = None + reqpos = i + break + + # Delete all request such as req <= sno + del self.sent_requests[:reqpos] + + return req + + def get_waiting_replyrequest(self): + for i in range(0, len(self.sent_requests)): + if hasattr(self.sent_requests[i], '_reply'): + req = self.sent_requests[i] + del self.sent_requests[:i + 1] + return req + + # Reply for an unknown request? No, that can't happen. + else: + raise RuntimeError("Request reply to unknown request. Can't happen!") + + def parse_connection_setup(self): + """Internal function used to parse connection setup response. + """ + + # Only the ConnectionSetupRequest has been sent so far + r = self.sent_requests[0] + + while True: + # print 'data_send:', repr(self.data_send) + # print 'data_recv:', repr(self.data_recv) + + if r._data: + alen = r._data['additional_length'] * 4 + + # The full response haven't arrived yet + if len(self.data_recv) < alen: + return False + + # Connection failed or further authentication is needed. + # Set reason to the reason string + if r._data['status'] != 1: + r._data['reason'] = self.data_recv[:r._data['reason_length']] + + # Else connection succeeded, parse the reply + else: + x, d = r._success_reply.parse_binary(self.data_recv[:alen], + self, rawdict = True) + r._data.update(x) + + del self.sent_requests[0] + + self.data_recv = self.data_recv[alen:] + + return True + + else: + # The base reply is 8 bytes long + if len(self.data_recv) < 8: + return False + + r._data, d = r._reply.parse_binary(self.data_recv[:8], + self, rawdict = True) + self.data_recv = self.data_recv[8:] + + # Loop around to see if we have got the additional data + # already + + +PixmapFormat = rq.Struct( rq.Card8('depth'), + rq.Card8('bits_per_pixel'), + rq.Card8('scanline_pad'), + rq.Pad(5) + ) + +VisualType = rq.Struct ( rq.Card32('visual_id'), + rq.Card8('visual_class'), + rq.Card8('bits_per_rgb_value'), + rq.Card16('colormap_entries'), + rq.Card32('red_mask'), + rq.Card32('green_mask'), + rq.Card32('blue_mask'), + rq.Pad(4) + ) + +Depth = rq.Struct( rq.Card8('depth'), + rq.Pad(1), + rq.LengthOf('visuals', 2), + rq.Pad(4), + rq.List('visuals', VisualType) + ) + +Screen = rq.Struct( rq.Window('root'), + rq.Colormap('default_colormap'), + rq.Card32('white_pixel'), + rq.Card32('black_pixel'), + rq.Card32('current_input_mask'), + rq.Card16('width_in_pixels'), + rq.Card16('height_in_pixels'), + rq.Card16('width_in_mms'), + rq.Card16('height_in_mms'), + rq.Card16('min_installed_maps'), + rq.Card16('max_installed_maps'), + rq.Card32('root_visual'), + rq.Card8('backing_store'), + rq.Card8('save_unders'), + rq.Card8('root_depth'), + rq.LengthOf('allowed_depths', 1), + rq.List('allowed_depths', Depth) + ) + + +class ConnectionSetupRequest(rq.GetAttrData): + _request = rq.Struct( rq.Set('byte_order', 1, (0x42, 0x6c)), + rq.Pad(1), + rq.Card16('protocol_major'), + rq.Card16('protocol_minor'), + rq.LengthOf('auth_prot_name', 2), + rq.LengthOf('auth_prot_data', 2), + rq.Pad(2), + rq.String8('auth_prot_name'), + rq.String8('auth_prot_data') ) + + _reply = rq.Struct ( rq.Card8('status'), + rq.Card8('reason_length'), + rq.Card16('protocol_major'), + rq.Card16('protocol_minor'), + rq.Card16('additional_length') ) + + _success_reply = rq.Struct( rq.Card32('release_number'), + rq.Card32('resource_id_base'), + rq.Card32('resource_id_mask'), + rq.Card32('motion_buffer_size'), + rq.LengthOf('vendor', 2), + rq.Card16('max_request_length'), + rq.LengthOf('roots', 1), + rq.LengthOf('pixmap_formats', 1), + rq.Card8('image_byte_order'), + rq.Card8('bitmap_format_bit_order'), + rq.Card8('bitmap_format_scanline_unit'), + rq.Card8('bitmap_format_scanline_pad'), + rq.Card8('min_keycode'), + rq.Card8('max_keycode'), + rq.Pad(4), + rq.String8('vendor'), + rq.List('pixmap_formats', PixmapFormat), + rq.List('roots', Screen), + ) + + + def __init__(self, display, *args, **keys): + self._binary = self._request.to_binary(*args, **keys) + self._data = None + + # Don't bother about locking, since no other threads have + # access to the display yet + + display.request_queue.append((self, True)) + + # However, we must lock send_and_recv, but we don't have + # to loop. + + display.send_recv_lock.acquire() + display.send_and_recv(request = -1) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/event.py b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/event.py new file mode 100644 index 0000000..4524452 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/event.py @@ -0,0 +1,434 @@ +# Xlib.protocol.event -- definitions of core events +# +# Copyright (C) 2000-2002 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +# Xlib modules +from .. import X + +# Xlib.protocol modules +from . import rq + + +class AnyEvent(rq.Event): + _code = None + _fields = rq.Struct( rq.Card8('type'), + rq.Card8('detail'), + rq.Card16('sequence_number'), + rq.FixedBinary('data', 28), + ) + +class KeyButtonPointer(rq.Event): + _code = None + _fields = rq.Struct( rq.Card8('type'), + rq.Card8('detail'), + rq.Card16('sequence_number'), + rq.Card32('time'), + rq.Window('root'), + rq.Window('window'), + rq.Window('child', (X.NONE, )), + rq.Int16('root_x'), + rq.Int16('root_y'), + rq.Int16('event_x'), + rq.Int16('event_y'), + rq.Card16('state'), + rq.Card8('same_screen'), + rq.Pad(1), + ) + +class KeyPress(KeyButtonPointer): + _code = X.KeyPress + +class KeyRelease(KeyButtonPointer): + _code = X.KeyRelease + +class ButtonPress(KeyButtonPointer): + _code = X.ButtonPress + +class ButtonRelease(KeyButtonPointer): + _code = X.ButtonRelease + +class MotionNotify(KeyButtonPointer): + _code = X.MotionNotify + +class EnterLeave(rq.Event): + _code = None + _fields = rq.Struct( rq.Card8('type'), + rq.Card8('detail'), + rq.Card16('sequence_number'), + rq.Card32('time'), + rq.Window('root'), + rq.Window('window'), + rq.Window('child', (X.NONE, )), + rq.Int16('root_x'), + rq.Int16('root_y'), + rq.Int16('event_x'), + rq.Int16('event_y'), + rq.Card16('state'), + rq.Card8('mode'), + rq.Card8('flags'), + ) + +class EnterNotify(EnterLeave): + _code = X.EnterNotify + +class LeaveNotify(EnterLeave): + _code = X.LeaveNotify + + +class Focus(rq.Event): + _code = None + _fields = rq.Struct( rq.Card8('type'), + rq.Card8('detail'), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card8('mode'), + rq.Pad(23), + ) + +class FocusIn(Focus): + _code = X.FocusIn + +class FocusOut(Focus): + _code = X.FocusOut + +class Expose(rq.Event): + _code = X.Expose + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card16('x'), + rq.Card16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('count'), + rq.Pad(14), + ) + +class GraphicsExpose(rq.Event): + _code = X.GraphicsExpose + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Drawable('drawable'), + rq.Card16('x'), + rq.Card16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('minor_event'), + rq.Card16('count'), + rq.Card8('major_event'), + rq.Pad(11), + ) + +class NoExpose(rq.Event): + _code = X.NoExpose + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Drawable('window'), + rq.Card16('minor_event'), + rq.Card8('major_event'), + rq.Pad(21), + ) + +class VisibilityNotify(rq.Event): + _code = X.VisibilityNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card8('state'), + rq.Pad(23), + ) + +class CreateNotify(rq.Event): + _code = X.CreateNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('parent'), + rq.Window('window'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('border_width'), + rq.Card8('override'), + rq.Pad(9), + ) + +class DestroyNotify(rq.Event): + _code = X.DestroyNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('event'), + rq.Window('window'), + rq.Pad(20), + ) + +class UnmapNotify(rq.Event): + _code = X.UnmapNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('event'), + rq.Window('window'), + rq.Card8('from_configure'), + rq.Pad(19), + ) + +class MapNotify(rq.Event): + _code = X.MapNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('event'), + rq.Window('window'), + rq.Card8('override'), + rq.Pad(19), + ) + +class MapRequest(rq.Event): + _code = X.MapRequest + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('parent'), + rq.Window('window'), + rq.Pad(20), + ) + +class ReparentNotify(rq.Event): + _code = X.ReparentNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('event'), + rq.Window('window'), + rq.Window('parent'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card8('override'), + rq.Pad(11), + ) + +class ConfigureNotify(rq.Event): + _code = X.ConfigureNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('event'), + rq.Window('window'), + rq.Window('above_sibling', (X.NONE, )), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('border_width'), + rq.Card8('override'), + rq.Pad(5), + ) + +class ConfigureRequest(rq.Event): + _code = X.ConfigureRequest + _fields = rq.Struct( rq.Card8('type'), + rq.Card8('stack_mode'), + rq.Card16('sequence_number'), + rq.Window('parent'), + rq.Window('window'), + rq.Window('sibling', (X.NONE, )), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('border_width'), + rq.Card16('value_mask'), + rq.Pad(4), + ) + +class GravityNotify(rq.Event): + _code = X.GravityNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('event'), + rq.Window('window'), + rq.Int16('x'), + rq.Int16('y'), + rq.Pad(16), + ) + +class ResizeRequest(rq.Event): + _code = X.ResizeRequest + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card16('width'), + rq.Card16('height'), + rq.Pad(20), + ) + +class Circulate(rq.Event): + _code = None + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('event'), + rq.Window('window'), + rq.Pad(4), + rq.Card8('place'), + rq.Pad(15), + ) + +class CirculateNotify(Circulate): + _code = X.CirculateNotify + +class CirculateRequest(Circulate): + _code = X.CirculateRequest + +class PropertyNotify(rq.Event): + _code = X.PropertyNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card32('atom'), + rq.Card32('time'), + rq.Card8('state'), + rq.Pad(15), + ) + +class SelectionClear(rq.Event): + _code = X.SelectionClear + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Card32('time'), + rq.Window('window'), + rq.Card32('atom'), + rq.Pad(16), + ) + +class SelectionRequest(rq.Event): + _code = X.SelectionRequest + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Card32('time'), + rq.Window('owner'), + rq.Window('requestor'), + rq.Card32('selection'), + rq.Card32('target'), + rq.Card32('property'), + rq.Pad(4), + ) + +class SelectionNotify(rq.Event): + _code = X.SelectionNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Card32('time'), + rq.Window('requestor'), + rq.Card32('selection'), + rq.Card32('target'), + rq.Card32('property'), + rq.Pad(8), + ) + +class ColormapNotify(rq.Event): + _code = X.ColormapNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Colormap('colormap', (X.NONE, )), + rq.Card8('new'), + rq.Card8('state'), + rq.Pad(18), + ) + +class MappingNotify(rq.Event): + _code = X.MappingNotify + _fields = rq.Struct( rq.Card8('type'), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.Card8('request'), + rq.Card8('first_keycode'), + rq.Card8('count'), + rq.Pad(25), + ) + +class ClientMessage(rq.Event): + _code = X.ClientMessage + _fields = rq.Struct( rq.Card8('type'), + rq.Format('data', 1), + rq.Card16('sequence_number'), + rq.Window('window'), + rq.Card32('client_type'), + rq.FixedPropertyData('data', 20), + ) + +class KeymapNotify(rq.Event): + _code = X.KeymapNotify + _fields = rq.Struct( rq.Card8('type'), + rq.FixedList('data', 31, rq.Card8Obj, pad = 0) + ) + + +event_class = { + X.KeyPress: KeyPress, + X.KeyRelease: KeyRelease, + X.ButtonPress: ButtonPress, + X.ButtonRelease: ButtonRelease, + X.MotionNotify: MotionNotify, + X.EnterNotify: EnterNotify, + X.LeaveNotify: LeaveNotify, + X.FocusIn: FocusIn, + X.FocusOut: FocusOut, + X.KeymapNotify: KeymapNotify, + X.Expose: Expose, + X.GraphicsExpose: GraphicsExpose, + X.NoExpose: NoExpose, + X.VisibilityNotify: VisibilityNotify, + X.CreateNotify: CreateNotify, + X.DestroyNotify: DestroyNotify, + X.UnmapNotify: UnmapNotify, + X.MapNotify: MapNotify, + X.MapRequest: MapRequest, + X.ReparentNotify: ReparentNotify, + X.ConfigureNotify: ConfigureNotify, + X.ConfigureRequest: ConfigureRequest, + X.GravityNotify: GravityNotify, + X.ResizeRequest: ResizeRequest, + X.CirculateNotify: CirculateNotify, + X.CirculateRequest: CirculateRequest, + X.PropertyNotify: PropertyNotify, + X.SelectionClear: SelectionClear, + X.SelectionRequest: SelectionRequest, + X.SelectionNotify: SelectionNotify, + X.ColormapNotify: ColormapNotify, + X.ClientMessage: ClientMessage, + X.MappingNotify: MappingNotify, + } diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/request.py b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/request.py new file mode 100644 index 0000000..608a768 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/request.py @@ -0,0 +1,1900 @@ +# Xlib.protocol.request -- definitions of core requests +# +# Copyright (C) 2000-2002 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +# Xlib modules +from .. import X + +# Xlib.protocol modules +from . import rq +from . import structs + + +class CreateWindow(rq.Request): + _request = rq.Struct( + rq.Opcode(1), + rq.Card8('depth'), + rq.RequestLength(), + rq.Window('wid'), + rq.Window('parent'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('border_width'), + rq.Set('window_class', 2, (X.CopyFromParent, X.InputOutput, X.InputOnly)), + rq.Card32('visual'), + structs.WindowValues('attrs'), + ) + +class ChangeWindowAttributes(rq.Request): + _request = rq.Struct( + rq.Opcode(2), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window'), + structs.WindowValues('attrs'), + ) + +class GetWindowAttributes(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(3), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('backing_store'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('visual'), + rq.Card16('win_class'), + rq.Card8('bit_gravity'), + rq.Card8('win_gravity'), + rq.Card32('backing_bit_planes'), + rq.Card32('backing_pixel'), + rq.Card8('save_under'), + rq.Card8('map_is_installed'), + rq.Card8('map_state'), + rq.Card8('override_redirect'), + rq.Colormap('colormap', (X.NONE, )), + rq.Card32('all_event_masks'), + rq.Card32('your_event_mask'), + rq.Card16('do_not_propagate_mask'), + rq.Pad(2), + ) + +class DestroyWindow(rq.Request): + _request = rq.Struct( + rq.Opcode(4), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + +class DestroySubWindows(rq.Request): + _request = rq.Struct( + rq.Opcode(5), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + +class ChangeSaveSet(rq.Request): + _request = rq.Struct( + rq.Opcode(6), + rq.Set('mode', 1, (X.SetModeInsert, X.SetModeDelete)), + rq.RequestLength(), + rq.Window('window'), + ) + +class ReparentWindow(rq.Request): + _request = rq.Struct( + rq.Opcode(7), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window'), + rq.Window('parent'), + rq.Int16('x'), + rq.Int16('y'), + ) + +class MapWindow(rq.Request): + _request = rq.Struct( + rq.Opcode(8), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + +class MapSubwindows(rq.Request): + _request = rq.Struct( + rq.Opcode(9), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + +class UnmapWindow(rq.Request): + _request = rq.Struct( + rq.Opcode(10), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + +class UnmapSubwindows(rq.Request): + _request = rq.Struct( + rq.Opcode(11), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + +class ConfigureWindow(rq.Request): + _request = rq.Struct( + rq.Opcode(12), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window'), + rq.ValueList( 'attrs', 2, 2, + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Int16('border_width'), + rq.Window('sibling'), + rq.Set('stack_mode', 1, + (X.Above, X.Below, X.TopIf, + X.BottomIf, X.Opposite)) + ) + ) + +class CirculateWindow(rq.Request): + _request = rq.Struct( + rq.Opcode(13), + rq.Set('direction', 1, (X.RaiseLowest, X.LowerHighest)), + rq.RequestLength(), + rq.Window('window'), + ) + +class GetGeometry(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(14), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable') + ) + + _reply = rq.Struct ( + rq.ReplyCode(), + rq.Card8('depth'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('root'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card16('border_width'), + rq.Pad(10) + ) + +class QueryTree(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(15), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('root'), + rq.Window('parent', (X.NONE, )), + rq.LengthOf('children', 2), + rq.Pad(14), + rq.List('children', rq.WindowObj), + ) + +class InternAtom(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(16), + rq.Bool('only_if_exists'), + rq.RequestLength(), + rq.LengthOf('name', 2), + rq.Pad(2), + rq.String8('name'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('atom'), + rq.Pad(20), + ) + + +class GetAtomName(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(17), + rq.Pad(1), + rq.RequestLength(), + rq.Card32('atom') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('name', 2), + rq.Pad(22), + rq.String8('name'), + ) + +class ChangeProperty(rq.Request): + _request = rq.Struct( + rq.Opcode(18), + rq.Set('mode', 1, (X.PropModeReplace, X.PropModePrepend, X.PropModeAppend)), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('property'), + rq.Card32('type'), + rq.Format('data', 1), + rq.Pad(3), + rq.LengthOf('data', 4), + rq.PropertyData('data'), + ) + +class DeleteProperty(rq.Request): + _request = rq.Struct( + rq.Opcode(19), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('property'), + ) + +class GetProperty(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(20), + rq.Bool('delete'), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('property'), + rq.Card32('type'), + rq.Card32('long_offset'), + rq.Card32('long_length'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Format('value', 1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('property_type'), + rq.Card32('bytes_after'), + rq.LengthOf('value', 4), + rq.Pad(12), + rq.PropertyData('value'), + ) + +class ListProperties(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(21), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('atoms', 2), + rq.Pad(22), + rq.List('atoms', rq.Card32Obj), + ) + +class SetSelectionOwner(rq.Request): + _request = rq.Struct( + rq.Opcode(22), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('selection'), + rq.Card32('time'), + ) + +class GetSelectionOwner(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(23), + rq.Pad(1), + rq.RequestLength(), + rq.Card32('selection') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('owner', (X.NONE, )), + rq.Pad(20), + ) + +class ConvertSelection(rq.Request): + _request = rq.Struct( + rq.Opcode(24), + rq.Pad(1), + rq.RequestLength(), + rq.Window('requestor'), + rq.Card32('selection'), + rq.Card32('target'), + rq.Card32('property'), + rq.Card32('time'), + ) + +class SendEvent(rq.Request): + _request = rq.Struct( + rq.Opcode(25), + rq.Bool('propagate'), + rq.RequestLength(), + rq.Window('destination'), + rq.Card32('event_mask'), + rq.EventField('event'), + ) + +class GrabPointer(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(26), + rq.Bool('owner_events'), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card16('event_mask'), + rq.Set('pointer_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Set('keyboard_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Window('confine_to', (X.NONE, )), + rq.Cursor('cursor', (X.NONE, )), + rq.Card32('time'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + ) + +class UngrabPointer(rq.Request): + _request = rq.Struct( + rq.Opcode(27), + rq.Pad(1), + rq.RequestLength(), + rq.Card32('time') + ) + +class GrabButton(rq.Request): + _request = rq.Struct( + rq.Opcode(28), + rq.Bool('owner_events'), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card16('event_mask'), + rq.Set('pointer_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Set('keyboard_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Window('confine_to', (X.NONE, )), + rq.Cursor('cursor', (X.NONE, )), + rq.Card8('button'), + rq.Pad(1), + rq.Card16('modifiers'), + ) + +class UngrabButton(rq.Request): + _request = rq.Struct( + rq.Opcode(29), + rq.Card8('button'), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card16('modifiers'), + rq.Pad(2), + ) + +class ChangeActivePointerGrab(rq.Request): + _request = rq.Struct( + rq.Opcode(30), + rq.Pad(1), + rq.RequestLength(), + rq.Cursor('cursor'), + rq.Card32('time'), + rq.Card16('event_mask'), + rq.Pad(2), + ) + +class GrabKeyboard(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(31), + rq.Bool('owner_events'), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card32('time'), + rq.Set('pointer_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Set('keyboard_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Pad(2), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + ) + +class UngrabKeyboard(rq.Request): + _request = rq.Struct( + rq.Opcode(32), + rq.Pad(1), + rq.RequestLength(), + rq.Card32('time') + ) + +class GrabKey(rq.Request): + _request = rq.Struct( + rq.Opcode(33), + rq.Bool('owner_events'), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card16('modifiers'), + rq.Card8('key'), + rq.Set('pointer_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Set('keyboard_mode', 1, (X.GrabModeSync, X.GrabModeAsync)), + rq.Pad(3), + ) + +class UngrabKey(rq.Request): + _request = rq.Struct( + rq.Opcode(34), + rq.Card8('key'), + rq.RequestLength(), + rq.Window('grab_window'), + rq.Card16('modifiers'), + rq.Pad(2), + ) + +class AllowEvents(rq.Request): + _request = rq.Struct( + rq.Opcode(35), + rq.Set('mode', 1, (X.AsyncPointer, + X.SyncPointer, + X.ReplayPointer, + X.AsyncKeyboard, + X.SyncKeyboard, + X.ReplayKeyboard, + X.AsyncBoth, + X.SyncBoth)), + rq.RequestLength(), + rq.Card32('time'), + ) + +class GrabServer(rq.Request): + _request = rq.Struct( + rq.Opcode(36), + rq.Pad(1), + rq.RequestLength(), + ) + +class UngrabServer(rq.Request): + _request = rq.Struct( + rq.Opcode(37), + rq.Pad(1), + rq.RequestLength(), + ) + +class QueryPointer(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(38), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('same_screen'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('root'), + rq.Window('child', (X.NONE, )), + rq.Int16('root_x'), + rq.Int16('root_y'), + rq.Int16('win_x'), + rq.Int16('win_y'), + rq.Card16('mask'), + rq.Pad(6), + ) + +class GetMotionEvents(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(39), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window'), + rq.Card32('start'), + rq.Card32('stop'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('events', 4), + rq.Pad(20), + rq.List('events', structs.TimeCoord), + ) + +class TranslateCoords(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(40), + rq.Pad(1), + rq.RequestLength(), + rq.Window('src_wid'), + rq.Window('dst_wid'), + rq.Int16('src_x'), + rq.Int16('src_y'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('same_screen'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('child', (X.NONE, )), + rq.Int16('x'), + rq.Int16('y'), + rq.Pad(16), + ) + +class WarpPointer(rq.Request): + _request = rq.Struct( + rq.Opcode(41), + rq.Pad(1), + rq.RequestLength(), + rq.Window('src_window'), + rq.Window('dst_window'), + rq.Int16('src_x'), + rq.Int16('src_y'), + rq.Card16('src_width'), + rq.Card16('src_height'), + rq.Int16('dst_x'), + rq.Int16('dst_y'), + ) + +class SetInputFocus(rq.Request): + _request = rq.Struct( + rq.Opcode(42), + rq.Set('revert_to', 1, (X.RevertToNone, X.RevertToPointerRoot, + X.RevertToParent)), + rq.RequestLength(), + rq.Window('focus'), + rq.Card32('time'), + ) + +class GetInputFocus(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(43), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('revert_to'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Window('focus', (X.NONE, X.PointerRoot)), + rq.Pad(20), + ) + +class QueryKeymap(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(44), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.FixedList('map', 32, rq.Card8Obj), + ) + + +class OpenFont(rq.Request): + _request = rq.Struct( + rq.Opcode(45), + rq.Pad(1), + rq.RequestLength(), + rq.Font('fid'), + rq.LengthOf('name', 2), + rq.Pad(2), + rq.String8('name'), + ) + +class CloseFont(rq.Request): + _request = rq.Struct( + rq.Opcode(46), + rq.Pad(1), + rq.RequestLength(), + rq.Font('font') + ) + +class QueryFont(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(47), + rq.Pad(1), + rq.RequestLength(), + rq.Fontable('font') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Object('min_bounds', structs.CharInfo), + rq.Pad(4), + rq.Object('max_bounds', structs.CharInfo), + rq.Pad(4), + rq.Card16('min_char_or_byte2'), + rq.Card16('max_char_or_byte2'), + rq.Card16('default_char'), + rq.LengthOf('properties', 2), + rq.Card8('draw_direction'), + rq.Card8('min_byte1'), + rq.Card8('max_byte1'), + rq.Card8('all_chars_exist'), + rq.Int16('font_ascent'), + rq.Int16('font_descent'), + rq.LengthOf('char_infos', 4), + rq.List('properties', structs.FontProp), + rq.List('char_infos', structs.CharInfo), + ) + +class QueryTextExtents(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(48), + rq.OddLength('string'), + rq.RequestLength(), + rq.Fontable('font'), + rq.String16('string'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('draw_direction'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Int16('font_ascent'), + rq.Int16('font_descent'), + rq.Int16('overall_ascent'), + rq.Int16('overall_descent'), + rq.Int32('overall_width'), + rq.Int32('overall_left'), + rq.Int32('overall_right'), + rq.Pad(4), + ) + +class ListFonts(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(49), + rq.Pad(1), + rq.RequestLength(), + rq.Card16('max_names'), + rq.LengthOf('pattern', 2), + rq.String8('pattern'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('fonts', 2), + rq.Pad(22), + rq.List('fonts', rq.Str), + ) + + +class ListFontsWithInfo(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(50), + rq.Pad(1), + rq.RequestLength(), + rq.Card16('max_names'), + rq.LengthOf('pattern', 2), + rq.String8('pattern'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.LengthOf('name', 1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Object('min_bounds', structs.CharInfo), + rq.Pad(4), + rq.Object('max_bounds', structs.CharInfo), + rq.Pad(4), + rq.Card16('min_char_or_byte2'), + rq.Card16('max_char_or_byte2'), + rq.Card16('default_char'), + rq.LengthOf('properties', 2), + rq.Card8('draw_direction'), + rq.Card8('min_byte1'), + rq.Card8('max_byte1'), + rq.Card8('all_chars_exist'), + rq.Int16('font_ascent'), + rq.Int16('font_descent'), + rq.Card32('replies_hint'), + rq.List('properties', structs.FontProp), + rq.String8('name'), + ) + + + # Somebody must have smoked some really wicked weed when they + # defined the ListFontsWithInfo request: + # The server sends a reply for _each_ matching font... + # It then sends a special reply (name length == 0) to indicate + # that there are no more fonts in the reply. + + # This means that we have to do some special parsing to see if + # we have got the end-of-reply reply. If we haven't, we + # have to reinsert the request in the front of the + # display.sent_request queue to catch the next response. + + # Bastards. + + def __init__(self, *args, **keys): + self._fonts = [] + rq.ReplyRequest.__init__(self, *args, **keys) + + def _parse_response(self, data): + + if ord(data[1]) == 0: + self._response_lock.acquire() + self._data = self._fonts + del self._fonts + self._response_lock.release() + return + + r, d = self._reply.parse_binary(data) + self._fonts.append(r) + + self._display.sent_requests.insert(0, self) + + + # Override the default __getattr__, since it isn't usable for + # the list reply. Instead provide a __getitem__ and a __len__. + + def __getattr__(self, attr): + raise AttributeError(attr) + + def __getitem__(self, item): + return self._data[item] + + def __len__(self): + return len(self._data) + + +class SetFontPath(rq.Request): + _request = rq.Struct( + rq.Opcode(51), + rq.Pad(1), + rq.RequestLength(), + rq.LengthOf('path', 2), + rq.Pad(2), + rq.List('path', rq.Str), + ) + +class GetFontPath(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(52), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('paths', 2), + rq.Pad(22), + rq.List('paths', rq.Str), + ) + +class CreatePixmap(rq.Request): + _request = rq.Struct( + rq.Opcode(53), + rq.Card8('depth'), + rq.RequestLength(), + rq.Pixmap('pid'), + rq.Drawable('drawable'), + rq.Card16('width'), + rq.Card16('height'), + ) + +class FreePixmap(rq.Request): + _request = rq.Struct( + rq.Opcode(54), + rq.Pad(1), + rq.RequestLength(), + rq.Pixmap('pixmap') + ) + +class CreateGC(rq.Request): + _request = rq.Struct( + rq.Opcode(55), + rq.Pad(1), + rq.RequestLength(), + rq.GC('cid'), + rq.Drawable('drawable'), + structs.GCValues('attrs'), + ) + +class ChangeGC(rq.Request): + _request = rq.Struct( + rq.Opcode(56), + rq.Pad(1), + rq.RequestLength(), + rq.GC('gc'), + structs.GCValues('attrs'), + ) + +class CopyGC(rq.Request): + _request = rq.Struct( + rq.Opcode(57), + rq.Pad(1), + rq.RequestLength(), + rq.GC('src_gc'), + rq.GC('dst_gc'), + rq.Card32('mask'), + ) + +class SetDashes(rq.Request): + _request = rq.Struct( + rq.Opcode(58), + rq.Pad(1), + rq.RequestLength(), + rq.GC('gc'), + rq.Card16('dash_offset'), + rq.LengthOf('dashes', 2), + rq.List('dashes', rq.Card8Obj), + ) + +class SetClipRectangles(rq.Request): + _request = rq.Struct( + rq.Opcode(59), + rq.Set('ordering', 1, (X.Unsorted, X.YSorted, X.YXSorted, X.YXBanded)), + rq.RequestLength(), + rq.GC('gc'), + rq.Int16('x_origin'), + rq.Int16('y_origin'), + rq.List('rectangles', structs.Rectangle), + ) + +class FreeGC(rq.Request): + _request = rq.Struct( + rq.Opcode(60), + rq.Pad(1), + rq.RequestLength(), + rq.GC('gc') + ) + +class ClearArea(rq.Request): + _request = rq.Struct( + rq.Opcode(61), + rq.Bool('exposures'), + rq.RequestLength(), + rq.Window('window'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + ) + +class CopyArea(rq.Request): + _request = rq.Struct( + rq.Opcode(62), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('src_drawable'), + rq.Drawable('dst_drawable'), + rq.GC('gc'), + rq.Int16('src_x'), + rq.Int16('src_y'), + rq.Int16('dst_x'), + rq.Int16('dst_y'), + rq.Card16('width'), + rq.Card16('height'), + ) + +class CopyPlane(rq.Request): + _request = rq.Struct( + rq.Opcode(63), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('src_drawable'), + rq.Drawable('dst_drawable'), + rq.GC('gc'), + rq.Int16('src_x'), + rq.Int16('src_y'), + rq.Int16('dst_x'), + rq.Int16('dst_y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card32('bit_plane'), + ) + +class PolyPoint(rq.Request): + _request = rq.Struct( + rq.Opcode(64), + rq.Set('coord_mode', 1, (X.CoordModeOrigin, X.CoordModePrevious)), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.List('points', structs.Point), + ) + +class PolyLine(rq.Request): + _request = rq.Struct( + rq.Opcode(65), + rq.Set('coord_mode', 1, (X.CoordModeOrigin, X.CoordModePrevious)), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.List('points', structs.Point), + ) + + +class PolySegment(rq.Request): + _request = rq.Struct( + rq.Opcode(66), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.List('segments', structs.Segment), + ) + + +class PolyRectangle(rq.Request): + _request = rq.Struct( + rq.Opcode(67), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.List('rectangles', structs.Rectangle), + ) + +class PolyArc(rq.Request): + _request = rq.Struct( + rq.Opcode(68), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.List('arcs', structs.Arc), + ) + +class FillPoly(rq.Request): + _request = rq.Struct( + rq.Opcode(69), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.Set('shape', 1, (X.Complex, X.Nonconvex, X.Convex)), + rq.Set('coord_mode', 1, (X.CoordModeOrigin, X.CoordModePrevious)), + rq.Pad(2), + rq.List('points', structs.Point), + ) + +class PolyFillRectangle(rq.Request): + _request = rq.Struct( + rq.Opcode(70), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.List('rectangles', structs.Rectangle), + ) + +class PolyFillArc(rq.Request): + _request = rq.Struct( + rq.Opcode(71), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.List('arcs', structs.Arc), + ) + +class PutImage(rq.Request): + _request = rq.Struct( + rq.Opcode(72), + rq.Set('format', 1, (X.XYBitmap, X.XYPixmap, X.ZPixmap)), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.Card16('width'), + rq.Card16('height'), + rq.Int16('dst_x'), + rq.Int16('dst_y'), + rq.Card8('left_pad'), + rq.Card8('depth'), + rq.Pad(2), + rq.Binary('data'), + ) + +class GetImage(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(73), + rq.Set('format', 1, (X.XYPixmap, X.ZPixmap)), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Card32('plane_mask'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('depth'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('visual'), + rq.Pad(20), + rq.Binary('data'), + ) + +class PolyText8(rq.Request): + _request = rq.Struct( + rq.Opcode(74), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.Int16('x'), + rq.Int16('y'), + rq.TextElements8('items'), + ) + +class PolyText16(rq.Request): + _request = rq.Struct( + rq.Opcode(75), + rq.Pad(1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.Int16('x'), + rq.Int16('y'), + rq.TextElements16('items'), + ) + +class ImageText8(rq.Request): + _request = rq.Struct( + rq.Opcode(76), + rq.LengthOf('string', 1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.Int16('x'), + rq.Int16('y'), + rq.String8('string'), + ) + +class ImageText16(rq.Request): + _request = rq.Struct( + rq.Opcode(77), + rq.LengthOf('string', 1), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.GC('gc'), + rq.Int16('x'), + rq.Int16('y'), + rq.String16('string'), + ) + +class CreateColormap(rq.Request): + _request = rq.Struct( + rq.Opcode(78), + rq.Set('alloc', 1, (X.AllocNone, X.AllocAll)), + rq.RequestLength(), + rq.Colormap('mid'), + rq.Window('window'), + rq.Card32('visual'), + ) + +class FreeColormap(rq.Request): + _request = rq.Struct( + rq.Opcode(79), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap') + ) + +class CopyColormapAndFree(rq.Request): + _request = rq.Struct( + rq.Opcode(80), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('mid'), + rq.Colormap('src_cmap'), + ) + +class InstallColormap(rq.Request): + _request = rq.Struct( + rq.Opcode(81), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap') + ) + +class UninstallColormap(rq.Request): + _request = rq.Struct( + rq.Opcode(82), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap') + ) + +class ListInstalledColormaps(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(83), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('cmaps', 2), + rq.Pad(22), + rq.List('cmaps', rq.ColormapObj), + ) + +class AllocColor(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(84), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.Card16('red'), + rq.Card16('green'), + rq.Card16('blue'), + rq.Pad(2), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('red'), + rq.Card16('green'), + rq.Card16('blue'), + rq.Pad(2), + rq.Card32('pixel'), + rq.Pad(12), + ) + +class AllocNamedColor(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(85), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.LengthOf('name', 2), + rq.Pad(2), + rq.String8('name'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('pixel'), + rq.Card16('exact_red'), + rq.Card16('exact_green'), + rq.Card16('exact_blue'), + rq.Card16('screen_red'), + rq.Card16('screen_green'), + rq.Card16('screen_blue'), + rq.Pad(8), + ) + +class AllocColorCells(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(86), + rq.Bool('contiguous'), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.Card16('colors'), + rq.Card16('planes'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('pixels', 2), + rq.LengthOf('masks', 2), + rq.Pad(20), + rq.List('pixels', rq.Card32Obj), + rq.List('masks', rq.Card32Obj), + ) + +class AllocColorPlanes(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(87), + rq.Bool('contiguous'), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.Card16('colors'), + rq.Card16('red'), + rq.Card16('green'), + rq.Card16('blue'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('pixels', 2), + rq.Pad(2), + rq.Card32('red_mask'), + rq.Card32('green_mask'), + rq.Card32('blue_mask'), + rq.Pad(8), + rq.List('pixels', rq.Card32Obj), + ) + +class FreeColors(rq.Request): + _request = rq.Struct( + rq.Opcode(88), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.Card32('plane_mask'), + rq.List('pixels', rq.Card32Obj), + ) + +class StoreColors(rq.Request): + _request = rq.Struct( + rq.Opcode(89), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.List('items', structs.ColorItem), + ) + +class StoreNamedColor(rq.Request): + _request = rq.Struct( + rq.Opcode(90), + rq.Card8('flags'), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.Card32('pixel'), + rq.LengthOf('name', 2), + rq.Pad(2), + rq.String8('name'), + ) + +class QueryColors(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(91), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.List('pixels', rq.Card32Obj), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('colors', 2), + rq.Pad(22), + rq.List('colors', structs.RGB), + ) + +class LookupColor(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(92), + rq.Pad(1), + rq.RequestLength(), + rq.Colormap('cmap'), + rq.LengthOf('name', 2), + rq.Pad(2), + rq.String8('name'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('exact_red'), + rq.Card16('exact_green'), + rq.Card16('exact_blue'), + rq.Card16('screen_red'), + rq.Card16('screen_green'), + rq.Card16('screen_blue'), + rq.Pad(12), + ) + + +class CreateCursor(rq.Request): + _request = rq.Struct( + rq.Opcode(93), + rq.Pad(1), + rq.RequestLength(), + rq.Cursor('cid'), + rq.Pixmap('source'), + rq.Pixmap('mask'), + rq.Card16('fore_red'), + rq.Card16('fore_green'), + rq.Card16('fore_blue'), + rq.Card16('back_red'), + rq.Card16('back_green'), + rq.Card16('back_blue'), + rq.Card16('x'), + rq.Card16('y'), + ) + +class CreateGlyphCursor(rq.Request): + _request = rq.Struct( + rq.Opcode(94), + rq.Pad(1), + rq.RequestLength(), + rq.Cursor('cid'), + rq.Font('source'), + rq.Font('mask'), + rq.Card16('source_char'), + rq.Card16('mask_char'), + rq.Card16('fore_red'), + rq.Card16('fore_green'), + rq.Card16('fore_blue'), + rq.Card16('back_red'), + rq.Card16('back_green'), + rq.Card16('back_blue'), + ) + +class FreeCursor(rq.Request): + _request = rq.Struct( + rq.Opcode(95), + rq.Pad(1), + rq.RequestLength(), + rq.Cursor('cursor') + ) + +class RecolorCursor(rq.Request): + _request = rq.Struct( + rq.Opcode(96), + rq.Pad(1), + rq.RequestLength(), + rq.Cursor('cursor'), + rq.Card16('fore_red'), + rq.Card16('fore_green'), + rq.Card16('fore_blue'), + rq.Card16('back_red'), + rq.Card16('back_green'), + rq.Card16('back_blue'), + ) + +class QueryBestSize(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(97), + rq.Set('item_class', 1, (X.CursorShape, X.TileShape, X.StippleShape)), + rq.RequestLength(), + rq.Drawable('drawable'), + rq.Card16('width'), + rq.Card16('height'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('width'), + rq.Card16('height'), + rq.Pad(20), + ) + +class QueryExtension(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(98), + rq.Pad(1), + rq.RequestLength(), + rq.LengthOf('name', 2), + rq.Pad(2), + rq.String8('name'), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card8('present'), + rq.Card8('major_opcode'), + rq.Card8('first_event'), + rq.Card8('first_error'), + rq.Pad(20), + ) + +class ListExtensions(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(99), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.LengthOf('names', 1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + rq.List('names', rq.Str), + ) + +class ChangeKeyboardMapping(rq.Request): + _request = rq.Struct( + rq.Opcode(100), + rq.LengthOf('keysyms', 1), + rq.RequestLength(), + rq.Card8('first_keycode'), + rq.Format('keysyms', 1), + rq.Pad(2), + rq.KeyboardMapping('keysyms'), + ) + +class GetKeyboardMapping(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(101), + rq.Pad(1), + rq.RequestLength(), + rq.Card8('first_keycode'), + rq.Card8('count'), + rq.Pad(2), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Format('keysyms', 1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + rq.KeyboardMapping('keysyms'), + ) + + +class ChangeKeyboardControl(rq.Request): + _request = rq.Struct( + rq.Opcode(102), + rq.Pad(1), + rq.RequestLength(), + rq.ValueList( 'attrs', 4, 0, + rq.Int8('key_click_percent'), + rq.Int8('bell_percent'), + rq.Int16('bell_pitch'), + rq.Int16('bell_duration'), + rq.Card8('led'), + rq.Set('led_mode', 1, (X.LedModeOff, X.LedModeOn)), + rq.Card8('key'), + rq.Set('auto_repeat_mode', 1, (X.AutoRepeatModeOff, + X.AutoRepeatModeOn, + X.AutoRepeatModeDefault)) + ) + ) + +class GetKeyboardControl(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(103), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('global_auto_repeat'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card32('led_mask'), + rq.Card8('key_click_percent'), + rq.Card8('bell_percent'), + rq.Card16('bell_pitch'), + rq.Card16('bell_duration'), + rq.Pad(2), + rq.FixedList('auto_repeats', 32, rq.Card8Obj), + ) + +class Bell(rq.Request): + _request = rq.Struct( + rq.Opcode(104), + rq.Int8('percent'), + rq.RequestLength(), + ) + +class ChangePointerControl(rq.Request): + _request = rq.Struct( + rq.Opcode(105), + rq.Pad(1), + rq.RequestLength(), + rq.Int16('accel_num'), + rq.Int16('accel_denum'), + rq.Int16('threshold'), + rq.Bool('do_accel'), + rq.Bool('do_thresh'), + ) + +class GetPointerControl(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(106), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('accel_num'), + rq.Card16('accel_denom'), + rq.Card16('threshold'), + rq.Pad(18), + ) + +class SetScreenSaver(rq.Request): + _request = rq.Struct( + rq.Opcode(107), + rq.Pad(1), + rq.RequestLength(), + rq.Int16('timeout'), + rq.Int16('interval'), + rq.Set('prefer_blank', 1, (X.DontPreferBlanking, + X.PreferBlanking, + X.DefaultBlanking)), + rq.Set('allow_exposures', 1, (X.DontAllowExposures, + X.AllowExposures, + X.DefaultExposures)), + rq.Pad(2), + ) + +class GetScreenSaver(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(108), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Pad(1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Card16('timeout'), + rq.Card16('interval'), + rq.Card8('prefer_blanking'), + rq.Card8('allow_exposures'), + rq.Pad(18), + ) + +class ChangeHosts(rq.Request): + _request = rq.Struct( + rq.Opcode(109), + rq.Set('mode', 1, (X.HostInsert, X.HostDelete)), + rq.RequestLength(), + rq.Set('host_family', 1, (X.FamilyInternet, X.FamilyDECnet, X.FamilyChaos, + X.FamilyServerInterpreted, X.FamilyInternetV6)), + rq.Pad(1), + rq.LengthOf('host', 2), + rq.List('host', rq.Card8Obj) + ) + +class ListHosts(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(110), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('mode'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.LengthOf('hosts', 2), + rq.Pad(22), + rq.List('hosts', structs.Host), + ) + +class SetAccessControl(rq.Request): + _request = rq.Struct( + rq.Opcode(111), + rq.Set('mode', 1, (X.DisableAccess, X.EnableAccess)), + rq.RequestLength(), + ) + +class SetCloseDownMode(rq.Request): + _request = rq.Struct( + rq.Opcode(112), + rq.Set('mode', 1, (X.DestroyAll, X.RetainPermanent, X.RetainTemporary)), + rq.RequestLength(), + ) + +class KillClient(rq.Request): + _request = rq.Struct( + rq.Opcode(113), + rq.Pad(1), + rq.RequestLength(), + rq.Resource('resource') + ) + +class RotateProperties(rq.Request): + _request = rq.Struct( + rq.Opcode(114), + rq.Pad(1), + rq.RequestLength(), + rq.Window('window'), + rq.LengthOf('properties', 2), + rq.Int16('delta'), + rq.List('properties', rq.Card32Obj), + ) + +class ForceScreenSaver(rq.Request): + _request = rq.Struct( + rq.Opcode(115), + rq.Set('mode', 1, (X.ScreenSaverReset, X.ScreenSaverActive)), + rq.RequestLength(), + ) + +class SetPointerMapping(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(116), + rq.LengthOf('map', 1), + rq.RequestLength(), + rq.List('map', rq.Card8Obj), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + ) + +class GetPointerMapping(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(117), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.LengthOf('map', 1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + rq.List('map', rq.Card8Obj), + ) + +class SetModifierMapping(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(118), + rq.Format('keycodes', 1), + rq.RequestLength(), + rq.ModifierMapping('keycodes') + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Card8('status'), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + ) + +class GetModifierMapping(rq.ReplyRequest): + _request = rq.Struct( + rq.Opcode(119), + rq.Pad(1), + rq.RequestLength(), + ) + + _reply = rq.Struct( + rq.ReplyCode(), + rq.Format('keycodes', 1), + rq.Card16('sequence_number'), + rq.ReplyLength(), + rq.Pad(24), + rq.ModifierMapping('keycodes') + ) + +class NoOperation(rq.Request): + _request = rq.Struct( + rq.Opcode(127), + rq.Pad(1), + rq.RequestLength(), + ) + + +major_codes = { + 1: CreateWindow, + 2: ChangeWindowAttributes, + 3: GetWindowAttributes, + 4: DestroyWindow, + 5: DestroySubWindows, + 6: ChangeSaveSet, + 7: ReparentWindow, + 8: MapWindow, + 9: MapSubwindows, + 10: UnmapWindow, + 11: UnmapSubwindows, + 12: ConfigureWindow, + 13: CirculateWindow, + 14: GetGeometry, + 15: QueryTree, + 16: InternAtom, + 17: GetAtomName, + 18: ChangeProperty, + 19: DeleteProperty, + 20: GetProperty, + 21: ListProperties, + 22: SetSelectionOwner, + 23: GetSelectionOwner, + 24: ConvertSelection, + 25: SendEvent, + 26: GrabPointer, + 27: UngrabPointer, + 28: GrabButton, + 29: UngrabButton, + 30: ChangeActivePointerGrab, + 31: GrabKeyboard, + 32: UngrabKeyboard, + 33: GrabKey, + 34: UngrabKey, + 35: AllowEvents, + 36: GrabServer, + 37: UngrabServer, + 38: QueryPointer, + 39: GetMotionEvents, + 40: TranslateCoords, + 41: WarpPointer, + 42: SetInputFocus, + 43: GetInputFocus, + 44: QueryKeymap, + 45: OpenFont, + 46: CloseFont, + 47: QueryFont, + 48: QueryTextExtents, + 49: ListFonts, + 50: ListFontsWithInfo, + 51: SetFontPath, + 52: GetFontPath, + 53: CreatePixmap, + 54: FreePixmap, + 55: CreateGC, + 56: ChangeGC, + 57: CopyGC, + 58: SetDashes, + 59: SetClipRectangles, + 60: FreeGC, + 61: ClearArea, + 62: CopyArea, + 63: CopyPlane, + 64: PolyPoint, + 65: PolyLine, + 66: PolySegment, + 67: PolyRectangle, + 68: PolyArc, + 69: FillPoly, + 70: PolyFillRectangle, + 71: PolyFillArc, + 72: PutImage, + 73: GetImage, + 74: PolyText8, + 75: PolyText16, + 76: ImageText8, + 77: ImageText16, + 78: CreateColormap, + 79: FreeColormap, + 80: CopyColormapAndFree, + 81: InstallColormap, + 82: UninstallColormap, + 83: ListInstalledColormaps, + 84: AllocColor, + 85: AllocNamedColor, + 86: AllocColorCells, + 87: AllocColorPlanes, + 88: FreeColors, + 89: StoreColors, + 90: StoreNamedColor, + 91: QueryColors, + 92: LookupColor, + 93: CreateCursor, + 94: CreateGlyphCursor, + 95: FreeCursor, + 96: RecolorCursor, + 97: QueryBestSize, + 98: QueryExtension, + 99: ListExtensions, + 100: ChangeKeyboardMapping, + 101: GetKeyboardMapping, + 102: ChangeKeyboardControl, + 103: GetKeyboardControl, + 104: Bell, + 105: ChangePointerControl, + 106: GetPointerControl, + 107: SetScreenSaver, + 108: GetScreenSaver, + 109: ChangeHosts, + 110: ListHosts, + 111: SetAccessControl, + 112: SetCloseDownMode, + 113: KillClient, + 114: RotateProperties, + 115: ForceScreenSaver, + 116: SetPointerMapping, + 117: GetPointerMapping, + 118: SetModifierMapping, + 119: GetModifierMapping, + 127: NoOperation, + } diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/rq.py b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/rq.py new file mode 100644 index 0000000..c54804e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/rq.py @@ -0,0 +1,1463 @@ +# Xlib.protocol.rq -- structure primitives for request, events and errors +# +# Copyright (C) 2000-2002 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +# Standard modules +import sys +import traceback +import struct +from array import array + +# Python 2/3 compatibility. +from six import PY3, binary_type, byte2int, indexbytes, iterbytes + +# Xlib modules +from .. import X +from ..support import lock + + +def decode_string(bs): + return bs.decode('latin1') + +if PY3: + def encode_array(a): + return a.tobytes() +else: + def encode_array(a): + return a.tostring() + + +class BadDataError(Exception): pass + +# These are struct codes, we know their byte sizes + +signed_codes = { 1: 'b', 2: 'h', 4: 'l' } +unsigned_codes = { 1: 'B', 2: 'H', 4: 'L' } + + +# Unfortunately, we don't know the array sizes of B, H and L, since +# these use the underlying architecture's size for a char, short and +# long. Therefore we probe for their sizes, and additionally create +# a mapping that translates from struct codes to array codes. +# +# Bleah. + +array_unsigned_codes = { } +struct_to_array_codes = { } + +for c in 'bhil': + size = array(c).itemsize + array_unsigned_codes[size] = c.upper() + try: + struct_to_array_codes[signed_codes[size]] = c + struct_to_array_codes[unsigned_codes[size]] = c.upper() + except KeyError: + pass + +# print array_unsigned_codes, struct_to_array_codes + + +class Field(object): + """Field objects represent the data fields of a Struct. + + Field objects must have the following attributes: + + name -- the field name, or None + structcode -- the struct codes representing this field + structvalues -- the number of values encodes by structcode + + Additionally, these attributes should either be None or real methods: + + check_value -- check a value before it is converted to binary + parse_value -- parse a value after it has been converted from binary + + If one of these attributes are None, no check or additional + parsings will be done one values when converting to or from binary + form. Otherwise, the methods should have the following behaviour: + + newval = check_value(val) + Check that VAL is legal when converting to binary form. The + value can also be converted to another Python value. In any + case, return the possibly new value. NEWVAL should be a + single Python value if structvalues is 1, a tuple of + structvalues elements otherwise. + + newval = parse_value(val, display) + VAL is an unpacked Python value, which now can be further + refined. DISPLAY is the current Display object. Return the + new value. VAL will be a single value if structvalues is 1, + a tuple of structvalues elements otherwise. + + If `structcode' is None the Field must have the method + f.parse_binary_value() instead. See its documentation string for + details. + """ + name = None + default = None + + structcode = None + structvalues = 0 + + check_value = None + parse_value = None + + keyword_args = False + + def __init__(self): + pass + + def parse_binary_value(self, data, display, length, format): + """value, remaindata = f.parse_binary_value(data, display, length, format) + + Decode a value for this field from the binary string DATA. + If there are a LengthField and/or a FormatField connected to this + field, their values will be LENGTH and FORMAT, respectively. If + there are no such fields the parameters will be None. + + DISPLAY is the display involved, which is really only used by + the Resource fields. + + The decoded value is returned as VALUE, and the remaining part + of DATA shold be returned as REMAINDATA. + """ + raise RuntimeError('Neither structcode or parse_binary_value ' \ + 'provided for {0}'.format(self)) + + +class Pad(Field): + def __init__(self, size): + self.size = size + self.value = b'\0' * size + self.structcode = '{0}x'.format(size) + self.structvalues = 0 + + +class ConstantField(Field): + def __init__(self, value): + self.value = value + + +class Opcode(ConstantField): + structcode = 'B' + structvalues = 1 + +class ReplyCode(ConstantField): + structcode = 'B' + structvalues = 1 + + def __init__(self): + self.value = 1 + +class LengthField(Field): + """A LengthField stores the length of some other Field whose size + may vary, e.g. List and String8. + + Its name should be the same as the name of the field whose size + it stores. The other_fields attribute can be used to specify the + names of other fields whose sizes are stored by this field, so + a single length field can set the length of multiple fields. + + The lf.get_binary_value() method of LengthFields is not used, instead + a lf.get_binary_length() should be provided. + + Unless LengthField.get_binary_length() is overridden in child classes, + there should also be a lf.calc_length(). + """ + structcode = 'L' + structvalues = 1 + other_fields = None + + def calc_length(self, length): + """newlen = lf.calc_length(length) + + Return a new length NEWLEN based on the provided LENGTH. + """ + + return length + + +class TotalLengthField(LengthField): + pass + +class RequestLength(TotalLengthField): + structcode = 'H' + structvalues = 1 + + def calc_length(self, length): + return length // 4 + +class ReplyLength(TotalLengthField): + structcode = 'L' + structvalues = 1 + + def calc_length(self, length): + return (length - 32) // 4 + + +class LengthOf(LengthField): + def __init__(self, name, size): + if isinstance(name, (list, tuple)): + self.name = name[0] + self.other_fields = name[1:] + else: + self.name = name + self.structcode = unsigned_codes[size] + + +class OddLength(LengthField): + structcode = 'B' + structvalues = 1 + + def __init__(self, name): + self.name = name + + def calc_length(self, length): + return length % 2 + + def parse_value(self, value, display): + if value == 0: + return 'even' + else: + return 'odd' + + +class FormatField(Field): + """A FormatField encodes the format of some other field, in a manner + similar to LengthFields. + + The ff.get_binary_value() method is not used, replaced by + ff.get_binary_format(). + """ + + structvalues = 1 + + def __init__(self, name, size): + self.name = name + self.structcode = unsigned_codes[size] + +Format = FormatField + + +class ValueField(Field): + def __init__(self, name, default = None): + self.name = name + self.default = default + + +class Int8(ValueField): + structcode = 'b' + structvalues = 1 + +class Int16(ValueField): + structcode = 'h' + structvalues = 1 + +class Int32(ValueField): + structcode = 'l' + structvalues = 1 + +class Card8(ValueField): + structcode = 'B' + structvalues = 1 + +class Card16(ValueField): + structcode = 'H' + structvalues = 1 + +class Card32(ValueField): + structcode = 'L' + structvalues = 1 + + +class Resource(Card32): + cast_function = '__resource__' + class_name = 'resource' + + def __init__(self, name, codes = (), default = None): + Card32.__init__(self, name, default) + self.codes = codes + + def check_value(self, value): + if hasattr(value, self.cast_function): + return getattr(value, self.cast_function)() + else: + return value + + def parse_value(self, value, display): + # if not display: + # return value + if value in self.codes: + return value + + c = display.get_resource_class(self.class_name) + if c: + return c(display, value) + else: + return value + +class Window(Resource): + cast_function = '__window__' + class_name = 'window' + +class Pixmap(Resource): + cast_function = '__pixmap__' + class_name = 'pixmap' + +class Drawable(Resource): + cast_function = '__drawable__' + class_name = 'drawable' + +class Fontable(Resource): + cast_function = '__fontable__' + class_name = 'fontable' + +class Font(Resource): + cast_function = '__font__' + class_name = 'font' + +class GC(Resource): + cast_function = '__gc__' + class_name = 'gc' + +class Colormap(Resource): + cast_function = '__colormap__' + class_name = 'colormap' + +class Cursor(Resource): + cast_function = '__cursor__' + class_name = 'cursor' + + +class Bool(ValueField): + structvalues = 1 + structcode = 'B' + + def check_value(self, value): + return not not value + +class Set(ValueField): + structvalues = 1 + + def __init__(self, name, size, values, default = None): + ValueField.__init__(self, name, default) + self.structcode = unsigned_codes[size] + self.values = values + + def check_value(self, val): + if val not in self.values: + raise ValueError('field %s: argument %s not in %s' + % (self.name, val, self.values)) + + return val + +class Gravity(Set): + def __init__(self, name): + Set.__init__(self, name, 1, (X.ForgetGravity, X.StaticGravity, + X.NorthWestGravity, X.NorthGravity, + X.NorthEastGravity, X.WestGravity, + X.CenterGravity, X.EastGravity, + X.SouthWestGravity, X.SouthGravity, + X.SouthEastGravity)) + + +class FixedBinary(ValueField): + structvalues = 1 + + def __init__(self, name, size): + ValueField.__init__(self, name) + self.structcode = '{0}s'.format(size) + + +class Binary(ValueField): + structcode = None + + def __init__(self, name, pad = 1): + ValueField.__init__(self, name) + self.pad = pad + + def pack_value(self, val): + val_bytes = val + slen = len(val_bytes) + + if self.pad: + return val_bytes + b'\0' * ((4 - slen % 4) % 4), slen, None + else: + return val_bytes, slen, None + + def parse_binary_value(self, data, display, length, format): + if length is None: + return data, b'' + + if self.pad: + slen = length + ((4 - length % 4) % 4) + else: + slen = length + + return data[:length], data[slen:] + + +class String8(ValueField): + structcode = None + + def __init__(self, name, pad = 1): + ValueField.__init__(self, name) + self.pad = pad + + def pack_value(self, val): + if isinstance(val, bytes): + val_bytes = val + else: + val_bytes = val.encode() + slen = len(val_bytes) + + if self.pad: + return val_bytes + b'\0' * ((4 - slen % 4) % 4), slen, None + else: + return val_bytes, slen, None + + def parse_binary_value(self, data, display, length, format): + if length is None: + return decode_string(data), b'' + + if self.pad: + slen = length + ((4 - length % 4) % 4) + else: + slen = length + + data_str = decode_string(data[:length]) + + return data_str, data[slen:] + + +class String16(ValueField): + structcode = None + + def __init__(self, name, pad = 1): + ValueField.__init__(self, name) + self.pad = pad + + def pack_value(self, val): + """Convert 8-byte string into 16-byte list""" + if isinstance(val, bytes): + val = list(iterbytes(val)) + + slen = len(val) + + if self.pad: + pad = b'\0\0' * (slen % 2) + else: + pad = b'' + + return struct.pack('>' + 'H' * slen, *val) + pad, slen, None + + def parse_binary_value(self, data, display, length, format): + if length == 'odd': + length = len(data) // 2 - 1 + elif length == 'even': + length = len(data) // 2 + + if self.pad: + slen = length + (length % 2) + else: + slen = length + + return struct.unpack('>' + 'H' * length, data[:length * 2]), data[slen * 2:] + + + +class List(ValueField): + """The List, FixedList and Object fields store compound data objects. + The type of data objects must be provided as an object with the + following attributes and methods: + + ... + + """ + + structcode = None + + def __init__(self, name, type, pad = 1): + ValueField.__init__(self, name) + self.type = type + self.pad = pad + + def parse_binary_value(self, data, display, length, format): + if length is None: + ret = [] + if self.type.structcode is None: + while data: + val, data = self.type.parse_binary(data, display) + ret.append(val) + else: + scode = '=' + self.type.structcode + slen = struct.calcsize(scode) + pos = 0 + while pos + slen <= len(data): + v = struct.unpack(scode, data[pos: pos + slen]) + + if self.type.structvalues == 1: + v = v[0] + + if self.type.parse_value is None: + ret.append(v) + else: + ret.append(self.type.parse_value(v, display)) + + pos = pos + slen + + data = data[pos:] + + else: + ret = [None] * int(length) + + if self.type.structcode is None: + for i in range(0, length): + ret[i], data = self.type.parse_binary(data, display) + else: + scode = '=' + self.type.structcode + slen = struct.calcsize(scode) + pos = 0 + for i in range(0, length): + v = struct.unpack(scode, data[pos: pos + slen]) + + if self.type.structvalues == 1: + v = v[0] + + if self.type.parse_value is None: + ret[i] = v + else: + ret[i] = self.type.parse_value(v, display) + + pos = pos + slen + + data = data[pos:] + + if self.pad: + data = data[len(data) % 4:] + + return ret, data + + def pack_value(self, val): + # Single-char values, we'll assume that means integer lists. + if self.type.structcode and len(self.type.structcode) == 1: + if self.type.check_value is not None: + val = [self.type.check_value(v) for v in val] + a = array(struct_to_array_codes[self.type.structcode], val) + data = encode_array(a) + else: + data = [] + for v in val: + data.append(self.type.pack_value(v)) + + data = b''.join(data) + + if self.pad: + dlen = len(data) + data = data + b'\0' * ((4 - dlen % 4) % 4) + + return data, len(val), None + + +class FixedList(List): + def __init__(self, name, size, type, pad = 1): + List.__init__(self, name, type, pad) + self.size = size + + def parse_binary_value(self, data, display, length, format): + return List.parse_binary_value(self, data, display, self.size, format) + + def pack_value(self, val): + if len(val) != self.size: + raise BadDataError('length mismatch for FixedList %s' % self.name) + return List.pack_value(self, val) + + +class Object(ValueField): + def __init__(self, name, type, default = None): + ValueField.__init__(self, name, default) + self.type = type + self.structcode = self.type.structcode + self.structvalues = self.type.structvalues + + def parse_binary_value(self, data, display, length, format): + return self.type.parse_binary(data, display) + + def parse_value(self, val, display): + return self.type.parse_value(val, display) + + def pack_value(self, val): + return self.type.pack_value(val) + + def check_value(self, val): + if isinstance(val, tuple): + vals = [] + i = 0 + for f in self.type.fields: + if f.name: + if f.check_value is None: + v = val[i] + else: + v = f.check_value(val[i]) + if f.structvalues == 1: + vals.append(v) + else: + vals.extend(v) + i = i + 1 + return vals + + if isinstance(val, dict): + data = val + elif isinstance(val, DictWrapper): + data = val._data + else: + raise TypeError('Object value must be tuple, dictionary or DictWrapper: %s' % val) + + vals = [] + for f in self.type.fields: + if f.name: + if f.check_value is None: + v = data[f.name] + else: + v = f.check_value(data[f.name]) + if f.structvalues == 1: + vals.append(v) + else: + vals.extend(v) + + return vals + + +class PropertyData(ValueField): + structcode = None + + def parse_binary_value(self, data, display, length, format): + if length is None: + length = len(data) // (format // 8) + else: + length = int(length) + + if format == 0: + ret = None + + elif format == 8: + ret = (8, data[:length]) + data = data[length + ((4 - length % 4) % 4):] + + elif format == 16: + ret = (16, array(array_unsigned_codes[2], data[:2 * length])) + data = data[2 * (length + length % 2):] + + elif format == 32: + ret = (32, array(array_unsigned_codes[4], data[:4 * length])) + data = data[4 * length:] + + return ret, data + + def pack_value(self, value): + fmt, val = value + + if fmt not in (8, 16, 32): + raise BadDataError('Invalid property data format {0}'.format(fmt)) + + if isinstance(val, binary_type): + size = fmt // 8 + vlen = len(val) + if vlen % size: + vlen = vlen - vlen % size + data = val[:vlen] + else: + data = val + + dlen = vlen // size + + else: + if isinstance(val, tuple): + val = list(val) + + size = fmt // 8 + a = array(array_unsigned_codes[size], val) + data = encode_array(a) + dlen = len(val) + + dl = len(data) + data = data + b'\0' * ((4 - dl % 4) % 4) + + return data, dlen, fmt + + +class FixedPropertyData(PropertyData): + def __init__(self, name, size): + PropertyData.__init__(self, name) + self.size = size + + def parse_binary_value(self, data, display, length, format): + return PropertyData.parse_binary_value(self, data, display, + self.size // (format // 8), format) + + def pack_value(self, value): + data, dlen, fmt = PropertyData.pack_value(self, value) + + if len(data) != self.size: + raise BadDataError('Wrong data length for FixedPropertyData: %s' + % (value, )) + + return data, dlen, fmt + + +class ValueList(Field): + structcode = None + keyword_args = True + default = 'usekeywords' + + def __init__(self, name, mask, pad, *fields): + self.name = name + self.maskcode = '={0}{1}x'.format(unsigned_codes[mask], pad).encode() + self.maskcodelen = struct.calcsize(self.maskcode) + self.fields = [] + + flag = 1 + for f in fields: + if f.name: + self.fields.append((f, flag)) + flag = flag << 1 + + def pack_value(self, arg, keys): + mask = 0 + data = b'' + + if arg == self.default: + arg = keys + + for field, flag in self.fields: + if field.name in arg: + mask = mask | flag + + val = arg[field.name] + if field.check_value is not None: + val = field.check_value(val) + + d = struct.pack('=' + field.structcode, val) + data = data + d + b'\0' * (4 - len(d)) + + return struct.pack(self.maskcode, mask) + data, None, None + + def parse_binary_value(self, data, display, length, format): + r = {} + + mask = int(struct.unpack(self.maskcode, data[:self.maskcodelen])[0]) + data = data[self.maskcodelen:] + + for field, flag in self.fields: + if mask & flag: + if field.structcode: + vals = struct.unpack('=' + field.structcode, + data[:struct.calcsize('=' + field.structcode)]) + if field.structvalues == 1: + vals = vals[0] + + if field.parse_value is not None: + vals = field.parse_value(vals, display) + + else: + vals, d = field.parse_binary_value(data[:4], display, None, None) + + r[field.name] = vals + data = data[4:] + + return DictWrapper(r), data + + +class KeyboardMapping(ValueField): + structcode = None + + def parse_binary_value(self, data, display, length, format): + if length is None: + dlen = len(data) + else: + dlen = 4 * length * format + + a = array(array_unsigned_codes[4], bytes(data[:dlen])) + + ret = [] + for i in range(0, len(a), format): + ret.append(a[i : i + format]) + + return ret, data[dlen:] + + def pack_value(self, value): + keycodes = 0 + for v in value: + keycodes = max(keycodes, len(v)) + + a = array(array_unsigned_codes[4]) + + for v in value: + for k in v: + a.append(k) + for i in range(len(v), keycodes): + a.append(X.NoSymbol) + + return encode_array(a), len(value), keycodes + + +class ModifierMapping(ValueField): + structcode = None + + def parse_binary_value(self, data, display, length, format): + a = array(array_unsigned_codes[1], data[:8 * format]) + + ret = [] + for i in range(0, 8): + ret.append(a[i * format : (i + 1) * format]) + + return ret, data[8 * format:] + + def pack_value(self, value): + if len(value) != 8: + raise BadDataError('ModifierMapping list should have eight elements') + + keycodes = 0 + for v in value: + keycodes = max(keycodes, len(v)) + + a = array(array_unsigned_codes[1]) + + for v in value: + for k in v: + a.append(k) + for i in range(len(v), keycodes): + a.append(0) + + return encode_array(a), len(value), keycodes + +class EventField(ValueField): + structcode = None + + def pack_value(self, value): + if not isinstance(value, Event): + raise BadDataError('%s is not an Event for field %s' % (value, self.name)) + + return value._binary, None, None + + def parse_binary_value(self, data, display, length, format): + from . import event + + estruct = display.event_classes.get(byte2int(data) & 0x7f, event.AnyEvent) + if type(estruct) == dict: + # this etype refers to a set of sub-events with individual subcodes + estruct = estruct[indexbytes(data, 1)] + + return estruct(display = display, binarydata = data[:32]), data[32:] + + +# +# Objects usable for List and FixedList fields. +# Struct is also usable. +# + +class ScalarObj(object): + def __init__(self, code): + self.structcode = code + self.structvalues = 1 + self.parse_value = None + self.check_value = None + +Card8Obj = ScalarObj('B') +Card16Obj = ScalarObj('H') +Card32Obj = ScalarObj('L') + +class ResourceObj(object): + structcode = 'L' + structvalues = 1 + + def __init__(self, class_name): + self.class_name = class_name + self.check_value = None + + def parse_value(self, value, display): + # if not display: + # return value + c = display.get_resource_class(self.class_name) + if c: + return c(display, value) + else: + return value + +WindowObj = ResourceObj('window') +ColormapObj = ResourceObj('colormap') + +class StrClass(object): + structcode = None + + def pack_value(self, val): + return (chr(len(val)) + val).encode() + + def parse_binary(self, data, display): + slen = byte2int(data) + 1 + return decode_string(data[1:slen]), data[slen:] + +Str = StrClass() + + +class Struct(object): + + """Struct objects represents a binary data structure. It can + contain both fields with static and dynamic sizes. However, all + static fields must appear before all dynamic fields. + + Fields are represented by various subclasses of the abstract base + class Field. The fields of a structure are given as arguments + when instantiating a Struct object. + + Struct objects have two public methods: + + to_binary() -- build a binary representation of the structure + with the values given as arguments + parse_binary() -- convert a binary (string) representation into + a Python dictionary or object. + + These functions will be generated dynamically for each Struct + object to make conversion as fast as possible. They are + generated the first time the methods are called. + """ + + def __init__(self, *fields): + self.fields = fields + + # Structures for to_binary, parse_value and parse_binary + self.static_codes = '=' + self.static_values = 0 + self.static_fields = [] + self.static_size = None + self.var_fields = [] + + for f in self.fields: + # Append structcode if there is one and we haven't + # got any varsize fields yet. + if f.structcode is not None: + assert not self.var_fields + + self.static_codes = self.static_codes + f.structcode + + # Only store fields with values + if f.structvalues > 0: + self.static_fields.append(f) + self.static_values = self.static_values + f.structvalues + + # If we have got one varsize field, all the rest must + # also be varsize fields. + else: + self.var_fields.append(f) + + self.static_size = struct.calcsize(self.static_codes) + if self.var_fields: + self.structcode = None + self.structvalues = 0 + else: + self.structcode = self.static_codes[1:] + self.structvalues = self.static_values + + + # These functions get called only once, as they will override + # themselves with dynamically created functions in the Struct + # object + + def to_binary(self, *varargs, **keys): + """data = s.to_binary(...) + + Convert Python values into the binary representation. The + arguments will be all value fields with names, in the order + given when the Struct object was instantiated. With one + exception: fields with default arguments will be last. + + Returns the binary representation as the string DATA. + """ + # Emulate Python function argument handling with our field names + names = [f.name for f in self.fields \ + if isinstance(f, ValueField) and f.name] + field_args = dict(zip(names, varargs)) + if set(field_args).intersection(keys): + dupes = ", ".join(set(field_args).intersection(keys)) + raise TypeError("{0} arguments were passed both positionally and by keyword".format(dupes)) + field_args.update(keys) + for f in self.fields: + if f.name and (f.name not in field_args): + if f.default is None: + raise TypeError("Missing required argument {0}".format(f.name)) + field_args[f.name] = f.default + # /argument handling + + # First pack all varfields so their lengths and formats are + # available when we pack their static LengthFields and + # FormatFields + + total_length = self.static_size + var_vals = {} + lengths = {} + formats = {} + + for f in self.var_fields: + if f.keyword_args: + v, l, fm = f.pack_value(field_args[f.name], keys) + else: + v, l, fm = f.pack_value(field_args[f.name]) + var_vals[f.name] = v + lengths[f.name] = l + formats[f.name] = fm + + total_length += len(v) + + + # Construct item list for struct.pack call, packing all static fields. + pack_items = [] + + for f in self.static_fields: + if isinstance(f, LengthField): + + # If this is a total length field, insert + # the calculated field value here + if isinstance(f, TotalLengthField): + pack_items.append(f.calc_length(total_length)) + else: + pack_items.append(f.calc_length(lengths[f.name])) + + # Format field, just insert the value we got previously + elif isinstance(f, FormatField): + pack_items.append(formats[f.name]) + + # A constant field, insert its value directly + elif isinstance(f, ConstantField): + pack_items.append(f.value) + + # Value fields + else: + if f.structvalues == 1: + # If there's a value check/convert function, call it + if f.check_value is not None: + pack_items.append(f.check_value(field_args[f.name])) + # Else just use the argument as provided + else: + pack_items.append(field_args[f.name]) + + # Multivalue field. Handled like single valuefield, + # but the value are tuple unpacked into separate arguments + # which are appended to pack_items + else: + if f.check_value is not None: + pack_items.extend(f.check_value(field_args[f.name])) + else: + pack_items.extend(field_args[f.name]) + + static_part = struct.pack(self.static_codes, *pack_items) + var_parts = [var_vals[f.name] for f in self.var_fields] + return static_part + b''.join(var_parts) + + + def pack_value(self, value): + + """ This function allows Struct objects to be used in List and + Object fields. Each item represents the arguments to pass to + to_binary, either a tuple, a dictionary or a DictWrapper. + + """ + + if type(value) is tuple: + return self.to_binary(*value) + elif isinstance(value, dict): + return self.to_binary(**value) + elif isinstance(value, DictWrapper): + return self.to_binary(**value._data) + else: + raise BadDataError('%s is not a tuple or a list' % (value)) + + + def parse_value(self, val, display, rawdict = False): + + """This function is used by List and Object fields to convert + Struct objects with no var_fields into Python values. + + """ + ret = {} + vno = 0 + for f in self.static_fields: + # Fields without names should be ignored, and there should + # not be any length or format fields if this function + # ever gets called. (If there were such fields, there should + # be a matching field in var_fields and then parse_binary + # would have been called instead. + + if not f.name: + pass + + elif isinstance(f, LengthField): + pass + + elif isinstance(f, FormatField): + pass + + # Value fields + else: + # If this field has a parse_value method, call it, otherwise + # use the unpacked value as is. + if f.structvalues == 1: + field_val = val[vno] + else: + field_val = val[vno:vno+f.structvalues] + + if f.parse_value is not None: + field_val = f.parse_value(field_val, display, rawdict=rawdict) + ret[f.name] = field_val + + vno = vno + f.structvalues + + if not rawdict: + return DictWrapper(ret) + return ret + + def parse_binary(self, data, display, rawdict = False): + + """values, remdata = s.parse_binary(data, display, rawdict = False) + + Convert a binary representation of the structure into Python values. + + DATA is a string or a buffer containing the binary data. + DISPLAY should be a Xlib.protocol.display.Display object if + there are any Resource fields or Lists with ResourceObjs. + + The Python values are returned as VALUES. If RAWDICT is true, + a Python dictionary is returned, where the keys are field + names and the values are the corresponding Python value. If + RAWDICT is false, a DictWrapper will be returned where all + fields are available as attributes. + + REMDATA are the remaining binary data, unused by the Struct object. + + """ + ret = {} + val = struct.unpack(self.static_codes, data[:self.static_size]) + lengths = {} + formats = {} + + vno = 0 + for f in self.static_fields: + + # Fields without name should be ignored. This is typically + # pad and constant fields + + if not f.name: + pass + + # Store index in val for Length and Format fields, to be used + # when treating varfields. + + elif isinstance(f, LengthField): + f_names = [f.name] + if f.other_fields: + f_names.extend(f.other_fields) + field_val = val[vno] + if f.parse_value is not None: + field_val = f.parse_value(field_val, display) + for f_name in f_names: + lengths[f_name] = field_val + + elif isinstance(f, FormatField): + formats[f.name] = val[vno] + + # Treat value fields the same was as in parse_value. + else: + if f.structvalues == 1: + field_val = val[vno] + else: + field_val = val[vno:vno+f.structvalues] + + if f.parse_value is not None: + field_val = f.parse_value(field_val, display) + ret[f.name] = field_val + + vno = vno + f.structvalues + + data = data[self.static_size:] + + # Call parse_binary_value for each var_field, passing the + # length and format values from the unpacked val. + + for f in self.var_fields: + ret[f.name], data = f.parse_binary_value(data, display, + lengths.get(f.name), + formats.get(f.name), + ) + + if not rawdict: + ret = DictWrapper(ret) + return ret, data + + +class TextElements8(ValueField): + string_textitem = Struct( LengthOf('string', 1), + Int8('delta'), + String8('string', pad = 0) ) + + def pack_value(self, value): + data = b'' + args = {} + + for v in value: + # Let values be simple strings, meaning a delta of 0 + if type(v) in (str, bytes): + v = (0, v) + + # A tuple, it should be (delta, string) + # Encode it as one or more textitems + + if isinstance(v, (tuple, dict, DictWrapper)): + + if isinstance(v, tuple): + delta, m_str = v + else: + delta = v['delta'] + m_str = v['string'] + + while delta or m_str: + args['delta'] = delta + args['string'] = m_str[:254] + + data = data + self.string_textitem.to_binary(*(), **args) + + delta = 0 + m_str = m_str[254:] + + # Else an integer, i.e. a font change + else: + # Use fontable cast function if instance + if isinstance(v, Fontable): + v = v.__fontable__() + + data = data + struct.pack('>BL', 255, v) + + # Pad out to four byte length + dlen = len(data) + return data + b'\0' * ((4 - dlen % 4) % 4), None, None + + def parse_binary_value(self, data, display, length, format): + values = [] + while 1: + if len(data) < 2: + break + + # font change + if byte2int(data) == 255: + values.append(struct.unpack('>L', bytes(data[1:5]))[0]) + data = data[5:] + + # skip null strings + elif byte2int(data) == 0 and indexbytes(data, 1) == 0: + data = data[2:] + + # string with delta + else: + v, data = self.string_textitem.parse_binary(data, display) + values.append(v) + + return values, '' + + + +class TextElements16(TextElements8): + string_textitem = Struct( LengthOf('string', 1), + Int8('delta'), + String16('string', pad = 0) ) + + + +class GetAttrData(object): + def __getattr__(self, attr): + try: + if self._data: + return self._data[attr] + else: + raise AttributeError(attr) + except KeyError: + raise AttributeError(attr) + +class DictWrapper(GetAttrData): + def __init__(self, dict): + self.__dict__['_data'] = dict + + def __getitem__(self, key): + return self._data[key] + + def __setitem__(self, key, value): + self._data[key] = value + + def __delitem__(self, key): + del self._data[key] + + def __setattr__(self, key, value): + self._data[key] = value + + def __delattr__(self, key): + del self._data[key] + + def __str__(self): + return str(self._data) + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, repr(self._data)) + + def __lt__(self, other): + if isinstance(other, DictWrapper): + return self._data < other._data + else: + return self._data < other + + def __gt__(self, other): + if isinstance(other, DictWrapper): + return self._data > other._data + else: + return self._data > other + + def __eq__(self, other): + if isinstance(other, DictWrapper): + return self._data == other._data + else: + return self._data == other + + +class Request(object): + def __init__(self, display, onerror = None, *args, **keys): + self._errorhandler = onerror + self._binary = self._request.to_binary(*args, **keys) + self._serial = None + display.send_request(self, onerror is not None) + + def _set_error(self, error): + if self._errorhandler is not None: + return call_error_handler(self._errorhandler, error, self) + else: + return 0 + +class ReplyRequest(GetAttrData): + def __init__(self, display, defer = False, *args, **keys): + self._display = display + self._binary = self._request.to_binary(*args, **keys) + self._serial = None + self._data = None + self._error = None + + self._response_lock = lock.allocate_lock() + + self._display.send_request(self, True) + if not defer: + self.reply() + + def reply(self): + # Send request and wait for reply if we hasn't + # already got one. This means that reply() can safely + # be called more than one time. + + self._response_lock.acquire() + while self._data is None and self._error is None: + self._display.send_recv_lock.acquire() + self._response_lock.release() + + self._display.send_and_recv(request = self._serial) + self._response_lock.acquire() + + self._response_lock.release() + self._display = None + + # If error has been set, raise it + if self._error: + raise self._error + + def _parse_response(self, data): + self._response_lock.acquire() + self._data, d = self._reply.parse_binary(data, self._display, rawdict = True) + self._response_lock.release() + + def _set_error(self, error): + self._response_lock.acquire() + self._error = error + self._response_lock.release() + return 1 + + def __repr__(self): + return '<%s serial = %s, data = %s, error = %s>' % (self.__class__.__name__, self._serial, self._data, self._error) + + +class Event(GetAttrData): + def __init__(self, binarydata = None, display = None, + **keys): + if binarydata: + self._binary = binarydata + self._data, data = self._fields.parse_binary(binarydata, display, + rawdict = True) + # split event type into type and send_event bit + self._data['send_event'] = not not self._data['type'] & 0x80 + self._data['type'] = self._data['type'] & 0x7f + else: + if self._code: + keys['type'] = self._code + + keys['sequence_number'] = 0 + + self._binary = self._fields.to_binary(**keys) + + keys['send_event'] = 0 + self._data = keys + + def __repr__(self): + kwlist = [] + for kw, val in self._data.items(): + if kw == 'send_event': + continue + if kw == 'type' and self._data['send_event']: + val = val | 0x80 + kwlist.append('%s = %s' % (kw, repr(val))) + + kws = ', '.join(kwlist) + return '%s(%s)' % (self.__class__.__name__, kws) + + def __lt__(self, other): + if isinstance(other, Event): + return self._data < other._data + else: + return self._data < other + + def __gt__(self, other): + if isinstance(other, Event): + return self._data > other._data + else: + return self._data > other + + def __eq__(self, other): + if isinstance(other, Event): + return self._data == other._data + else: + return self._data == other + + +def call_error_handler(handler, error, request): + try: + return handler(error, request) + except: + sys.stderr.write('Exception raised by error handler.\n') + traceback.print_exc() + return 0 diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/structs.py b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/structs.py new file mode 100644 index 0000000..2cbe18b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/protocol/structs.py @@ -0,0 +1,161 @@ +# Xlib.protocol.structs -- some common request structures +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +# Xlib modules +from .. import X + +# Xlib.protocol modules +from . import rq + +def WindowValues(arg): + return rq.ValueList( arg, 4, 0, + rq.Pixmap('background_pixmap'), + rq.Card32('background_pixel'), + rq.Pixmap('border_pixmap'), + rq.Card32('border_pixel'), + rq.Gravity('bit_gravity'), + rq.Gravity('win_gravity'), + rq.Set('backing_store', 1, + (X.NotUseful, X.WhenMapped, X.Always)), + rq.Card32('backing_planes'), + rq.Card32('backing_pixel'), + rq.Bool('override_redirect'), + rq.Bool('save_under'), + rq.Card32('event_mask'), + rq.Card32('do_not_propagate_mask'), + rq.Colormap('colormap'), + rq.Cursor('cursor'), + ) + +def GCValues(arg): + return rq.ValueList( arg, 4, 0, + rq.Set('function', 1, + (X.GXclear, X.GXand, X.GXandReverse, + X.GXcopy, X.GXandInverted, X.GXnoop, + X.GXxor, X.GXor, X.GXnor, X.GXequiv, + X.GXinvert, X.GXorReverse, X.GXcopyInverted, + X.GXorInverted, X.GXnand, X.GXset)), + rq.Card32('plane_mask'), + rq.Card32('foreground'), + rq.Card32('background'), + rq.Card16('line_width'), + rq.Set('line_style', 1, + (X.LineSolid, X.LineOnOffDash, X.LineDoubleDash)), + rq.Set('cap_style', 1, + (X.CapNotLast, X.CapButt, + X.CapRound, X.CapProjecting)), + rq.Set('join_style', 1, + (X.JoinMiter, X.JoinRound, X.JoinBevel)), + rq.Set('fill_style', 1, + (X.FillSolid, X.FillTiled, + X.FillStippled, X.FillOpaqueStippled)), + rq.Set('fill_rule', 1, + (X.EvenOddRule, X.WindingRule)), + rq.Pixmap('tile'), + rq.Pixmap('stipple'), + rq.Int16('tile_stipple_x_origin'), + rq.Int16('tile_stipple_y_origin'), + rq.Font('font'), + rq.Set('subwindow_mode', 1, + (X.ClipByChildren, X.IncludeInferiors)), + rq.Bool('graphics_exposures'), + rq.Int16('clip_x_origin'), + rq.Int16('clip_y_origin'), + rq.Pixmap('clip_mask'), + rq.Card16('dash_offset'), + rq.Card8('dashes'), + rq.Set('arc_mode', 1, (X.ArcChord, X.ArcPieSlice)) + ) + + + +TimeCoord = rq.Struct( + rq.Card32('time'), + rq.Int16('x'), + rq.Int16('y'), + ) + +Host = rq.Struct( + rq.Set('family', 1, (X.FamilyInternet, X.FamilyDECnet, X.FamilyChaos)), + rq.Pad(1), + rq.LengthOf('name', 2), + rq.List('name', rq.Card8Obj) + ) + +CharInfo = rq.Struct( + rq.Int16('left_side_bearing'), + rq.Int16('right_side_bearing'), + rq.Int16('character_width'), + rq.Int16('ascent'), + rq.Int16('descent'), + rq.Card16('attributes'), + ) + +FontProp = rq.Struct( + rq.Card32('name'), + rq.Card32('value'), + ) + +ColorItem = rq.Struct( + rq.Card32('pixel'), + rq.Card16('red'), + rq.Card16('green'), + rq.Card16('blue'), + rq.Card8('flags'), + rq.Pad(1), + ) + + +RGB = rq.Struct( + rq.Card16('red'), + rq.Card16('green'), + rq.Card16('blue'), + rq.Pad(2), + ) + + +Point = rq.Struct( + rq.Int16('x'), + rq.Int16('y'), + ) + +Segment = rq.Struct( + rq.Int16('x1'), + rq.Int16('y1'), + rq.Int16('x2'), + rq.Int16('y2'), + ) + +Rectangle = rq.Struct( + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + ) + +Arc = rq.Struct( + rq.Int16('x'), + rq.Int16('y'), + rq.Card16('width'), + rq.Card16('height'), + rq.Int16('angle1'), + rq.Int16('angle2'), + ) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/rdb.py b/CLI/venv/lib/python3.12/site-packages/Xlib/rdb.py new file mode 100644 index 0000000..8670b30 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/rdb.py @@ -0,0 +1,712 @@ +# Xlib.rdb -- X resource database implementation +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + + +# See end of file for an explanation of the algorithm and +# data structures used. + + +# Standard modules +import re +import sys + +# Xlib modules +from .support import lock + +# Set up a few regexpes for parsing string representation of resources + +comment_re = re.compile(r'^\s*!') +resource_spec_re = re.compile(r'^\s*([-_a-zA-Z0-9?.*]+)\s*:\s*(.*)$') +value_escape_re = re.compile('\\\\([ \tn\\\\]|[0-7]{3,3})') +resource_parts_re = re.compile(r'([.*]+)') + +# Constants used for determining which match is best + +NAME_MATCH = 0 +CLASS_MATCH = 2 +WILD_MATCH = 4 +MATCH_SKIP = 6 + +# Option error class +class OptionError(Exception): + pass + + +class ResourceDB(object): + def __init__(self, file = None, string = None, resources = None): + self.db = {} + self.lock = lock.allocate_lock() + + if file is not None: + self.insert_file(file) + if string is not None: + self.insert_string(string) + if resources is not None: + self.insert_resources(resources) + + def insert_file(self, file): + """insert_file(file) + + Load resources entries from FILE, and insert them into the + database. FILE can be a filename (a string)or a file object. + + """ + + if type(file) is bytes: + file = open(file, 'r') + + self.insert_string(file.read()) + + + def insert_string(self, data): + """insert_string(data) + + Insert the resources entries in the string DATA into the + database. + + """ + + # First split string into lines + lines = data.split('\n') + + while lines: + line = lines[0] + del lines[0] + + # Skip empty line + if not line: + continue + + # Skip comments + if comment_re.match(line): + continue + + # Handle continued lines + while line[-1] == '\\': + if lines: + line = line[:-1] + lines[0] + del lines[0] + else: + line = line[:-1] + break + + # Split line into resource and value + m = resource_spec_re.match(line) + + # Bad line, just ignore it silently + if not m: + continue + + res, value = m.group(1, 2) + + # Convert all escape sequences in value + splits = value_escape_re.split(value) + + for i in range(1, len(splits), 2): + s = splits[i] + if len(s) == 3: + splits[i] = chr(int(s, 8)) + elif s == 'n': + splits[i] = '\n' + + # strip the last value part to get rid of any + # unescaped blanks + splits[-1] = splits[-1].rstrip() + + value = ''.join(splits) + + self.insert(res, value) + + + def insert_resources(self, resources): + """insert_resources(resources) + + Insert all resources entries in the list RESOURCES into the + database. Each element in RESOURCES should be a tuple: + + (resource, value) + + Where RESOURCE is a string and VALUE can be any Python value. + + """ + + for res, value in resources: + self.insert(res, value) + + def insert(self, resource, value): + """insert(resource, value) + + Insert a resource entry into the database. RESOURCE is a + string and VALUE can be any Python value. + + """ + + # Split res into components and bindings + parts = resource_parts_re.split(resource) + + # If the last part is empty, this is an invalid resource + # which we simply ignore + if parts[-1] == '': + return + + self.lock.acquire() + + db = self.db + for i in range(1, len(parts), 2): + + # Create a new mapping/value group + if parts[i - 1] not in db: + db[parts[i - 1]] = ({}, {}) + + # Use second mapping if a loose binding, first otherwise + if '*' in parts[i]: + db = db[parts[i - 1]][1] + else: + db = db[parts[i - 1]][0] + + # Insert value into the derived db + if parts[-1] in db: + db[parts[-1]] = db[parts[-1]][:2] + (value, ) + else: + db[parts[-1]] = ({}, {}, value) + + self.lock.release() + + def __getitem__(self, keys_tuple): + """db[name, class] + + Return the value matching the resource identified by NAME and + CLASS. If no match is found, KeyError is raised. + """ + + # Split name and class into their parts + name, cls = keys_tuple + + namep = name.split('.') + clsp = cls.split('.') + + # It is an error for name and class to have different number + # of parts + + if len(namep) != len(clsp): + raise ValueError('Different number of parts in resource name/class: %s/%s' % (name, cls)) + + complen = len(namep) + matches = [] + + # Lock database and wrap the lookup code in a try-finally + # block to make sure that it is unlocked. + + self.lock.acquire() + try: + + # Precedence order: name -> class -> ? + + if namep[0] in self.db: + bin_insert(matches, _Match((NAME_MATCH, ), self.db[namep[0]])) + + if clsp[0] in self.db: + bin_insert(matches, _Match((CLASS_MATCH, ), self.db[clsp[0]])) + + if '?' in self.db: + bin_insert(matches, _Match((WILD_MATCH, ), self.db['?'])) + + + # Special case for the unlikely event that the resource + # only has one component + if complen == 1 and matches: + x = matches[0] + if x.final(complen): + return x.value() + else: + raise KeyError((name, cls)) + + + # Special case for resources which begins with a loose + # binding, e.g. '*foo.bar' + if '' in self.db: + bin_insert(matches, _Match((), self.db[''][1])) + + + # Now iterate over all components until we find the best match. + + # For each component, we choose the best partial match among + # the mappings by applying these rules in order: + + # Rule 1: If the current group contains a match for the + # name, class or '?', we drop all previously found loose + # binding mappings. + + # Rule 2: A matching name has precedence over a matching + # class, which in turn has precedence over '?'. + + # Rule 3: Tight bindings have precedence over loose + # bindings. + + while matches: + + # Work on the first element == the best current match + + x = matches[0] + del matches[0] + + # print 'path: ', x.path + # if x.skip: + # print 'skip: ', x.db + # else: + # print 'group: ', x.group + # print + + i = x.match_length() + + for part, score in ((namep[i], NAME_MATCH), + (clsp[i], CLASS_MATCH), + ('?', WILD_MATCH)): + + # Attempt to find a match in x + match = x.match(part, score) + if match: + # Hey, we actually found a value! + if match.final(complen): + return match.value() + + # Else just insert the new match + else: + bin_insert(matches, match) + + # Generate a new loose match + match = x.skip_match(complen) + if match: + bin_insert(matches, match) + + # Oh well, nothing matched + raise KeyError((name, cls)) + + finally: + self.lock.release() + + def get(self, res, cls, default = None): + """get(name, class [, default]) + + Return the value matching the resource identified by NAME and + CLASS. If no match is found, DEFAULT is returned, or None if + DEFAULT isn't specified. + + """ + + try: + return self[(res, cls)] + except KeyError: + return default + + def update(self, db): + """update(db) + + Update this database with all resources entries in the resource + database DB. + + """ + + self.lock.acquire() + update_db(self.db, db.db) + self.lock.release() + + def output(self): + """output() + + Return the resource database in text representation. + """ + + self.lock.acquire() + text = output_db('', self.db) + self.lock.release() + return text + + def getopt(self, name, argv, opts): + """getopt(name, argv, opts) + + Parse X command line options, inserting the recognised options + into the resource database. + + NAME is the application name, and will be prepended to all + specifiers. ARGV is the list of command line arguments, + typically sys.argv[1:]. + + OPTS is a mapping of options to resource specifiers. The key is + the option flag (with leading -), and the value is an instance of + some Option subclass: + + NoArg(specifier, value): set resource to value. + IsArg(specifier): set resource to option itself + SepArg(specifier): value is next argument + ResArg: resource and value in next argument + SkipArg: ignore this option and next argument + SkipLine: ignore rest of arguments + SkipNArgs(count): ignore this option and count arguments + + The remaining, non-option, oparguments is returned. + + rdb.OptionError is raised if there is an error in the argument list. + """ + + while argv and argv[0] and argv[0][0] == '-': + try: + argv = opts[argv[0]].parse(name, self, argv) + except KeyError: + raise OptionError('unknown option: %s' % argv[0]) + except IndexError: + raise OptionError('missing argument to option: %s' % argv[0]) + + return argv + + +class _Match(object): + def __init__(self, path, dbs): + self.path = path + + if type(dbs) is tuple: + self.skip = 0 + self.group = dbs + + else: + self.skip = 1 + self.db = dbs + + def __lt__(self, other): + return self.path < other.path + + def __gt__(self, other): + return self.path > other.path + + def __eq__(self, other): + return self.path == other.path + + def match_length(self): + return len(self.path) + + def match(self, part, score): + if self.skip: + if part in self.db: + return _Match(self.path + (score, ), self.db[part]) + else: + return None + else: + if part in self.group[0]: + return _Match(self.path + (score, ), self.group[0][part]) + elif part in self.group[1]: + return _Match(self.path + (score + 1, ), self.group[1][part]) + else: + return None + + def skip_match(self, complen): + # Can't make another skip if we have run out of components + if len(self.path) + 1 >= complen: + return None + + # If this already is a skip match, clone a new one + if self.skip: + if self.db: + return _Match(self.path + (MATCH_SKIP, ), self.db) + else: + return None + + # Only generate a skip match if the loose binding mapping + # is non-empty + elif self.group[1]: + return _Match(self.path + (MATCH_SKIP, ), self.group[1]) + + # This is a dead end match + else: + return None + + def final(self, complen): + if not self.skip and len(self.path) == complen and len(self.group) > 2: + return 1 + else: + return 0 + + def value(self): + return self.group[2] + + +# +# Helper function for ResourceDB.__getitem__() +# + +def bin_insert(list, element): + """bin_insert(list, element) + + Insert ELEMENT into LIST. LIST must be sorted, and ELEMENT will + be inserted to that LIST remains sorted. If LIST already contains + ELEMENT, it will not be duplicated. + + """ + + if not list: + list.append(element) + return + + lower = 0 + upper = len(list) - 1 + + while lower <= upper: + center = (lower + upper) // 2 + if element < list[center]: + upper = center - 1 + elif element > list[center]: + lower = center + 1 + elif element == list[center]: + return + + if element < list[upper]: + list.insert(upper, element) + elif element > list[upper]: + list.insert(upper + 1, element) + + +# +# Helper functions for ResourceDB.update() +# + +def update_db(dest, src): + for comp, group in src.items(): + + # DEST already contains this component, update it + if comp in dest: + + # Update tight and loose binding databases + update_db(dest[comp][0], group[0]) + update_db(dest[comp][1], group[1]) + + # If a value has been set in SRC, update + # value in DEST + + if len(group) > 2: + dest[comp] = dest[comp][:2] + group[2:] + + # COMP not in src, make a deep copy + else: + dest[comp] = copy_group(group) + +def copy_group(group): + return (copy_db(group[0]), copy_db(group[1])) + group[2:] + +def copy_db(db): + newdb = {} + for comp, group in db.items(): + newdb[comp] = copy_group(group) + + return newdb + + +# +# Helper functions for output +# + +def output_db(prefix, db): + res = '' + for comp, group in db.items(): + + # There's a value for this component + if len(group) > 2: + res = res + '%s%s: %s\n' % (prefix, comp, output_escape(group[2])) + + # Output tight and loose bindings + res = res + output_db(prefix + comp + '.', group[0]) + res = res + output_db(prefix + comp + '*', group[1]) + + return res + +def output_escape(value): + value = str(value) + if not value: + return value + + for char, esc in (('\\', '\\\\'), + ('\000', '\\000'), + ('\n', '\\n')): + + value = value.replace(char, esc) + + # If first or last character is space or tab, escape them. + if value[0] in ' \t': + value = '\\' + value + if value[-1] in ' \t' and value[-2:-1] != '\\': + value = value[:-1] + '\\' + value[-1] + + return value + + +# +# Option type definitions +# + +class Option(object): + def __init__(self): + pass + + def parse(self, name, db, args): + pass + +class NoArg(Option): + """Value is provided to constructor.""" + def __init__(self, specifier, value): + self.specifier = specifier + self.value = value + + def parse(self, name, db, args): + db.insert(name + self.specifier, self.value) + return args[1:] + +class IsArg(Option): + """Value is the option string itself.""" + def __init__(self, specifier): + self.specifier = specifier + + def parse(self, name, db, args): + db.insert(name + self.specifier, args[0]) + return args[1:] + +class SepArg(Option): + """Value is the next argument.""" + def __init__(self, specifier): + self.specifier = specifier + + def parse(self, name, db, args): + db.insert(name + self.specifier, args[1]) + return args[2:] + +class ResArgClass(Option): + """Resource and value in the next argument.""" + def parse(self, name, db, args): + db.insert_string(args[1]) + return args[2:] + +ResArg = ResArgClass() + +class SkipArgClass(Option): + """Ignore this option and next argument.""" + def parse(self, name, db, args): + return args[2:] + +SkipArg = SkipArgClass() + +class SkipLineClass(Option): + """Ignore rest of the arguments.""" + def parse(self, name, db, args): + return [] + +SkipLine = SkipLineClass() + +class SkipNArgs(Option): + """Ignore this option and the next COUNT arguments.""" + def __init__(self, count): + self.count = count + + def parse(self, name, db, args): + return args[1 + self.count:] + + + +def get_display_opts(options, argv = sys.argv): + """display, name, db, args = get_display_opts(options, [argv]) + + Parse X OPTIONS from ARGV (or sys.argv if not provided). + + Connect to the display specified by a *.display resource if one is + set, or to the default X display otherwise. Extract the + RESOURCE_MANAGER property and insert all resources from ARGV. + + The four return values are: + DISPLAY -- the display object + NAME -- the application name (the filname of ARGV[0]) + DB -- the created resource database + ARGS -- any remaining arguments + """ + + from Xlib import display, Xatom + import os + + name = os.path.splitext(os.path.basename(argv[0]))[0] + + optdb = ResourceDB() + leftargv = optdb.getopt(name, argv[1:], options) + + dname = optdb.get(name + '.display', name + '.Display', None) + d = display.Display(dname) + + rdbstring = d.screen(0).root.get_full_property(Xatom.RESOURCE_MANAGER, + Xatom.STRING) + if rdbstring: + data = rdbstring.value + else: + data = None + + db = ResourceDB(string = data) + db.update(optdb) + + return d, name, db, leftargv + + +# Common X options +stdopts = {'-bg': SepArg('*background'), + '-background': SepArg('*background'), + '-fg': SepArg('*foreground'), + '-foreground': SepArg('*foreground'), + '-fn': SepArg('*font'), + '-font': SepArg('*font'), + '-name': SepArg('.name'), + '-title': SepArg('.title'), + '-synchronous': NoArg('*synchronous', 'on'), + '-xrm': ResArg, + '-display': SepArg('.display'), + '-d': SepArg('.display'), + } + + +# Notes on the implementation: + +# Resource names are split into their components, and each component +# is stored in a mapping. The value for a component is a tuple of two +# or three elements: + +# (tightmapping, loosemapping [, value]) + +# tightmapping contains the next components which are connected with a +# tight binding (.). loosemapping contains the ones connected with +# loose binding (*). If value is present, then this component is the +# last component for some resource which that value. + +# The top level components are stored in the mapping r.db, where r is +# the resource object. + +# Example: Inserting "foo.bar*gazonk: yep" into an otherwise empty +# resource database would give the following structure: + +# { 'foo': ( { 'bar': ( { }, +# { 'gazonk': ( { }, +# { }, +# 'yep') +# } +# ) +# }, +# {}) +# } diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/__init__.py b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__init__.py new file mode 100644 index 0000000..d6c1746 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__init__.py @@ -0,0 +1,26 @@ +# Xlib.support.__init__ -- support code package +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +__all__ = [ + 'lock', + 'connect' + # The platform specific modules should not be listed here + ] diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..9c0269e Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/connect.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/connect.cpython-312.pyc new file mode 100644 index 0000000..5756f25 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/connect.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/lock.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/lock.cpython-312.pyc new file mode 100644 index 0000000..7f08893 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/lock.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/unix_connect.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/unix_connect.cpython-312.pyc new file mode 100644 index 0000000..4def218 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/unix_connect.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/vms_connect.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/vms_connect.cpython-312.pyc new file mode 100644 index 0000000..0fd8b38 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/support/__pycache__/vms_connect.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/connect.py b/CLI/venv/lib/python3.12/site-packages/Xlib/support/connect.py new file mode 100644 index 0000000..e8c822f --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/support/connect.py @@ -0,0 +1,102 @@ +# Xlib.support.connect -- OS-independent display connection functions +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +import sys +import importlib + +# List the modules which contain the corresponding functions + +_display_mods = { + 'OpenVMS': 'vms_connect', + } + +_default_display_mod = 'unix_connect' + +_socket_mods = { + 'OpenVMS': 'vms_connect' + } + +_default_socket_mod = 'unix_connect' + +_auth_mods = { + 'OpenVMS': 'vms_connect' + } + +_default_auth_mod = 'unix_connect' + + +# Figure out which OS we're using. +# sys.platform is either "OS-ARCH" or just "OS". + +_parts = sys.platform.split('-') +platform = _parts[0] +del _parts + + +def _relative_import(modname): + return importlib.import_module('..' + modname, __name__) + + +def get_display(display): + """dname, protocol, host, dno, screen = get_display(display) + + Parse DISPLAY into its components. If DISPLAY is None, use + the default display. The return values are: + + DNAME -- the full display name (string) + PROTOCOL -- the protocol to use (None if automatic) + HOST -- the host name (string, possibly empty) + DNO -- display number (integer) + SCREEN -- default screen number (integer) + """ + + modname = _display_mods.get(platform, _default_display_mod) + mod = _relative_import(modname) + return mod.get_display(display) + + +def get_socket(dname, protocol, host, dno): + """socket = get_socket(dname, protocol, host, dno) + + Connect to the display specified by DNAME, PROTOCOL, HOST and DNO, which + are the corresponding values from a previous call to get_display(). + + Return SOCKET, a new socket object connected to the X server. + """ + + modname = _socket_mods.get(platform, _default_socket_mod) + mod = _relative_import(modname) + return mod.get_socket(dname, protocol, host, dno) + + +def get_auth(sock, dname, protocol, host, dno): + """auth_name, auth_data = get_auth(sock, dname, protocol, host, dno) + + Return authentication data for the display on the other side of + SOCK, which was opened with DNAME, HOST and DNO, using PROTOCOL. + + Return AUTH_NAME and AUTH_DATA, two strings to be used in the + connection setup request. + """ + + modname = _auth_mods.get(platform, _default_auth_mod) + mod = _relative_import(modname) + return mod.get_auth(sock, dname, protocol, host, dno) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/lock.py b/CLI/venv/lib/python3.12/site-packages/Xlib/support/lock.py new file mode 100644 index 0000000..29289b6 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/support/lock.py @@ -0,0 +1,44 @@ +# Xlib.support.lock -- allocate a lock +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +class _DummyLock(object): + def __init__(self): + + # This might be nerdy, but by assigning methods like this + # instead of defining them all, we create a single bound + # method object once instead of one each time one of the + # methods is called. + + # This gives some speed improvements which should reduce the + # impact of the threading infrastructure in the regular code, + # when not using threading. + + self.acquire = self.release = self.locked = self.__noop + + def __noop(self, *args): + return + + +# More optimisations: we use a single lock for all lock instances +_dummy_lock = _DummyLock() + +def allocate_lock(): + return _dummy_lock diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/unix_connect.py b/CLI/venv/lib/python3.12/site-packages/Xlib/support/unix_connect.py new file mode 100644 index 0000000..aee6dd9 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/support/unix_connect.py @@ -0,0 +1,217 @@ +# Xlib.support.unix_connect -- Unix-type display connection functions +# +# Copyright (C) 2000,2002 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +import re +import os +import platform +import socket +from Xlib import error, xauth + + +SUPPORTED_PROTOCOLS = (None, 'tcp', 'unix') + +# Darwin funky socket. +uname = platform.uname() +if (uname[0] == 'Darwin') and ([int(x) for x in uname[2].split('.')] >= [9, 0]): + SUPPORTED_PROTOCOLS += ('darwin',) + DARWIN_DISPLAY_RE = re.compile(r'^/private/tmp/[-:a-zA-Z0-9._]*:(?P[0-9]+)(\.(?P[0-9]+))?$') + +DISPLAY_RE = re.compile(r'^((?Ptcp|unix)/)?(?P[-:a-zA-Z0-9._]*):(?P[0-9]+)(\.(?P[0-9]+))?$') + + +def get_display(display): + # Use $DISPLAY if display isn't provided + if display is None: + display = os.environ.get('DISPLAY', '') + + re_list = [(DISPLAY_RE, {})] + + if 'darwin' in SUPPORTED_PROTOCOLS: + re_list.insert(0, (DARWIN_DISPLAY_RE, {'protocol': 'darwin'})) + + for re, defaults in re_list: + m = re.match(display) + if m is not None: + protocol, host, dno, screen = [ + m.groupdict().get(field, defaults.get(field)) + for field in ('proto', 'host', 'dno', 'screen') + ] + break + else: + raise error.DisplayNameError(display) + + if protocol == 'tcp' and not host: + # Host is mandatory when protocol is TCP. + raise error.DisplayNameError(display) + + dno = int(dno) + if screen: + screen = int(screen) + else: + screen = 0 + + return display, protocol, host, dno, screen + + +def _get_tcp_socket(host, dno): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((host, 6000 + dno)) + return s + + +def _get_unix_socket(address): + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(address) + return s + + +def get_socket(dname, protocol, host, dno): + assert protocol in SUPPORTED_PROTOCOLS + try: + # Darwin funky socket. + if protocol == 'darwin': + s = _get_unix_socket(dname) + + # TCP socket, note the special case: `unix:0.0` is equivalent to `:0.0`. + elif (protocol is None or protocol != 'unix') and host and host != 'unix': + s = _get_tcp_socket(host, dno) + + # Unix socket. + else: + address = '/tmp/.X11-unix/X%d' % dno + if not os.path.exists(address): + # Use abstract address. + address = '\0' + address + try: + s = _get_unix_socket(address) + except socket.error: + if not protocol and not host: + # If no protocol/host was specified, fallback to TCP. + s = _get_tcp_socket(host, dno) + else: + raise + except socket.error as val: + raise error.DisplayConnectionError(dname, str(val)) + + # Make sure that the connection isn't inherited in child processes. + _ensure_not_inheritable(s) + + return s + + +def _ensure_not_inheritable(sock): + # According to PEP446, in Python 3.4 and above, + # it is not inherited in child processes by default. + # However, just in case, we explicitly make it non-inheritable. + # Also, we don't use the code like the following, + # because there would be no possibility of backporting to past versions. + # if sys.version_info.major == 3 and sys.version_info.minor >= 4: + # sock.set_inheritable(False) + # return + # We just check if the socket has `set_inheritable`. + if hasattr(sock, 'set_inheritable'): + sock.set_inheritable(False) + return + + # On Windows, + # Python doesn't support fcntl module because Windows doesn't have fcntl API. + # At least by not importing fcntl, we will be able to import python-xlib on Windows. + if platform.system() == 'Windows': + # so.. unfortunately, for Python 3.3 and below, on Windows, + # we can't make sure that the connection isn't inherited in child processes for now. + return + + import fcntl + fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC) + + +def new_get_auth(sock, dname, protocol, host, dno): + assert protocol in SUPPORTED_PROTOCOLS + # Translate socket address into the xauth domain + if protocol == 'darwin': + family = xauth.FamilyLocal + addr = socket.gethostname() + + elif protocol == 'tcp': + family = xauth.FamilyInternet + + # Convert the prettyprinted IP number into 4-octet string. + # Sometimes these modules are too damn smart... + octets = sock.getpeername()[0].split('.') + addr = bytearray(int(x) for x in octets) + else: + family = xauth.FamilyLocal + addr = socket.gethostname().encode() + + try: + au = xauth.Xauthority() + except error.XauthError: + return b'', b'' + + while 1: + try: + return au.get_best_auth(family, addr, dno) + except error.XNoAuthError: + pass + + # We need to do this to handle ssh's X forwarding. It sets + # $DISPLAY to localhost:10, but stores the xauth cookie as if + # DISPLAY was :10. Hence, if localhost and not found, try + # again as a Unix socket. + if family == xauth.FamilyInternet and addr == b'\x7f\x00\x00\x01': + family = xauth.FamilyLocal + addr = socket.gethostname().encode() + else: + return b'', b'' + + +def old_get_auth(sock, dname, host, dno): + # Find authorization cookie + auth_name = auth_data = b'' + + try: + # We could parse .Xauthority, but xauth is simpler + # although more inefficient + data = os.popen('xauth list %s 2>/dev/null' % dname).read() + + # If there's a cookie, it is of the format + # DISPLAY SCHEME COOKIE + # We're interested in the two last parts for the + # connection establishment + lines = data.split('\n') + if len(lines) >= 1: + parts = lines[0].split(None, 2) + if len(parts) == 3: + auth_name = parts[1] + hexauth = parts[2] + auth = b'' + + # Translate hexcode into binary + for i in range(0, len(hexauth), 2): + auth = auth + chr(int(hexauth[i:i+2], 16)) + + auth_data = auth + except os.error: + pass + + return auth_name, auth_data + +get_auth = new_get_auth diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/support/vms_connect.py b/CLI/venv/lib/python3.12/site-packages/Xlib/support/vms_connect.py new file mode 100644 index 0000000..2799bfa --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/support/vms_connect.py @@ -0,0 +1,74 @@ +# Xlib.support.vms_connect -- VMS-type display connection functions +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +import re +import socket + +from Xlib import error + +display_re = re.compile(r'^([-a-zA-Z0-9._]*):([0-9]+)(\.([0-9]+))?$') + +def get_display(display): + + # Use dummy display if none is set. We really should + # check DECW$DISPLAY instead, but that has to wait + + if display is None: + return ':0.0', None, 'localhost', 0, 0 + + m = display_re.match(display) + if not m: + raise error.DisplayNameError(display) + + name = display + + # Always return a host, since we don't have AF_UNIX sockets + host = m.group(1) + if not host: + host = 'localhost' + + dno = int(m.group(2)) + screen = m.group(4) + if screen: + screen = int(screen) + else: + screen = 0 + + return name, None, host, dno, screen + + +def get_socket(dname, protocol, host, dno): + try: + # Always use TCP/IP sockets. Later it would be nice to + # be able to use DECNET och LOCAL connections. + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((host, 6000 + dno)) + + except socket.error as val: + raise error.DisplayConnectionError(dname, str(val)) + + return s + + +def get_auth(sock, dname, host, dno): + # VMS doesn't have xauth + return '', '' diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/threaded.py b/CLI/venv/lib/python3.12/site-packages/Xlib/threaded.py new file mode 100644 index 0000000..5fdf016 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/threaded.py @@ -0,0 +1,28 @@ +# Xlib.threaded -- Import this module to enable threading +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from six.moves import _thread + +# We change the allocate_lock function in Xlib.support.lock to +# return a basic Python lock, instead of the default dummy lock + +from Xlib.support import lock +lock.allocate_lock = _thread.allocate_lock diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xauth.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xauth.py new file mode 100644 index 0000000..8651448 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xauth.py @@ -0,0 +1,134 @@ +# Xlib.xauth -- ~/.Xauthority access +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +import os +import struct + +from Xlib import X, error + +FamilyInternet = X.FamilyInternet +FamilyDECnet = X.FamilyDECnet +FamilyChaos = X.FamilyChaos +FamilyServerInterpreted = X.FamilyServerInterpreted +FamilyInternetV6 = X.FamilyInternetV6 +FamilyLocal = 256 + +class Xauthority(object): + def __init__(self, filename = None): + if filename is None: + filename = os.environ.get('XAUTHORITY') + + if filename is None: + try: + filename = os.path.join(os.environ['HOME'], '.Xauthority') + except KeyError: + raise error.XauthError( + '$HOME not set, cannot find ~/.Xauthority') + + try: + with open(filename, 'rb') as fp: + raw = fp.read() + except IOError as err: + raise error.XauthError('could not read from {0}: {1}'.format(filename, err)) + + self.entries = [] + + # entry format (all shorts in big-endian) + # short family; + # short addrlen; + # char addr[addrlen]; + # short numlen; + # char num[numlen]; + # short namelen; + # char name[namelen]; + # short datalen; + # char data[datalen]; + + n = 0 + try: + while n < len(raw): + family, = struct.unpack('>H', raw[n:n+2]) + n = n + 2 + + length, = struct.unpack('>H', raw[n:n+2]) + n = n + length + 2 + addr = raw[n - length : n] + + length, = struct.unpack('>H', raw[n:n+2]) + n = n + length + 2 + num = raw[n - length : n] + + length, = struct.unpack('>H', raw[n:n+2]) + n = n + length + 2 + name = raw[n - length : n] + + length, = struct.unpack('>H', raw[n:n+2]) + n = n + length + 2 + data = raw[n - length : n] + + if len(data) != length: + break + + self.entries.append((family, addr, num, name, data)) + except struct.error: + print("Xlib.xauth: warning, failed to parse part of xauthority file {0}, aborting all further parsing".format(filename)) + + if len(self.entries) == 0: + print("Xlib.xauth: warning, no xauthority details available") + # raise an error? this should get partially caught by the XNoAuthError in get_best_auth.. + + def __len__(self): + return len(self.entries) + + def __getitem__(self, i): + return self.entries[i] + + def get_best_auth(self, family, address, dispno, + types = ( b"MIT-MAGIC-COOKIE-1", )): + + """Find an authentication entry matching FAMILY, ADDRESS and + DISPNO. + + The name of the auth scheme must match one of the names in + TYPES. If several entries match, the first scheme in TYPES + will be choosen. + + If an entry is found, the tuple (name, data) is returned, + otherwise XNoAuthError is raised. + """ + + num = str(dispno).encode() + + matches = {} + + for efam, eaddr, enum, ename, edata in self.entries: + if enum == b'' and ename not in matches: + enum = num + if efam == family and eaddr == address and num == enum: + matches[ename] = edata + + for t in types: + try: + return (t, matches[t]) + except KeyError: + pass + + raise error.XNoAuthError((family, address, dispno)) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__init__.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__init__.py new file mode 100644 index 0000000..6fb3bc9 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__init__.py @@ -0,0 +1,29 @@ +# Xlib.xobject.__init__ -- glue for Xlib.xobject package +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +__all__ = [ + 'colormap', + 'cursor', + 'drawable', + 'fontable', + 'icccm', + 'resource', + ] diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..442f23a Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/colormap.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/colormap.cpython-312.pyc new file mode 100644 index 0000000..7ba0e4a Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/colormap.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/cursor.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/cursor.cpython-312.pyc new file mode 100644 index 0000000..3cf5a68 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/cursor.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/drawable.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/drawable.cpython-312.pyc new file mode 100644 index 0000000..8679191 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/drawable.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/fontable.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/fontable.cpython-312.pyc new file mode 100644 index 0000000..9079a4c Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/fontable.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/icccm.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/icccm.cpython-312.pyc new file mode 100644 index 0000000..9a917a1 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/icccm.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/resource.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/resource.cpython-312.pyc new file mode 100644 index 0000000..0386907 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/__pycache__/resource.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/colormap.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/colormap.py new file mode 100644 index 0000000..8ba2fce --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/colormap.py @@ -0,0 +1,141 @@ +# Xlib.xobject.colormap -- colormap object +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib import error +from Xlib.protocol import request + +from . import resource + +import re + +rgb_res = [ + re.compile(r'\Argb:([0-9a-fA-F]{1,4})/([0-9a-fA-F]{1,4})/([0-9a-fA-F]{1,4})\Z'), + re.compile(r'\A#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\Z'), + re.compile(r'\A#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])\Z'), + re.compile(r'\A#([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])\Z'), + re.compile(r'\A#([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])\Z'), + ] + +class Colormap(resource.Resource): + __colormap__ = resource.Resource.__resource__ + + def free(self, onerror = None): + request.FreeColormap(display = self.display, + onerror = onerror, + cmap = self.id) + + self.display.free_resource_id(self.id) + + def copy_colormap_and_free(self, scr_cmap): + mid = self.display.allocate_resource_id() + request.CopyColormapAndFree(display = self.display, + mid = mid, + src_cmap = src_cmap) + + cls = self.display.get_resource_class('colormap', Colormap) + return cls(self.display, mid, owner = 1) + + def install_colormap(self, onerror = None): + request.InstallColormap(display = self.display, + onerror = onerror, + cmap = self.id) + + def uninstall_colormap(self, onerror = None): + request.UninstallColormap(display = self.display, + onerror = onerror, + cmap = self.id) + + def alloc_color(self, red, green, blue): + return request.AllocColor(display = self.display, + cmap = self.id, + red = red, + green = green, + blue = blue) + + def alloc_named_color(self, name): + for r in rgb_res: + m = r.match(name) + if m: + rs = m.group(1) + r = int(rs + '0' * (4 - len(rs)), 16) + + gs = m.group(2) + g = int(gs + '0' * (4 - len(gs)), 16) + + bs = m.group(3) + b = int(bs + '0' * (4 - len(bs)), 16) + + return self.alloc_color(r, g, b) + + try: + return request.AllocNamedColor(display = self.display, + cmap = self.id, + name = name) + except error.BadName: + return None + + def alloc_color_cells(self, contiguous, colors, planes): + return request.AllocColorCells(display = self.display, + contiguous = contiguous, + cmap = self.id, + colors = colors, + planes = planes) + + def alloc_color_planes(self, contiguous, colors, red, green, blue): + return request.AllocColorPlanes(display = self.display, + contiguous = contiguous, + cmap = self.id, + colors = colors, + red = red, + green = green, + blue = blue) + + def free_colors(self, pixels, plane_mask, onerror = None): + request.FreeColors(display = self.display, + onerror = onerror, + cmap = self.id, + plane_mask = plane_mask, + pixels = pixels) + + def store_colors(self, items, onerror = None): + request.StoreColors(display = self.display, + onerror = onerror, + cmap = self.id, + items = items) + + def store_named_color(self, name, pixel, flags, onerror = None): + request.StoreNamedColor(display = self.display, + onerror = onerror, + flags = flags, + cmap = self.id, + pixel = pixel, + name = name) + + def query_colors(self, pixels): + r = request.QueryColors(display = self.display, + cmap = self.id, + pixels = pixels) + return r.colors + + def lookup_color(self, name): + return request.LookupColor(display = self.display, + cmap = self.id, + name = name) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/cursor.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/cursor.py new file mode 100644 index 0000000..2d49bbb --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/cursor.py @@ -0,0 +1,47 @@ +# Xlib.xobject.cursor -- cursor object +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib.protocol import request + +from . import resource + +class Cursor(resource.Resource): + __cursor__ = resource.Resource.__resource__ + + def free(self, onerror = None): + request.FreeCursor(display = self.display, + onerror = onerror, + cursor = self.id) + self.display.free_resource_id(self.id) + + def recolor(self, foreground, background, onerror=None): + fore_red, fore_green, fore_blue = foreground + back_red, back_green, back_blue = background + + request.RecolorCursor(display = self.display, + onerror = onerror, + cursor = self.id, + fore_red = fore_red, + fore_green = fore_green, + fore_blue = fore_blue, + back_red = back_red, + back_green = back_green, + back_blue = back_blue) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/drawable.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/drawable.py new file mode 100644 index 0000000..c47b91b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/drawable.py @@ -0,0 +1,835 @@ +# Xlib.xobject.drawable -- drawable objects (window and pixmap) +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib import X, Xatom +from Xlib.protocol import request, rq + +# Other X resource objects +from . import resource +from . import colormap +from . import cursor +from . import fontable + +# Inter-client communication conventions +from . import icccm + +class Drawable(resource.Resource): + __drawable__ = resource.Resource.__resource__ + + def get_geometry(self): + return request.GetGeometry(display = self.display, + drawable = self) + + def create_pixmap(self, width, height, depth): + pid = self.display.allocate_resource_id() + request.CreatePixmap(display = self.display, + depth = depth, + pid = pid, + drawable = self.id, + width = width, + height = height) + + cls = self.display.get_resource_class('pixmap', Pixmap) + return cls(self.display, pid, owner = 1) + + def create_gc(self, **keys): + cid = self.display.allocate_resource_id() + request.CreateGC(display = self.display, + cid = cid, + drawable = self.id, + attrs = keys) + + cls = self.display.get_resource_class('gc', fontable.GC) + return cls(self.display, cid, owner = 1) + + def copy_area(self, gc, src_drawable, src_x, src_y, width, height, dst_x, dst_y, onerror = None): + request.CopyArea(display = self.display, + onerror = onerror, + src_drawable = src_drawable, + dst_drawable = self.id, + gc = gc, + src_x = src_x, + src_y = src_y, + dst_x = dst_x, + dst_y = dst_y, + width = width, + height = height) + + def copy_plane(self, gc, src_drawable, src_x, src_y, width, height, + dst_x, dst_y, bit_plane, onerror = None): + request.CopyPlane(display = self.display, + onerror = onerror, + src_drawable = src_drawable, + dst_drawable = self.id, + gc = gc, + src_x = src_x, + src_y = src_y, + dst_x = dst_x, + dst_y = dst_y, + width = width, + height = height, + bit_plane = bit_plane) + + def poly_point(self, gc, coord_mode, points, onerror = None): + request.PolyPoint(display = self.display, + onerror = onerror, + coord_mode = coord_mode, + drawable = self.id, + gc = gc, + points = points) + + def point(self, gc, x, y, onerror = None): + request.PolyPoint(display = self.display, + onerror = onerror, + coord_mode = X.CoordModeOrigin, + drawable = self.id, + gc = gc, + points = [(x, y)]) + + def poly_line(self, gc, coord_mode, points, onerror = None): + request.PolyLine(display = self.display, + onerror = onerror, + coord_mode = coord_mode, + drawable = self.id, + gc = gc, + points = points) + + def line(self, gc, x1, y1, x2, y2, onerror = None): + request.PolySegment(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + segments = [(x1, y1, x2, y2)]) + + def poly_segment(self, gc, segments, onerror = None): + request.PolySegment(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + segments = segments) + + def poly_rectangle(self, gc, rectangles, onerror = None): + request.PolyRectangle(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + rectangles = rectangles) + + def rectangle(self, gc, x, y, width, height, onerror = None): + request.PolyRectangle(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + rectangles = [(x, y, width, height)]) + + + def poly_arc(self, gc, arcs, onerror = None): + request.PolyArc(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + arcs = arcs) + + def arc(self, gc, x, y, width, height, angle1, angle2, onerror = None): + request.PolyArc(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + arcs = [(x, y, width, height, angle1, angle2)]) + + def fill_poly(self, gc, shape, coord_mode, points, onerror = None): + request.FillPoly(display = self.display, + onerror = onerror, + shape = shape, + coord_mode = coord_mode, + drawable = self.id, + gc = gc, + points = points) + + def poly_fill_rectangle(self, gc, rectangles, onerror = None): + request.PolyFillRectangle(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + rectangles = rectangles) + + def fill_rectangle(self, gc, x, y, width, height, onerror = None): + request.PolyFillRectangle(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + rectangles = [(x, y, width, height)]) + + def poly_fill_arc(self, gc, arcs, onerror = None): + request.PolyFillArc(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + arcs = arcs) + + def fill_arc(self, gc, x, y, width, height, angle1, angle2, onerror = None): + request.PolyFillArc(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + arcs = [(x, y, width, height, angle1, angle2)]) + + + def put_image(self, gc, x, y, width, height, format, + depth, left_pad, data, onerror = None): + request.PutImage(display = self.display, + onerror = onerror, + format = format, + drawable = self.id, + gc = gc, + width = width, + height = height, + dst_x = x, + dst_y = y, + left_pad = left_pad, + depth = depth, + data = data) + + # Trivial little method for putting PIL images. Will break on anything + # but depth 1 or 24... + def put_pil_image(self, gc, x, y, image, onerror = None): + width, height = image.size + if image.mode == '1': + format = X.XYBitmap + depth = 1 + if self.display.info.bitmap_format_bit_order == 0: + rawmode = '1;R' + else: + rawmode = '1' + pad = self.display.info.bitmap_format_scanline_pad + stride = roundup(width, pad) >> 3 + elif image.mode == 'RGB': + format = X.ZPixmap + depth = 24 + if self.display.info.image_byte_order == 0: + rawmode = 'BGRX' + else: + rawmode = 'RGBX' + pad = self.display.info.bitmap_format_scanline_pad + unit = self.display.info.bitmap_format_scanline_unit + stride = roundup(width * unit, pad) >> 3 + else: + raise ValueError('Unknown data format') + + maxlen = (self.display.info.max_request_length << 2) \ + - request.PutImage._request.static_size + split = maxlen // stride + + x1 = 0 + x2 = width + y1 = 0 + + while y1 < height: + h = min(height, split) + if h < height: + subimage = image.crop((x1, y1, x2, y1 + h)) + else: + subimage = image + w, h = subimage.size + data = subimage.tobytes("raw", rawmode, stride, 0) + self.put_image(gc, x, y, w, h, format, depth, 0, data) + y1 = y1 + h + y = y + h + + + def get_image(self, x, y, width, height, format, plane_mask): + return request.GetImage(display = self.display, + format = format, + drawable = self.id, + x = x, + y = y, + width = width, + height = height, + plane_mask = plane_mask) + + def draw_text(self, gc, x, y, text, onerror = None): + request.PolyText8(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + x = x, + y = y, + items = [text]) + + def poly_text(self, gc, x, y, items, onerror = None): + request.PolyText8(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + x = x, + y = y, + items = items) + + def poly_text_16(self, gc, x, y, items, onerror = None): + request.PolyText16(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + x = x, + y = y, + items = items) + + def image_text(self, gc, x, y, string, onerror = None): + request.ImageText8(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + x = x, + y = y, + string = string) + + def image_text_16(self, gc, x, y, string, onerror = None): + request.ImageText16(display = self.display, + onerror = onerror, + drawable = self.id, + gc = gc, + x = x, + y = y, + string = string) + + def query_best_size(self, item_class, width, height): + return request.QueryBestSize(display = self.display, + item_class = item_class, + drawable = self.id, + width = width, + height = height) + +class Window(Drawable): + __window__ = resource.Resource.__resource__ + + _STRING_ENCODING = 'ISO-8859-1' + _UTF8_STRING_ENCODING = 'UTF-8' + + def create_window(self, x, y, width, height, border_width, depth, + window_class = X.CopyFromParent, + visual = X.CopyFromParent, + onerror = None, + **keys): + + wid = self.display.allocate_resource_id() + request.CreateWindow(display = self.display, + onerror = onerror, + depth = depth, + wid = wid, + parent = self.id, + x = x, + y = y, + width = width, + height = height, + border_width = border_width, + window_class = window_class, + visual = visual, + attrs = keys) + + cls = self.display.get_resource_class('window', Window) + return cls(self.display, wid, owner = 1) + + def change_attributes(self, onerror = None, **keys): + request.ChangeWindowAttributes(display = self.display, + onerror = onerror, + window = self.id, + attrs = keys) + + def get_attributes(self): + return request.GetWindowAttributes(display = self.display, + window = self.id) + + def destroy(self, onerror = None): + request.DestroyWindow(display = self.display, + onerror = onerror, + window = self.id) + + self.display.free_resource_id(self.id) + + def destroy_sub_windows(self, onerror = None): + request.DestroySubWindows(display = self.display, + onerror = onerror, + window = self.id) + + + def change_save_set(self, mode, onerror = None): + request.ChangeSaveSet(display = self.display, + onerror = onerror, + mode = mode, + window = self.id) + + def reparent(self, parent, x, y, onerror = None): + request.ReparentWindow(display = self.display, + onerror = onerror, + window = self.id, + parent = parent, + x = x, + y = y) + + def map(self, onerror = None): + request.MapWindow(display = self.display, + onerror = onerror, + window = self.id) + + def map_sub_windows(self, onerror = None): + request.MapSubwindows(display = self.display, + onerror = onerror, + window = self.id) + + def unmap(self, onerror = None): + request.UnmapWindow(display = self.display, + onerror = onerror, + window = self.id) + + def unmap_sub_windows(self, onerror = None): + request.UnmapSubwindows(display = self.display, + onerror = onerror, + window = self.id) + + def configure(self, onerror = None, **keys): + request.ConfigureWindow(display = self.display, + onerror = onerror, + window = self.id, + attrs = keys) + + def circulate(self, direction, onerror = None): + request.CirculateWindow(display = self.display, + onerror = onerror, + direction = direction, + window = self.id) + + def raise_window(self, onerror = None): + """alias for raising the window to the top - as in XRaiseWindow""" + self.configure(onerror, stack_mode = X.Above) + + def query_tree(self): + return request.QueryTree(display = self.display, + window = self.id) + + def change_property(self, property, property_type, format, data, + mode = X.PropModeReplace, onerror = None): + + request.ChangeProperty(display = self.display, + onerror = onerror, + mode = mode, + window = self.id, + property = property, + type = property_type, + data = (format, data)) + + def change_text_property(self, property, property_type, data, + mode = X.PropModeReplace, onerror = None): + if not isinstance(data, bytes): + if property_type == Xatom.STRING: + data = data.encode(self._STRING_ENCODING) + elif property_type == self.display.get_atom('UTF8_STRING'): + data = data.encode(self._UTF8_STRING_ENCODING) + self.change_property(property, property_type, 8, data, + mode=mode, onerror=onerror) + + def delete_property(self, property, onerror = None): + request.DeleteProperty(display = self.display, + onerror = onerror, + window = self.id, + property = property) + + def get_property(self, property, property_type, offset, length, delete = False): + r = request.GetProperty(display = self.display, + delete = delete, + window = self.id, + property = property, + type = property_type, + long_offset = offset, + long_length = length) + + if r.property_type: + fmt, value = r.value + r.format = fmt + r.value = value + return r + else: + return None + + def get_full_property(self, property, property_type, sizehint = 10): + prop = self.get_property(property, property_type, 0, sizehint) + if prop: + val = prop.value + if prop.bytes_after: + prop = self.get_property(property, property_type, sizehint, + prop.bytes_after // 4 + 1) + val = val + prop.value + + prop.value = val + return prop + else: + return None + + def get_full_text_property(self, property, property_type=X.AnyPropertyType, sizehint = 10): + prop = self.get_full_property(property, property_type, + sizehint=sizehint) + if prop is None or prop.format != 8: + return None + if prop.property_type == Xatom.STRING: + prop.value = prop.value.decode(self._STRING_ENCODING) + elif prop.property_type == self.display.get_atom('UTF8_STRING'): + prop.value = prop.value.decode(self._UTF8_STRING_ENCODING) + # FIXME: at least basic support for compound text would be nice. + # elif prop.property_type == self.display.get_atom('COMPOUND_TEXT'): + return prop.value + + def list_properties(self): + r = request.ListProperties(display = self.display, + window = self.id) + return r.atoms + + def set_selection_owner(self, selection, time, onerror = None): + request.SetSelectionOwner(display = self.display, + onerror = onerror, + window = self.id, + selection = selection, + time = time) + + def convert_selection(self, selection, target, property, time, onerror = None): + request.ConvertSelection(display = self.display, + onerror = onerror, + requestor = self.id, + selection = selection, + target = target, + property = property, + time = time) + + def send_event(self, event, event_mask = 0, propagate = False, onerror = None): + request.SendEvent(display = self.display, + onerror = onerror, + propagate = propagate, + destination = self.id, + event_mask = event_mask, + event = event) + + def grab_pointer(self, owner_events, event_mask, + pointer_mode, keyboard_mode, + confine_to, cursor, time): + + r = request.GrabPointer(display = self.display, + owner_events = owner_events, + grab_window = self.id, + event_mask = event_mask, + pointer_mode = pointer_mode, + keyboard_mode = keyboard_mode, + confine_to = confine_to, + cursor = cursor, + time = time) + return r.status + + def grab_button(self, button, modifiers, owner_events, event_mask, + pointer_mode, keyboard_mode, + confine_to, cursor, onerror = None): + + request.GrabButton(display = self.display, + onerror = onerror, + owner_events = owner_events, + grab_window = self.id, + event_mask = event_mask, + pointer_mode = pointer_mode, + keyboard_mode = keyboard_mode, + confine_to = confine_to, + cursor = cursor, + button = button, + modifiers = modifiers) + + def ungrab_button(self, button, modifiers, onerror = None): + request.UngrabButton(display = self.display, + onerror = onerror, + button = button, + grab_window = self.id, + modifiers = modifiers) + + + def grab_keyboard(self, owner_events, pointer_mode, keyboard_mode, time): + r = request.GrabKeyboard(display = self.display, + owner_events = owner_events, + grab_window = self.id, + time = time, + pointer_mode = pointer_mode, + keyboard_mode = keyboard_mode) + + return r.status + + def grab_key(self, key, modifiers, owner_events, pointer_mode, keyboard_mode, onerror = None): + request.GrabKey(display = self.display, + onerror = onerror, + owner_events = owner_events, + grab_window = self.id, + modifiers = modifiers, + key = key, + pointer_mode = pointer_mode, + keyboard_mode = keyboard_mode) + + def ungrab_key(self, key, modifiers, onerror = None): + request.UngrabKey(display = self.display, + onerror = onerror, + key = key, + grab_window = self.id, + modifiers = modifiers) + + def query_pointer(self): + return request.QueryPointer(display = self.display, + window = self.id) + + def get_motion_events(self, start, stop): + r = request.GetMotionEvents(display = self.display, + window = self.id, + start = start, + stop = stop) + return r.events + + def translate_coords(self, src_window, src_x, src_y): + return request.TranslateCoords(display = self.display, + src_wid = src_window, + dst_wid = self.id, + src_x = src_x, + src_y = src_y) + + def warp_pointer(self, x, y, src_window = 0, src_x = 0, src_y = 0, + src_width = 0, src_height = 0, onerror = None): + + request.WarpPointer(display = self.display, + onerror = onerror, + src_window = src_window, + dst_window = self.id, + src_x = src_x, + src_y = src_y, + src_width = src_width, + src_height = src_height, + dst_x = x, + dst_y = y) + + def set_input_focus(self, revert_to, time, onerror = None): + request.SetInputFocus(display = self.display, + onerror = onerror, + revert_to = revert_to, + focus = self.id, + time = time) + + def clear_area(self, x = 0, y = 0, width = 0, height = 0, exposures = False, onerror = None): + request.ClearArea(display = self.display, + onerror = onerror, + exposures = exposures, + window = self.id, + x = x, + y = y, + width = width, + height = height) + + def create_colormap(self, visual, alloc): + mid = self.display.allocate_resource_id() + request.CreateColormap(display = self.display, + alloc = alloc, + mid = mid, + window = self.id, + visual = visual) + cls = self.display.get_resource_class('colormap', colormap.Colormap) + return cls(self.display, mid, owner = 1) + + def list_installed_colormaps(self): + r = request.ListInstalledColormaps(display = self.display, + window = self.id) + return r.cmaps + + def rotate_properties(self, properties, delta, onerror = None): + request.RotateProperties(display = self.display, + onerror = onerror, + window = self.id, + delta = delta, + properties = properties) + + def set_wm_name(self, name, onerror = None): + self.change_text_property(Xatom.WM_NAME, Xatom.STRING, name, + onerror = onerror) + + def get_wm_name(self): + return self.get_full_text_property(Xatom.WM_NAME, Xatom.STRING) + + def set_wm_icon_name(self, name, onerror = None): + self.change_text_property(Xatom.WM_ICON_NAME, Xatom.STRING, name, + onerror = onerror) + + def get_wm_icon_name(self): + return self.get_full_text_property(Xatom.WM_ICON_NAME, Xatom.STRING) + + def set_wm_class(self, inst, cls, onerror = None): + self.change_text_property(Xatom.WM_CLASS, Xatom.STRING, + '%s\0%s\0' % (inst, cls), + onerror = onerror) + + def get_wm_class(self): + value = self.get_full_text_property(Xatom.WM_CLASS, Xatom.STRING) + if value is None: + return None + parts = value.split('\0') + if len(parts) < 2: + return None + else: + return parts[0], parts[1] + + def set_wm_transient_for(self, window, onerror = None): + self.change_property(Xatom.WM_TRANSIENT_FOR, Xatom.WINDOW, + 32, [window.id], + onerror = onerror) + + def get_wm_transient_for(self): + d = self.get_property(Xatom.WM_TRANSIENT_FOR, Xatom.WINDOW, 0, 1) + if d is None or d.format != 32 or len(d.value) < 1: + return None + else: + cls = self.display.get_resource_class('window', Window) + return cls(self.display, d.value[0]) + + + def set_wm_protocols(self, protocols, onerror = None): + self.change_property(self.display.get_atom('WM_PROTOCOLS'), + Xatom.ATOM, 32, protocols, + onerror = onerror) + + def get_wm_protocols(self): + d = self.get_full_property(self.display.get_atom('WM_PROTOCOLS'), Xatom.ATOM) + if d is None or d.format != 32: + return [] + else: + return d.value + + def set_wm_colormap_windows(self, windows, onerror = None): + self.change_property(self.display.get_atom('WM_COLORMAP_WINDOWS'), + Xatom.WINDOW, 32, + map(lambda w: w.id, windows), + onerror = onerror) + + def get_wm_colormap_windows(self): + d = self.get_full_property(self.display.get_atom('WM_COLORMAP_WINDOWS'), + Xatom.WINDOW) + if d is None or d.format != 32: + return [] + else: + cls = self.display.get_resource_class('window', Window) + return map(lambda i, d = self.display, c = cls: c(d, i), + d.value) + + + def set_wm_client_machine(self, name, onerror = None): + self.change_text_property(Xatom.WM_CLIENT_MACHINE, Xatom.STRING, name, + onerror = onerror) + + def get_wm_client_machine(self): + return self.get_full_text_property(Xatom.WM_CLIENT_MACHINE, Xatom.STRING) + + def set_wm_normal_hints(self, hints = {}, onerror = None, **keys): + self._set_struct_prop(Xatom.WM_NORMAL_HINTS, Xatom.WM_SIZE_HINTS, + icccm.WMNormalHints, hints, keys, onerror) + + def get_wm_normal_hints(self): + return self._get_struct_prop(Xatom.WM_NORMAL_HINTS, Xatom.WM_SIZE_HINTS, + icccm.WMNormalHints) + + def set_wm_hints(self, hints = {}, onerror = None, **keys): + self._set_struct_prop(Xatom.WM_HINTS, Xatom.WM_HINTS, + icccm.WMHints, hints, keys, onerror) + + def get_wm_hints(self): + return self._get_struct_prop(Xatom.WM_HINTS, Xatom.WM_HINTS, + icccm.WMHints) + + def set_wm_state(self, hints = {}, onerror = None, **keys): + atom = self.display.get_atom('WM_STATE') + self._set_struct_prop(atom, atom, icccm.WMState, hints, keys, onerror) + + def get_wm_state(self): + atom = self.display.get_atom('WM_STATE') + return self._get_struct_prop(atom, atom, icccm.WMState) + + def set_wm_icon_size(self, hints = {}, onerror = None, **keys): + self._set_struct_prop(Xatom.WM_ICON_SIZE, Xatom.WM_ICON_SIZE, + icccm.WMIconSize, hints, keys, onerror) + + def get_wm_icon_size(self): + return self._get_struct_prop(Xatom.WM_ICON_SIZE, Xatom.WM_ICON_SIZE, + icccm.WMIconSize) + + # Helper function for getting structured properties. + # pname and ptype are atoms, and pstruct is a Struct object. + # Returns a DictWrapper, or None + + def _get_struct_prop(self, pname, ptype, pstruct): + r = self.get_property(pname, ptype, 0, pstruct.static_size // 4) + if r and r.format == 32: + value = rq.encode_array(r.value) + if len(value) == pstruct.static_size: + return pstruct.parse_binary(value, self.display)[0] + + return None + + # Helper function for setting structured properties. + # pname and ptype are atoms, and pstruct is a Struct object. + # hints is a mapping or a DictWrapper, keys is a mapping. keys + # will be modified. onerror is the error handler. + + def _set_struct_prop(self, pname, ptype, pstruct, hints, keys, onerror): + if isinstance(hints, rq.DictWrapper): + keys.update(hints._data) + else: + keys.update(hints) + + value = pstruct.to_binary(*(), **keys) + + self.change_property(pname, ptype, 32, value, onerror = onerror) + + +class Pixmap(Drawable): + __pixmap__ = resource.Resource.__resource__ + + def free(self, onerror = None): + request.FreePixmap(display = self.display, + onerror = onerror, + pixmap = self.id) + + self.display.free_resource_id(self.id) + + def create_cursor(self, mask, foreground, background, x, y): + fore_red, fore_green, fore_blue = foreground + back_red, back_green, back_blue = background + cid = self.display.allocate_resource_id() + request.CreateCursor(display = self.display, + cid = cid, + source = self.id, + mask = mask, + fore_red = fore_red, + fore_green = fore_green, + fore_blue = fore_blue, + back_red = back_red, + back_green = back_green, + back_blue = back_blue, + x = x, + y = y) + cls = self.display.get_resource_class('cursor', cursor.Cursor) + return cls(self.display, cid, owner = 1) + + +def roundup(value, unit): + return (value + (unit - 1)) & ~(unit - 1) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/fontable.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/fontable.py new file mode 100644 index 0000000..4a33890 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/fontable.py @@ -0,0 +1,110 @@ +# Xlib.xobject.fontable -- fontable objects (GC, font) +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib.protocol import request + +from . import resource +from . import cursor + +class Fontable(resource.Resource): + __fontable__ = resource.Resource.__resource__ + + def query(self): + return request.QueryFont(display = self.display, + font = self.id) + + def query_text_extents(self, string): + return request.QueryTextExtents(display = self.display, + font = self.id, + string = string) + + +class GC(Fontable): + __gc__ = resource.Resource.__resource__ + + def change(self, onerror = None, **keys): + request.ChangeGC(display = self.display, + onerror = onerror, + gc = self.id, + attrs = keys) + + + def copy(self, src_gc, mask, onerror = None): + request.CopyGC(display = self.display, + onerror = onerror, + src_gc = src_gc, + dst_gc = self.id, + mask = mask) + + def set_dashes(self, offset, dashes, onerror = None): + request.SetDashes(display = self.display, + onerror = onerror, + gc = self.id, + dash_offset = offset, + dashes = dashes) + + def set_clip_rectangles(self, x_origin, y_origin, rectangles, ordering, onerror = None): + request.SetClipRectangles(display = self.display, + onerror = onerror, + ordering = ordering, + gc = self.id, + x_origin = x_origin, + y_origin = y_origin, + rectangles = rectangles) + def free(self, onerror = None): + request.FreeGC(display = self.display, + onerror = onerror, + gc = self.id) + + self.display.free_resource_id(self.id) + + + +class Font(Fontable): + __font__ = resource.Resource.__resource__ + + def close(self, onerror = None): + request.CloseFont(display = self.display, + onerror = onerror, + font = self.id) + self.display.free_resource_id(self.id) + + def create_glyph_cursor(self, mask, source_char, mask_char, + foreground, background): + fore_red, fore_green, fore_blue = foreground + back_red, back_green, back_blue = background + + cid = self.display.allocate_resource_id() + request.CreateGlyphCursor(display = self.display, + cid = cid, + source = self.id, + mask = mask, + source_char = source_char, + mask_char = mask_char, + fore_red = fore_red, + fore_green = fore_green, + fore_blue = fore_blue, + back_red = back_red, + back_green = back_green, + back_blue = back_blue) + + cls = self.display.get_resource_class('cursor', cursor.Cursor) + return cls(self.display, cid, owner = 1) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/icccm.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/icccm.py new file mode 100644 index 0000000..a328925 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/icccm.py @@ -0,0 +1,75 @@ +# Xlib.xobject.icccm -- ICCCM structures +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib import X, Xutil +from Xlib.protocol import rq + +Aspect = rq.Struct( rq.Int32('num'), rq.Int32('denum') ) + +WMNormalHints = rq.Struct( rq.Card32('flags'), + rq.Pad(16), + rq.Int32('min_width', default = 0), + rq.Int32('min_height', default = 0), + rq.Int32('max_width', default = 0), + rq.Int32('max_height', default = 0), + rq.Int32('width_inc', default = 0), + rq.Int32('height_inc', default = 0), + rq.Object('min_aspect', Aspect, default = (0, 0)), + rq.Object('max_aspect', Aspect, default = (0, 0)), + rq.Int32('base_width', default = 0), + rq.Int32('base_height', default = 0), + rq.Int32('win_gravity', default = 0), + ) + +WMHints = rq.Struct( rq.Card32('flags'), + rq.Card32('input', default = 0), + rq.Set('initial_state', 4, + # withdrawn is totally bogus according to + # ICCCM, but some window managers seem to + # use this value to identify dockapps. + # Oh well. + ( Xutil.WithdrawnState, + Xutil.NormalState, + Xutil.IconicState ), + default = Xutil.NormalState), + rq.Pixmap('icon_pixmap', default = 0), + rq.Window('icon_window', default = 0), + rq.Int32('icon_x', default = 0), + rq.Int32('icon_y', default = 0), + rq.Pixmap('icon_mask', default = 0), + rq.Window('window_group', default = 0), + ) + +WMState = rq.Struct( rq.Set('state', 4, + ( Xutil.WithdrawnState, + Xutil.NormalState, + Xutil.IconicState )), + rq.Window('icon', ( X.NONE, )), + ) + + +WMIconSize = rq.Struct( rq.Card32('min_width'), + rq.Card32('min_height'), + rq.Card32('max_width'), + rq.Card32('max_height'), + rq.Card32('width_inc'), + rq.Card32('height_inc'), + ) diff --git a/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/resource.py b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/resource.py new file mode 100644 index 0000000..460b1f0 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/Xlib/xobject/resource.py @@ -0,0 +1,54 @@ +# Xlib.xobject.resource -- any X resource object +# +# Copyright (C) 2000 Peter Liljenberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 59 Temple Place, +# Suite 330, +# Boston, MA 02111-1307 USA + +from Xlib.protocol import request + +class Resource(object): + def __init__(self, display, rid, owner = 0): + self.display = display + self.id = rid + self.owner = owner + + def __resource__(self): + return self.id + + def __eq__(self, obj): + if isinstance(obj, Resource): + if self.display == obj.display: + return self.id == obj.id + else: + return False + else: + return id(self) == id(obj) + + def __ne__(self, obj): + return not self == obj + + def __hash__(self): + return int(self.id) + + def __repr__(self): + return '<%s 0x%08x>' % (self.__class__.__name__, self.id) + + def kill_client(self, onerror = None): + request.KillClient(display = self.display, + onerror = onerror, + resource = self.id) diff --git a/CLI/venv/lib/python3.12/site-packages/__pycache__/six.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/__pycache__/six.cpython-312.pyc new file mode 100644 index 0000000..d775edc Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/__pycache__/six.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/INSTALLER b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/METADATA b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/METADATA new file mode 100644 index 0000000..f78425a --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/METADATA @@ -0,0 +1,97 @@ +Metadata-Version: 2.4 +Name: argumentparser +Version: 1.2.1 +Summary: Python 2/3 compatible commandline argument parser +Author: Tim Savannah +Author-email: kata198@gmail.com +Maintainer: Tim Savannah +Maintainer-email: kata198@gmail.com +License: LGPLv3 +Keywords: argument parser,argumentparser,argument,parser,argv,sys.argv,commandline,cmd,args +Classifier: Development Status :: 5 - Production/Stable +Classifier: Programming Language :: Python +Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: keywords +Dynamic: license +Dynamic: maintainer +Dynamic: maintainer-email +Dynamic: summary + + +A utility class for parsing command-line arguments. + +Constructor: + + | @param names list - This is a list of "names" which should reflect each argument. + | @param shortOptions list - This is a list of short (-x val) options. Length should match names. If no short option is available, use 'None'. Omit the leading - + | @param longOptions list - This is a list of long (--xyz val or --xyz= val) options. If no long option is available, use 'None'. Omit the leading -- + | @param staticOptions list - This is a list of static options (arguments that have meaning just being present, without taking an additional value). + | Any members of this list will be present in the results of #parse, set to True is present, otherwise False. + | @param multipleStaticOptions - A dictionary for multiple static arguments that resolve to one value. Key is the "name", values are all potential values. Ex: {'cheese' : ['--cheddar', 'gouda'] } presence of either 'gouda' or '--cheddar' in results would set cheese to True, otherwise False. + | @param allowOtherArguments default False - if False, consider non-specified arguments as errors. Regardless of value, unmatched params will be in 'unmatched' key of return value. + +Functions: + + | def parse(args) + | parse - Parses provided arguments and returns information on them. If using sys.argv, omit the first argument. + + | @return - dict keys are + | 'result' => dictionary of result name->value + | 'errors' => list of strings of errors or empty list + | 'warnings' => list of strings of warnings, or empty list + | 'unmatched' => list of strings of unmatched params, in order + +Example: + + | In [1]: from ArgumentParser import ArgumentParser + | In [2]: parser = ArgumentParser(['firstName', 'lastName', 'birthday'], + | ...: ['f', 'l', 'b'], + | ...: ['first-name', 'last-name', 'birthday'], + | ...: ['--citizen'] + | ) + | + | In [3]: parser.parse('-f Tim --last-name=savannah --birthday 6/28'.split(' ')) + | Out[3]: + | {'errors': [], + | 'result': {'--citizen': False, + | 'birthday': '6/28', + | 'firstName': 'Tim', + | 'lastName': 'savannah'}, + | 'warnings': [], + | 'unmatched' : []} + | + | In [4]: parser.parse('-f Tim --last-name=savannah --citizen'.split(' ')) + | Out[4]: + | {'errors': [], + | 'result': {'--citizen': True, 'firstName': 'Tim', 'lastName': 'savannah'}, + | 'warnings': [], + | 'unmatched': []} + +Example2: + + | >>> from ArgumentParser import ArgumentParser + | >>> parser = ArgumentParser(['name'], ['n'], ['name'], None, False) + | >>> parser.parse('-n hello some other args'.split(' ')) + | {'errors': ["Unknown argument 'some' (at position 2)", "Unknown argument 'other' (at position 3)", "Unknown argument 'args' (at position 4)"], 'result': {'name': 'hello'}, 'unmatched': ['some', 'other', 'args'], 'warnings': []} + | >>> parser = ArgumentParser(['name'], ['n'], ['name'], None, True) + | >>> parser.parse('-n hello some other args'.split(' ')) + | {'errors': [], 'result': {'name': 'hello'}, 'unmatched': ['some', 'other', 'args'], 'warnings': []} + +Example3: + + | >>> import ArgumentParser + | >>> parser = ArgumentParser.ArgumentParser( ('one', 'two'), ('o', 't'), ('uno', 'dos'), ('x'), {'cheese' : ['cheddar', 'gouda'], 'baby' : {'child', 'infant'}} ) + | >>> parser.parse(['-o', '1', 'cheddar']) + | {'errors': [], 'result': {'baby': False, 'cheese': True, 'x': False, 'one': '1'}, 'unmatched': [], 'warnings': []} + diff --git a/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/RECORD b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/RECORD new file mode 100644 index 0000000..8ed7002 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/RECORD @@ -0,0 +1,8 @@ +ArgumentParser/__init__.py,sha256=-fR5C77JVecO_hP9wn83B2AoFFEEsQoH9nxy1XJ-rXc,6693 +ArgumentParser/__pycache__/__init__.cpython-312.pyc,, +argumentparser-1.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +argumentparser-1.2.1.dist-info/METADATA,sha256=cS5iYhVP0mnAv9wR5MNzVWs51TLS8Sp9ubjIdCVRRLc,4603 +argumentparser-1.2.1.dist-info/RECORD,, +argumentparser-1.2.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +argumentparser-1.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 +argumentparser-1.2.1.dist-info/top_level.txt,sha256=S_4po3BtGX5FpNaUyW2aepvzYtCMOQmj_NI6NyfwS18,15 diff --git a/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/REQUESTED b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/WHEEL b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/WHEEL new file mode 100644 index 0000000..e7fa31b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (80.9.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/top_level.txt b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/top_level.txt new file mode 100644 index 0000000..94e360d --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/argumentparser-1.2.1.dist-info/top_level.txt @@ -0,0 +1 @@ +ArgumentParser diff --git a/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/INSTALLER b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/METADATA b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/METADATA new file mode 100644 index 0000000..6eeadf9 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/METADATA @@ -0,0 +1,78 @@ +Metadata-Version: 2.4 +Name: evdev +Version: 1.9.2 +Summary: Bindings to the Linux input handling subsystem +Author-email: Georgi Valkov +Maintainer-email: Tobi +License: Copyright (c) 2012-2025 Georgi Valkov. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. Neither the name of author nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR + COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Project-URL: Homepage, https://github.com/gvalkov/python-evdev +Keywords: evdev,input,uinput +Classifier: Development Status :: 5 - Production/Stable +Classifier: Programming Language :: Python :: 3 +Classifier: Operating System :: POSIX :: Linux +Classifier: Intended Audience :: Developers +Classifier: Topic :: Software Development :: Libraries +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python :: Implementation :: CPython +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +License-File: LICENSE +Dynamic: license-file + +# evdev + +

+ pypi version + License + Packaging status +

+ +This package provides bindings to the generic input event interface in Linux. +The *evdev* interface serves the purpose of passing events generated in the +kernel directly to userspace through character devices that are typically +located in `/dev/input/`. + +This package also comes with bindings to *uinput*, the userspace input +subsystem. *Uinput* allows userspace programs to create and handle input devices +that can inject events directly into the input subsystem. + +***Documentation:*** +https://python-evdev.readthedocs.io/en/latest/ + +***Development:*** +https://github.com/gvalkov/python-evdev + +***Package:*** +https://pypi.python.org/pypi/evdev + +***Changelog:*** +https://python-evdev.readthedocs.io/en/latest/changelog.html diff --git a/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/RECORD b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/RECORD new file mode 100644 index 0000000..3264e4f --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/RECORD @@ -0,0 +1,38 @@ +evdev-1.9.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +evdev-1.9.2.dist-info/METADATA,sha256=SFlJ2PoLjy17pdWwoYfIG4NuNvjRVyuSDDa1jeOpz8Y,3700 +evdev-1.9.2.dist-info/RECORD,, +evdev-1.9.2.dist-info/WHEEL,sha256=6TsICjgOR7isz_jYr-ssV7RSRmh1_0Z7_b5ESlzfzVY,104 +evdev-1.9.2.dist-info/licenses/LICENSE,sha256=1FVJYNZJYVDIjB_QLXlzEhqaV7lh6lj-NJ-_ito4FrI,1507 +evdev-1.9.2.dist-info/top_level.txt,sha256=tgRM-peDJTah3Is39Micsqkx31ek4FTHG4usyN23Xsk,6 +evdev/__init__.py,sha256=cu0Qu3CK4loreHKefFqudMmHQP-P-rkXSjrzjxHUCbw,1011 +evdev/__pycache__/__init__.cpython-312.pyc,, +evdev/__pycache__/device.cpython-312.pyc,, +evdev/__pycache__/ecodes.cpython-312.pyc,, +evdev/__pycache__/ecodes_runtime.cpython-312.pyc,, +evdev/__pycache__/eventio.cpython-312.pyc,, +evdev/__pycache__/eventio_async.cpython-312.pyc,, +evdev/__pycache__/events.cpython-312.pyc,, +evdev/__pycache__/evtest.cpython-312.pyc,, +evdev/__pycache__/ff.cpython-312.pyc,, +evdev/__pycache__/genecodes_c.cpython-312.pyc,, +evdev/__pycache__/genecodes_py.cpython-312.pyc,, +evdev/__pycache__/uinput.cpython-312.pyc,, +evdev/__pycache__/util.cpython-312.pyc,, +evdev/_ecodes.cpython-312-x86_64-linux-gnu.so,sha256=JkDf05hHVtLHsFxnBCobL_p6m2Zf1-SDRHhSMZ0oY2I,86304 +evdev/_input.cpython-312-x86_64-linux-gnu.so,sha256=f1GoZ6TGw851VjD5gukUnC4jdBKrygQ72Lbmwg08_f0,51824 +evdev/_uinput.cpython-312-x86_64-linux-gnu.so,sha256=bdxkVZ9XF2Gg5LB9byH-uQgStXixFvNe0OHHcuW5KAM,37352 +evdev/device.py,sha256=8sKHGmZh3DF1lJpsIy0pF1R9L5qGzazFGretaysu1Os,12959 +evdev/ecodes.py,sha256=_AVTtsN9w5f4M74FQgbxwAQPOedmCqVts0TCX4AE6Yw,98110 +evdev/ecodes_runtime.py,sha256=_QR3aSjX3pbwrk0f1dA-tXjiECKtV_uPpUtXpWP_cTI,2838 +evdev/eventio.py,sha256=4SnIINjPJadQChUEy_1lbTzuTORsydDC7zL2qkegTIY,4422 +evdev/eventio_async.py,sha256=B1qaEKYoiiop8YpG0AFf0lu2Im3CvW50dRPLug40xWA,3078 +evdev/events.py,sha256=_0vXzjv8yFtJR9drfwhmBZl9w4ZmfwQhgCo3WcrWi-Q,5905 +evdev/evtest.py,sha256=u0umJIV_HQUDlbBhLvXEKZ87UZqNIhk0XJRcm5VYIzg,5543 +evdev/ff.py,sha256=1B1VJ8TJ_CpJ01Qi4tUym1p8qZK_HKQSZvvhA8ROoJY,4961 +evdev/genecodes_c.py,sha256=_AhMK1iOQlkykOSzkbCbCJfZTk_dDU-jLsL_7FhYUqM,3618 +evdev/genecodes_py.py,sha256=-FuU-qy4-C_q7xkSwJICwMbCmAxyvezwSU4L2SRqwAs,1996 +evdev/input.c,sha256=omyOdIW51ZwmbcEGYO5_0viY93BX5AYaQ4PQS7s3z1E,16061 +evdev/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +evdev/uinput.c,sha256=9CkdJwL57R-qxaBS3T6vCJq9rC2KrRQK7BTHforK4XI,10188 +evdev/uinput.py,sha256=vJb5E0ThptDo6HeB0mc74zFXkh3_oW7a5amn-jhWo9U,13363 +evdev/util.py,sha256=WzgxwgjBuCE25n6UNPk91Bg2_j6weGUv1VO3vfyX8xU,4409 diff --git a/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/WHEEL b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/WHEEL new file mode 100644 index 0000000..8de3dd0 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (80.9.0) +Root-Is-Purelib: false +Tag: cp312-cp312-linux_x86_64 + diff --git a/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/licenses/LICENSE b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/licenses/LICENSE new file mode 100644 index 0000000..8482b07 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/licenses/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2012-2025 Georgi Valkov. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. Neither the name of author nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/top_level.txt b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/top_level.txt new file mode 100644 index 0000000..97a5e58 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev-1.9.2.dist-info/top_level.txt @@ -0,0 +1 @@ +evdev diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__init__.py b/CLI/venv/lib/python3.12/site-packages/evdev/__init__.py new file mode 100644 index 0000000..bae0fec --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/__init__.py @@ -0,0 +1,39 @@ +# -------------------------------------------------------------------------- +# Gather everything into a single, convenient namespace. +# -------------------------------------------------------------------------- + +# The superfluous "import name as name" syntax is here to satisfy mypy's attrs-defined rule. +# Alternatively all exported objects can be listed in __all__. + +from . import ( + ecodes as ecodes, + ff as ff, +) + +from .device import ( + AbsInfo as AbsInfo, + DeviceInfo as DeviceInfo, + EvdevError as EvdevError, + InputDevice as InputDevice, +) + +from .events import ( + AbsEvent as AbsEvent, + InputEvent as InputEvent, + KeyEvent as KeyEvent, + RelEvent as RelEvent, + SynEvent as SynEvent, + event_factory as event_factory, +) + +from .uinput import ( + UInput as UInput, + UInputError as UInputError, +) + +from .util import ( + categorize as categorize, + list_devices as list_devices, + resolve_ecodes as resolve_ecodes, + resolve_ecodes_dict as resolve_ecodes_dict, +) diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..40658da Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/device.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/device.cpython-312.pyc new file mode 100644 index 0000000..77a8f7a Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/device.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ecodes.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ecodes.cpython-312.pyc new file mode 100644 index 0000000..9e98e8e Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ecodes.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ecodes_runtime.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ecodes_runtime.cpython-312.pyc new file mode 100644 index 0000000..9e616a3 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ecodes_runtime.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/eventio.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/eventio.cpython-312.pyc new file mode 100644 index 0000000..8380e3d Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/eventio.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/eventio_async.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/eventio_async.cpython-312.pyc new file mode 100644 index 0000000..2d995e1 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/eventio_async.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/events.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/events.cpython-312.pyc new file mode 100644 index 0000000..22db36a Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/events.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/evtest.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/evtest.cpython-312.pyc new file mode 100644 index 0000000..36c5d06 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/evtest.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ff.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ff.cpython-312.pyc new file mode 100644 index 0000000..1c767de Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/ff.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/genecodes_c.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/genecodes_c.cpython-312.pyc new file mode 100644 index 0000000..c6f93c0 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/genecodes_c.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/genecodes_py.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/genecodes_py.cpython-312.pyc new file mode 100644 index 0000000..be3b365 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/genecodes_py.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/uinput.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/uinput.cpython-312.pyc new file mode 100644 index 0000000..6e118c6 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/uinput.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/util.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000..54007b4 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/__pycache__/util.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/_ecodes.cpython-312-x86_64-linux-gnu.so b/CLI/venv/lib/python3.12/site-packages/evdev/_ecodes.cpython-312-x86_64-linux-gnu.so new file mode 100755 index 0000000..b8d03dc Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/_ecodes.cpython-312-x86_64-linux-gnu.so differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/_input.cpython-312-x86_64-linux-gnu.so b/CLI/venv/lib/python3.12/site-packages/evdev/_input.cpython-312-x86_64-linux-gnu.so new file mode 100755 index 0000000..05dda82 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/_input.cpython-312-x86_64-linux-gnu.so differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/_uinput.cpython-312-x86_64-linux-gnu.so b/CLI/venv/lib/python3.12/site-packages/evdev/_uinput.cpython-312-x86_64-linux-gnu.so new file mode 100755 index 0000000..495f87e Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/evdev/_uinput.cpython-312-x86_64-linux-gnu.so differ diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/device.py b/CLI/venv/lib/python3.12/site-packages/evdev/device.py new file mode 100644 index 0000000..a7f9b92 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/device.py @@ -0,0 +1,440 @@ +import contextlib +import os +from typing import Dict, Generic, Iterator, List, Literal, NamedTuple, Tuple, TypeVar, Union, overload + +from . import _input, ecodes, util + +try: + from .eventio_async import EvdevError, EventIO +except ImportError: + from .eventio import EvdevError, EventIO + +_AnyStr = TypeVar("_AnyStr", str, bytes) + + +class AbsInfo(NamedTuple): + """Absolute axis information. + + A ``namedtuple`` with absolute axis information - + corresponds to the ``input_absinfo`` struct: + + Attributes + --------- + value + Latest reported value for the axis. + + min + Specifies minimum value for the axis. + + max + Specifies maximum value for the axis. + + fuzz + Specifies fuzz value that is used to filter noise from the + event stream. + + flat + Values that are within this value will be discarded by joydev + interface and reported as 0 instead. + + resolution + Specifies resolution for the values reported for the axis. + Resolution for main axes (``ABS_X, ABS_Y, ABS_Z``) is reported + in units per millimeter (units/mm), resolution for rotational + axes (``ABS_RX, ABS_RY, ABS_RZ``) is reported in units per + radian. + + Note + ---- + The input core does not clamp reported values to the ``[minimum, + maximum]`` limits, such task is left to userspace. + + """ + + value: int + min: int + max: int + fuzz: int + flat: int + resolution: int + + def __str__(self): + return "value {}, min {}, max {}, fuzz {}, flat {}, res {}".format(*self) # pylint: disable=not-an-iterable + + +class KbdInfo(NamedTuple): + """Keyboard repeat rate. + + Attributes + ---------- + delay + Amount of time that a key must be depressed before it will start + to repeat (in milliseconds). + + repeat + Keyboard repeat rate in characters per second. + """ + + delay: int + repeat: int + + def __str__(self): + return "delay {}, repeat {}".format(self.delay, self.repeat) + + +class DeviceInfo(NamedTuple): + """ + Attributes + ---------- + bustype + vendor + product + version + """ + + bustype: int + vendor: int + product: int + version: int + + def __str__(self) -> str: + msg = "bus: {:04x}, vendor {:04x}, product {:04x}, version {:04x}" + return msg.format(*self) # pylint: disable=not-an-iterable + + +class InputDevice(EventIO, Generic[_AnyStr]): + """ + A linux input device from which input events can be read. + """ + + __slots__ = ("path", "fd", "info", "name", "phys", "uniq", "_rawcapabilities", "version", "ff_effects_count") + + def __init__(self, dev: Union[_AnyStr, "os.PathLike[_AnyStr]"]): + """ + Arguments + --------- + dev : str|bytes|PathLike + Path to input device + """ + + #: Path to input device. + self.path: _AnyStr = dev if not hasattr(dev, "__fspath__") else dev.__fspath__() + + # Certain operations are possible only when the device is opened in read-write mode. + try: + fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK) + except OSError: + fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK) + + #: A non-blocking file descriptor to the device file. + self.fd: int = fd + + # Returns (bustype, vendor, product, version, name, phys, capabilities). + info_res = _input.ioctl_devinfo(self.fd) + + #: A :class:`DeviceInfo ` instance. + self.info = DeviceInfo(*info_res[:4]) + + #: The name of the event device. + self.name: str = info_res[4] + + #: The physical topology of the device. + self.phys: str = info_res[5] + + #: The unique identifier of the device. + self.uniq: str = info_res[6] + + #: The evdev protocol version. + self.version: int = _input.ioctl_EVIOCGVERSION(self.fd) + + #: The raw dictionary of device capabilities - see `:func:capabilities()`. + self._rawcapabilities = _input.ioctl_capabilities(self.fd) + + #: The number of force feedback effects the device can keep in its memory. + self.ff_effects_count = _input.ioctl_EVIOCGEFFECTS(self.fd) + + def __del__(self) -> None: + if hasattr(self, "fd") and self.fd is not None: + try: + self.close() + except (OSError, ImportError, AttributeError): + pass + + def _capabilities(self, absinfo: bool = True): + res = {} + + for etype, _ecodes in self._rawcapabilities.items(): + for code in _ecodes: + l = res.setdefault(etype, []) + if isinstance(code, tuple): + if absinfo: + a = code[1] # (0, 0, 0, 255, 0, 0) + i = AbsInfo(*a) + l.append((code[0], i)) + else: + l.append(code[0]) + else: + l.append(code) + + return res + + @overload + def capabilities(self, verbose: Literal[False] = ..., absinfo: bool = ...) -> Dict[int, List[int]]: + ... + @overload + def capabilities(self, verbose: Literal[True], absinfo: bool = ...) -> Dict[Tuple[str, int], List[Tuple[str, int]]]: + ... + def capabilities(self, verbose: bool = False, absinfo: bool = True) -> Union[Dict[int, List[int]], Dict[Tuple[str, int], List[Tuple[str, int]]]]: + """ + Return the event types that this device supports as a mapping of + supported event types to lists of handled event codes. + + Example + -------- + >>> device.capabilities() + { 1: [272, 273, 274], + 2: [0, 1, 6, 8] } + + If ``verbose`` is ``True``, event codes and types will be resolved + to their names. + + :: + + { ('EV_KEY', 1): [('BTN_MOUSE', 272), + ('BTN_RIGHT', 273), + ('BTN_MIDDLE', 273)], + ('EV_REL', 2): [('REL_X', 0), + ('REL_Y', 1), + ('REL_HWHEEL', 6), + ('REL_WHEEL', 8)] } + + Unknown codes or types will be resolved to ``'?'``. + + If ``absinfo`` is ``True``, the list of capabilities will also + include absolute axis information in the form of + :class:`AbsInfo` instances:: + + { 3: [ (0, AbsInfo(min=0, max=255, fuzz=0, flat=0)), + (1, AbsInfo(min=0, max=255, fuzz=0, flat=0)) ]} + + Combined with ``verbose`` the above becomes:: + + { ('EV_ABS', 3): [ (('ABS_X', 0), AbsInfo(min=0, max=255, fuzz=0, flat=0)), + (('ABS_Y', 1), AbsInfo(min=0, max=255, fuzz=0, flat=0)) ]} + + """ + + if verbose: + return dict(util.resolve_ecodes_dict(self._capabilities(absinfo))) + else: + return self._capabilities(absinfo) + + def input_props(self, verbose: bool = False): + """ + Get device properties and quirks. + + Example + ------- + >>> device.input_props() + [0, 5] + + If ``verbose`` is ``True``, input properties are resolved to their + names. Unknown codes are resolved to ``'?'``:: + + [('INPUT_PROP_POINTER', 0), ('INPUT_PROP_POINTING_STICK', 5)] + + """ + props = _input.ioctl_EVIOCGPROP(self.fd) + if verbose: + return util.resolve_ecodes(ecodes.INPUT_PROP, props) + + return props + + def leds(self, verbose: bool = False): + """ + Return currently set LED keys. + + Example + ------- + >>> device.leds() + [0, 1, 8, 9] + + If ``verbose`` is ``True``, event codes are resolved to their + names. Unknown codes are resolved to ``'?'``:: + + [('LED_NUML', 0), ('LED_CAPSL', 1), ('LED_MISC', 8), ('LED_MAIL', 9)] + + """ + leds = _input.ioctl_EVIOCG_bits(self.fd, ecodes.EV_LED) + if verbose: + return util.resolve_ecodes(ecodes.LED, leds) + + return leds + + def set_led(self, led_num: int, value: int) -> None: + """ + Set the state of the selected LED. + + Example + ------- + >>> device.set_led(ecodes.LED_NUML, 1) + """ + self.write(ecodes.EV_LED, led_num, value) + + def __eq__(self, other): + """ + Two devices are equal if their :data:`info` attributes are equal. + """ + return isinstance(other, self.__class__) and self.info == other.info and self.path == other.path + + def __str__(self) -> str: + msg = 'device {}, name "{}", phys "{}", uniq "{}"' + return msg.format(self.path, self.name, self.phys, self.uniq or "") + + def __repr__(self) -> str: + msg = (self.__class__.__name__, self.path) + return "{}({!r})".format(*msg) + + def __fspath__(self): + return self.path + + def close(self) -> None: + if self.fd > -1: + try: + super().close() + os.close(self.fd) + finally: + self.fd = -1 + + def grab(self) -> None: + """ + Grab input device using ``EVIOCGRAB`` - other applications will + be unable to receive events until the device is released. Only + one process can hold a ``EVIOCGRAB`` on a device. + + Warning + ------- + Grabbing an already grabbed device will raise an ``OSError``. + """ + + _input.ioctl_EVIOCGRAB(self.fd, 1) + + def ungrab(self) -> None: + """ + Release device if it has been already grabbed (uses `EVIOCGRAB`). + + Warning + ------- + Releasing an already released device will raise an + ``OSError('Invalid argument')``. + """ + + _input.ioctl_EVIOCGRAB(self.fd, 0) + + @contextlib.contextmanager + def grab_context(self) -> Iterator[None]: + """ + A context manager for the duration of which only the current + process will be able to receive events from the device. + """ + self.grab() + yield + self.ungrab() + + def upload_effect(self, effect: "ff.Effect"): + """ + Upload a force feedback effect to a force feedback device. + """ + + data = memoryview(effect).tobytes() + ff_id = _input.upload_effect(self.fd, data) + return ff_id + + def erase_effect(self, ff_id) -> None: + """ + Erase a force effect from a force feedback device. This also + stops the effect. + """ + + _input.erase_effect(self.fd, ff_id) + + @property + def repeat(self): + """ + Get or set the keyboard repeat rate (in characters per + minute) and delay (in milliseconds). + """ + + return KbdInfo(*_input.ioctl_EVIOCGREP(self.fd)) + + @repeat.setter + def repeat(self, value: Tuple[int, int]): + return _input.ioctl_EVIOCSREP(self.fd, *value) + + def active_keys(self, verbose: bool = False): + """ + Return currently active keys. + + Example + ------- + + >>> device.active_keys() + [1, 42] + + If ``verbose`` is ``True``, key codes are resolved to their + verbose names. Unknown codes are resolved to ``'?'``. For + example:: + + [('KEY_ESC', 1), ('KEY_LEFTSHIFT', 42)] + + """ + active_keys = _input.ioctl_EVIOCG_bits(self.fd, ecodes.EV_KEY) + if verbose: + return util.resolve_ecodes(ecodes.KEY, active_keys) + + return active_keys + + def absinfo(self, axis_num: int): + """ + Return current :class:`AbsInfo` for input device axis + + Arguments + --------- + axis_num : int + EV_ABS keycode (example :attr:`ecodes.ABS_X`) + + Example + ------- + >>> device.absinfo(ecodes.ABS_X) + AbsInfo(value=1501, min=-32768, max=32767, fuzz=0, flat=128, resolution=0) + """ + return AbsInfo(*_input.ioctl_EVIOCGABS(self.fd, axis_num)) + + def set_absinfo(self, axis_num: int, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None) -> None: + """ + Update :class:`AbsInfo` values. Only specified values will be overwritten. + + Arguments + --------- + axis_num : int + EV_ABS keycode (example :attr:`ecodes.ABS_X`) + + Example + ------- + >>> device.set_absinfo(ecodes.ABS_X, min=-2000, max=2000) + + You can also unpack AbsInfo tuple that will overwrite all values + + >>> device.set_absinfo(ecodes.ABS_Y, *AbsInfo(0, -2000, 2000, 0, 15, 0)) + """ + + cur_absinfo = self.absinfo(axis_num) + new_absinfo = AbsInfo( + value if value is not None else cur_absinfo.value, + min if min is not None else cur_absinfo.min, + max if max is not None else cur_absinfo.max, + fuzz if fuzz is not None else cur_absinfo.fuzz, + flat if flat is not None else cur_absinfo.flat, + resolution if resolution is not None else cur_absinfo.resolution, + ) + _input.ioctl_EVIOCSABS(self.fd, axis_num, new_absinfo) diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/ecodes.py b/CLI/venv/lib/python3.12/site-packages/evdev/ecodes.py new file mode 100644 index 0000000..39cdcbd --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/ecodes.py @@ -0,0 +1,3885 @@ +# Automatically generated by evdev.genecodes_py + +""" +This modules exposes the integer constants defined in ``linux/input.h`` and +``linux/input-event-codes.h``. + +Exposed constants:: + + KEY, ABS, REL, SW, MSC, LED, BTN, REP, SND, ID, EV, + BUS, SYN, FF, FF_STATUS, INPUT_PROP + +This module also provides reverse and forward mappings of the names and values +of the above mentioned constants:: + + >>> evdev.ecodes.KEY_A + 30 + + >>> evdev.ecodes.ecodes['KEY_A'] + 30 + + >>> evdev.ecodes.KEY[30] + 'KEY_A' + + >>> evdev.ecodes.REL[0] + 'REL_X' + + >>> evdev.ecodes.EV[evdev.ecodes.EV_KEY] + 'EV_KEY' + + >>> evdev.ecodes.bytype[evdev.ecodes.EV_REL][0] + 'REL_X' + +Keep in mind that values in reverse mappings may point to one or more event +codes. For example:: + + >>> evdev.ecodes.FF[80] + ('FF_EFFECT_MIN', 'FF_RUMBLE') + + >>> evdev.ecodes.FF[81] + 'FF_PERIODIC' +""" + +from typing import Final, Dict, Tuple, Union + +ABS_BRAKE: Final[int] = 10 +ABS_CNT: Final[int] = 64 +ABS_DISTANCE: Final[int] = 25 +ABS_GAS: Final[int] = 9 +ABS_HAT0X: Final[int] = 16 +ABS_HAT0Y: Final[int] = 17 +ABS_HAT1X: Final[int] = 18 +ABS_HAT1Y: Final[int] = 19 +ABS_HAT2X: Final[int] = 20 +ABS_HAT2Y: Final[int] = 21 +ABS_HAT3X: Final[int] = 22 +ABS_HAT3Y: Final[int] = 23 +ABS_MAX: Final[int] = 63 +ABS_MISC: Final[int] = 40 +ABS_MT_BLOB_ID: Final[int] = 56 +ABS_MT_DISTANCE: Final[int] = 59 +ABS_MT_ORIENTATION: Final[int] = 52 +ABS_MT_POSITION_X: Final[int] = 53 +ABS_MT_POSITION_Y: Final[int] = 54 +ABS_MT_PRESSURE: Final[int] = 58 +ABS_MT_SLOT: Final[int] = 47 +ABS_MT_TOOL_TYPE: Final[int] = 55 +ABS_MT_TOOL_X: Final[int] = 60 +ABS_MT_TOOL_Y: Final[int] = 61 +ABS_MT_TOUCH_MAJOR: Final[int] = 48 +ABS_MT_TOUCH_MINOR: Final[int] = 49 +ABS_MT_TRACKING_ID: Final[int] = 57 +ABS_MT_WIDTH_MAJOR: Final[int] = 50 +ABS_MT_WIDTH_MINOR: Final[int] = 51 +ABS_PRESSURE: Final[int] = 24 +ABS_PROFILE: Final[int] = 33 +ABS_RESERVED: Final[int] = 46 +ABS_RUDDER: Final[int] = 7 +ABS_RX: Final[int] = 3 +ABS_RY: Final[int] = 4 +ABS_RZ: Final[int] = 5 +ABS_THROTTLE: Final[int] = 6 +ABS_TILT_X: Final[int] = 26 +ABS_TILT_Y: Final[int] = 27 +ABS_TOOL_WIDTH: Final[int] = 28 +ABS_VOLUME: Final[int] = 32 +ABS_WHEEL: Final[int] = 8 +ABS_X: Final[int] = 0 +ABS_Y: Final[int] = 1 +ABS_Z: Final[int] = 2 +BTN_0: Final[int] = 256 +BTN_1: Final[int] = 257 +BTN_2: Final[int] = 258 +BTN_3: Final[int] = 259 +BTN_4: Final[int] = 260 +BTN_5: Final[int] = 261 +BTN_6: Final[int] = 262 +BTN_7: Final[int] = 263 +BTN_8: Final[int] = 264 +BTN_9: Final[int] = 265 +BTN_A: Final[int] = 304 +BTN_B: Final[int] = 305 +BTN_BACK: Final[int] = 278 +BTN_BASE: Final[int] = 294 +BTN_BASE2: Final[int] = 295 +BTN_BASE3: Final[int] = 296 +BTN_BASE4: Final[int] = 297 +BTN_BASE5: Final[int] = 298 +BTN_BASE6: Final[int] = 299 +BTN_C: Final[int] = 306 +BTN_DEAD: Final[int] = 303 +BTN_DIGI: Final[int] = 320 +BTN_DPAD_DOWN: Final[int] = 545 +BTN_DPAD_LEFT: Final[int] = 546 +BTN_DPAD_RIGHT: Final[int] = 547 +BTN_DPAD_UP: Final[int] = 544 +BTN_EAST: Final[int] = 305 +BTN_EXTRA: Final[int] = 276 +BTN_FORWARD: Final[int] = 277 +BTN_GAMEPAD: Final[int] = 304 +BTN_GEAR_DOWN: Final[int] = 336 +BTN_GEAR_UP: Final[int] = 337 +BTN_JOYSTICK: Final[int] = 288 +BTN_LEFT: Final[int] = 272 +BTN_MIDDLE: Final[int] = 274 +BTN_MISC: Final[int] = 256 +BTN_MODE: Final[int] = 316 +BTN_MOUSE: Final[int] = 272 +BTN_NORTH: Final[int] = 307 +BTN_PINKIE: Final[int] = 293 +BTN_RIGHT: Final[int] = 273 +BTN_SELECT: Final[int] = 314 +BTN_SIDE: Final[int] = 275 +BTN_SOUTH: Final[int] = 304 +BTN_START: Final[int] = 315 +BTN_STYLUS: Final[int] = 331 +BTN_STYLUS2: Final[int] = 332 +BTN_STYLUS3: Final[int] = 329 +BTN_TASK: Final[int] = 279 +BTN_THUMB: Final[int] = 289 +BTN_THUMB2: Final[int] = 290 +BTN_THUMBL: Final[int] = 317 +BTN_THUMBR: Final[int] = 318 +BTN_TL: Final[int] = 310 +BTN_TL2: Final[int] = 312 +BTN_TOOL_AIRBRUSH: Final[int] = 324 +BTN_TOOL_BRUSH: Final[int] = 322 +BTN_TOOL_DOUBLETAP: Final[int] = 333 +BTN_TOOL_FINGER: Final[int] = 325 +BTN_TOOL_LENS: Final[int] = 327 +BTN_TOOL_MOUSE: Final[int] = 326 +BTN_TOOL_PEN: Final[int] = 320 +BTN_TOOL_PENCIL: Final[int] = 323 +BTN_TOOL_QUADTAP: Final[int] = 335 +BTN_TOOL_QUINTTAP: Final[int] = 328 +BTN_TOOL_RUBBER: Final[int] = 321 +BTN_TOOL_TRIPLETAP: Final[int] = 334 +BTN_TOP: Final[int] = 291 +BTN_TOP2: Final[int] = 292 +BTN_TOUCH: Final[int] = 330 +BTN_TR: Final[int] = 311 +BTN_TR2: Final[int] = 313 +BTN_TRIGGER: Final[int] = 288 +BTN_TRIGGER_HAPPY: Final[int] = 704 +BTN_TRIGGER_HAPPY1: Final[int] = 704 +BTN_TRIGGER_HAPPY10: Final[int] = 713 +BTN_TRIGGER_HAPPY11: Final[int] = 714 +BTN_TRIGGER_HAPPY12: Final[int] = 715 +BTN_TRIGGER_HAPPY13: Final[int] = 716 +BTN_TRIGGER_HAPPY14: Final[int] = 717 +BTN_TRIGGER_HAPPY15: Final[int] = 718 +BTN_TRIGGER_HAPPY16: Final[int] = 719 +BTN_TRIGGER_HAPPY17: Final[int] = 720 +BTN_TRIGGER_HAPPY18: Final[int] = 721 +BTN_TRIGGER_HAPPY19: Final[int] = 722 +BTN_TRIGGER_HAPPY2: Final[int] = 705 +BTN_TRIGGER_HAPPY20: Final[int] = 723 +BTN_TRIGGER_HAPPY21: Final[int] = 724 +BTN_TRIGGER_HAPPY22: Final[int] = 725 +BTN_TRIGGER_HAPPY23: Final[int] = 726 +BTN_TRIGGER_HAPPY24: Final[int] = 727 +BTN_TRIGGER_HAPPY25: Final[int] = 728 +BTN_TRIGGER_HAPPY26: Final[int] = 729 +BTN_TRIGGER_HAPPY27: Final[int] = 730 +BTN_TRIGGER_HAPPY28: Final[int] = 731 +BTN_TRIGGER_HAPPY29: Final[int] = 732 +BTN_TRIGGER_HAPPY3: Final[int] = 706 +BTN_TRIGGER_HAPPY30: Final[int] = 733 +BTN_TRIGGER_HAPPY31: Final[int] = 734 +BTN_TRIGGER_HAPPY32: Final[int] = 735 +BTN_TRIGGER_HAPPY33: Final[int] = 736 +BTN_TRIGGER_HAPPY34: Final[int] = 737 +BTN_TRIGGER_HAPPY35: Final[int] = 738 +BTN_TRIGGER_HAPPY36: Final[int] = 739 +BTN_TRIGGER_HAPPY37: Final[int] = 740 +BTN_TRIGGER_HAPPY38: Final[int] = 741 +BTN_TRIGGER_HAPPY39: Final[int] = 742 +BTN_TRIGGER_HAPPY4: Final[int] = 707 +BTN_TRIGGER_HAPPY40: Final[int] = 743 +BTN_TRIGGER_HAPPY5: Final[int] = 708 +BTN_TRIGGER_HAPPY6: Final[int] = 709 +BTN_TRIGGER_HAPPY7: Final[int] = 710 +BTN_TRIGGER_HAPPY8: Final[int] = 711 +BTN_TRIGGER_HAPPY9: Final[int] = 712 +BTN_WEST: Final[int] = 308 +BTN_WHEEL: Final[int] = 336 +BTN_X: Final[int] = 307 +BTN_Y: Final[int] = 308 +BTN_Z: Final[int] = 309 +BUS_ADB: Final[int] = 23 +BUS_AMD_SFH: Final[int] = 32 +BUS_AMIGA: Final[int] = 22 +BUS_ATARI: Final[int] = 27 +BUS_BLUETOOTH: Final[int] = 5 +BUS_CEC: Final[int] = 30 +BUS_GAMEPORT: Final[int] = 20 +BUS_GSC: Final[int] = 26 +BUS_HIL: Final[int] = 4 +BUS_HOST: Final[int] = 25 +BUS_I2C: Final[int] = 24 +BUS_I8042: Final[int] = 17 +BUS_INTEL_ISHTP: Final[int] = 31 +BUS_ISA: Final[int] = 16 +BUS_ISAPNP: Final[int] = 2 +BUS_PARPORT: Final[int] = 21 +BUS_PCI: Final[int] = 1 +BUS_RMI: Final[int] = 29 +BUS_RS232: Final[int] = 19 +BUS_SPI: Final[int] = 28 +BUS_USB: Final[int] = 3 +BUS_VIRTUAL: Final[int] = 6 +BUS_XTKBD: Final[int] = 18 +EV_ABS: Final[int] = 3 +EV_CNT: Final[int] = 32 +EV_FF: Final[int] = 21 +EV_FF_STATUS: Final[int] = 23 +EV_KEY: Final[int] = 1 +EV_LED: Final[int] = 17 +EV_MAX: Final[int] = 31 +EV_MSC: Final[int] = 4 +EV_PWR: Final[int] = 22 +EV_REL: Final[int] = 2 +EV_REP: Final[int] = 20 +EV_SND: Final[int] = 18 +EV_SW: Final[int] = 5 +EV_SYN: Final[int] = 0 +EV_UINPUT: Final[int] = 257 +EV_VERSION: Final[int] = 65537 +FF_AUTOCENTER: Final[int] = 97 +FF_CNT: Final[int] = 128 +FF_CONSTANT: Final[int] = 82 +FF_CUSTOM: Final[int] = 93 +FF_DAMPER: Final[int] = 85 +FF_EFFECT_MAX: Final[int] = 87 +FF_EFFECT_MIN: Final[int] = 80 +FF_FRICTION: Final[int] = 84 +FF_GAIN: Final[int] = 96 +FF_INERTIA: Final[int] = 86 +FF_MAX: Final[int] = 127 +FF_MAX_EFFECTS: Final[int] = 96 +FF_PERIODIC: Final[int] = 81 +FF_RAMP: Final[int] = 87 +FF_RUMBLE: Final[int] = 80 +FF_SAW_DOWN: Final[int] = 92 +FF_SAW_UP: Final[int] = 91 +FF_SINE: Final[int] = 90 +FF_SPRING: Final[int] = 83 +FF_SQUARE: Final[int] = 88 +FF_STATUS_MAX: Final[int] = 1 +FF_STATUS_PLAYING: Final[int] = 1 +FF_STATUS_STOPPED: Final[int] = 0 +FF_TRIANGLE: Final[int] = 89 +FF_WAVEFORM_MAX: Final[int] = 93 +FF_WAVEFORM_MIN: Final[int] = 88 +ID_BUS: Final[int] = 0 +ID_PRODUCT: Final[int] = 2 +ID_VENDOR: Final[int] = 1 +ID_VERSION: Final[int] = 3 +INPUT_PROP_ACCELEROMETER: Final[int] = 6 +INPUT_PROP_BUTTONPAD: Final[int] = 2 +INPUT_PROP_CNT: Final[int] = 32 +INPUT_PROP_DIRECT: Final[int] = 1 +INPUT_PROP_MAX: Final[int] = 31 +INPUT_PROP_POINTER: Final[int] = 0 +INPUT_PROP_POINTING_STICK: Final[int] = 5 +INPUT_PROP_SEMI_MT: Final[int] = 3 +INPUT_PROP_TOPBUTTONPAD: Final[int] = 4 +KEY_0: Final[int] = 11 +KEY_1: Final[int] = 2 +KEY_102ND: Final[int] = 86 +KEY_10CHANNELSDOWN: Final[int] = 441 +KEY_10CHANNELSUP: Final[int] = 440 +KEY_2: Final[int] = 3 +KEY_3: Final[int] = 4 +KEY_3D_MODE: Final[int] = 623 +KEY_4: Final[int] = 5 +KEY_5: Final[int] = 6 +KEY_6: Final[int] = 7 +KEY_7: Final[int] = 8 +KEY_8: Final[int] = 9 +KEY_9: Final[int] = 10 +KEY_A: Final[int] = 30 +KEY_AB: Final[int] = 406 +KEY_ACCESSIBILITY: Final[int] = 590 +KEY_ADDRESSBOOK: Final[int] = 429 +KEY_AGAIN: Final[int] = 129 +KEY_ALL_APPLICATIONS: Final[int] = 204 +KEY_ALS_TOGGLE: Final[int] = 560 +KEY_ALTERASE: Final[int] = 222 +KEY_ANGLE: Final[int] = 371 +KEY_APOSTROPHE: Final[int] = 40 +KEY_APPSELECT: Final[int] = 580 +KEY_ARCHIVE: Final[int] = 361 +KEY_ASPECT_RATIO: Final[int] = 375 +KEY_ASSISTANT: Final[int] = 583 +KEY_ATTENDANT_OFF: Final[int] = 540 +KEY_ATTENDANT_ON: Final[int] = 539 +KEY_ATTENDANT_TOGGLE: Final[int] = 541 +KEY_AUDIO: Final[int] = 392 +KEY_AUDIO_DESC: Final[int] = 622 +KEY_AUTOPILOT_ENGAGE_TOGGLE: Final[int] = 637 +KEY_AUX: Final[int] = 390 +KEY_B: Final[int] = 48 +KEY_BACK: Final[int] = 158 +KEY_BACKSLASH: Final[int] = 43 +KEY_BACKSPACE: Final[int] = 14 +KEY_BASSBOOST: Final[int] = 209 +KEY_BATTERY: Final[int] = 236 +KEY_BLUE: Final[int] = 401 +KEY_BLUETOOTH: Final[int] = 237 +KEY_BOOKMARKS: Final[int] = 156 +KEY_BREAK: Final[int] = 411 +KEY_BRIGHTNESSDOWN: Final[int] = 224 +KEY_BRIGHTNESSUP: Final[int] = 225 +KEY_BRIGHTNESS_AUTO: Final[int] = 244 +KEY_BRIGHTNESS_CYCLE: Final[int] = 243 +KEY_BRIGHTNESS_MAX: Final[int] = 593 +KEY_BRIGHTNESS_MENU: Final[int] = 649 +KEY_BRIGHTNESS_MIN: Final[int] = 592 +KEY_BRIGHTNESS_TOGGLE: Final[int] = 431 +KEY_BRIGHTNESS_ZERO: Final[int] = 244 +KEY_BRL_DOT1: Final[int] = 497 +KEY_BRL_DOT10: Final[int] = 506 +KEY_BRL_DOT2: Final[int] = 498 +KEY_BRL_DOT3: Final[int] = 499 +KEY_BRL_DOT4: Final[int] = 500 +KEY_BRL_DOT5: Final[int] = 501 +KEY_BRL_DOT6: Final[int] = 502 +KEY_BRL_DOT7: Final[int] = 503 +KEY_BRL_DOT8: Final[int] = 504 +KEY_BRL_DOT9: Final[int] = 505 +KEY_BUTTONCONFIG: Final[int] = 576 +KEY_C: Final[int] = 46 +KEY_CALC: Final[int] = 140 +KEY_CALENDAR: Final[int] = 397 +KEY_CAMERA: Final[int] = 212 +KEY_CAMERA_ACCESS_DISABLE: Final[int] = 588 +KEY_CAMERA_ACCESS_ENABLE: Final[int] = 587 +KEY_CAMERA_ACCESS_TOGGLE: Final[int] = 589 +KEY_CAMERA_DOWN: Final[int] = 536 +KEY_CAMERA_FOCUS: Final[int] = 528 +KEY_CAMERA_LEFT: Final[int] = 537 +KEY_CAMERA_RIGHT: Final[int] = 538 +KEY_CAMERA_UP: Final[int] = 535 +KEY_CAMERA_ZOOMIN: Final[int] = 533 +KEY_CAMERA_ZOOMOUT: Final[int] = 534 +KEY_CANCEL: Final[int] = 223 +KEY_CAPSLOCK: Final[int] = 58 +KEY_CD: Final[int] = 383 +KEY_CHANNEL: Final[int] = 363 +KEY_CHANNELDOWN: Final[int] = 403 +KEY_CHANNELUP: Final[int] = 402 +KEY_CHAT: Final[int] = 216 +KEY_CLEAR: Final[int] = 355 +KEY_CLEARVU_SONAR: Final[int] = 646 +KEY_CLOSE: Final[int] = 206 +KEY_CLOSECD: Final[int] = 160 +KEY_CNT: Final[int] = 768 +KEY_COFFEE: Final[int] = 152 +KEY_COMMA: Final[int] = 51 +KEY_COMPOSE: Final[int] = 127 +KEY_COMPUTER: Final[int] = 157 +KEY_CONFIG: Final[int] = 171 +KEY_CONNECT: Final[int] = 218 +KEY_CONTEXT_MENU: Final[int] = 438 +KEY_CONTROLPANEL: Final[int] = 579 +KEY_COPY: Final[int] = 133 +KEY_CUT: Final[int] = 137 +KEY_CYCLEWINDOWS: Final[int] = 154 +KEY_D: Final[int] = 32 +KEY_DASHBOARD: Final[int] = 204 +KEY_DATA: Final[int] = 631 +KEY_DATABASE: Final[int] = 426 +KEY_DELETE: Final[int] = 111 +KEY_DELETEFILE: Final[int] = 146 +KEY_DEL_EOL: Final[int] = 448 +KEY_DEL_EOS: Final[int] = 449 +KEY_DEL_LINE: Final[int] = 451 +KEY_DICTATE: Final[int] = 586 +KEY_DIGITS: Final[int] = 413 +KEY_DIRECTION: Final[int] = 153 +KEY_DIRECTORY: Final[int] = 394 +KEY_DISPLAYTOGGLE: Final[int] = 431 +KEY_DISPLAY_OFF: Final[int] = 245 +KEY_DOCUMENTS: Final[int] = 235 +KEY_DOLLAR: Final[int] = 434 +KEY_DOT: Final[int] = 52 +KEY_DOWN: Final[int] = 108 +KEY_DO_NOT_DISTURB: Final[int] = 591 +KEY_DUAL_RANGE_RADAR: Final[int] = 643 +KEY_DVD: Final[int] = 389 +KEY_E: Final[int] = 18 +KEY_EDIT: Final[int] = 176 +KEY_EDITOR: Final[int] = 422 +KEY_EJECTCD: Final[int] = 161 +KEY_EJECTCLOSECD: Final[int] = 162 +KEY_EMAIL: Final[int] = 215 +KEY_EMOJI_PICKER: Final[int] = 585 +KEY_END: Final[int] = 107 +KEY_ENTER: Final[int] = 28 +KEY_EPG: Final[int] = 365 +KEY_EQUAL: Final[int] = 13 +KEY_ESC: Final[int] = 1 +KEY_EURO: Final[int] = 435 +KEY_EXIT: Final[int] = 174 +KEY_F: Final[int] = 33 +KEY_F1: Final[int] = 59 +KEY_F10: Final[int] = 68 +KEY_F11: Final[int] = 87 +KEY_F12: Final[int] = 88 +KEY_F13: Final[int] = 183 +KEY_F14: Final[int] = 184 +KEY_F15: Final[int] = 185 +KEY_F16: Final[int] = 186 +KEY_F17: Final[int] = 187 +KEY_F18: Final[int] = 188 +KEY_F19: Final[int] = 189 +KEY_F2: Final[int] = 60 +KEY_F20: Final[int] = 190 +KEY_F21: Final[int] = 191 +KEY_F22: Final[int] = 192 +KEY_F23: Final[int] = 193 +KEY_F24: Final[int] = 194 +KEY_F3: Final[int] = 61 +KEY_F4: Final[int] = 62 +KEY_F5: Final[int] = 63 +KEY_F6: Final[int] = 64 +KEY_F7: Final[int] = 65 +KEY_F8: Final[int] = 66 +KEY_F9: Final[int] = 67 +KEY_FASTFORWARD: Final[int] = 208 +KEY_FASTREVERSE: Final[int] = 629 +KEY_FAVORITES: Final[int] = 364 +KEY_FILE: Final[int] = 144 +KEY_FINANCE: Final[int] = 219 +KEY_FIND: Final[int] = 136 +KEY_FIRST: Final[int] = 404 +KEY_FISHING_CHART: Final[int] = 641 +KEY_FN: Final[int] = 464 +KEY_FN_1: Final[int] = 478 +KEY_FN_2: Final[int] = 479 +KEY_FN_B: Final[int] = 484 +KEY_FN_D: Final[int] = 480 +KEY_FN_E: Final[int] = 481 +KEY_FN_ESC: Final[int] = 465 +KEY_FN_F: Final[int] = 482 +KEY_FN_F1: Final[int] = 466 +KEY_FN_F10: Final[int] = 475 +KEY_FN_F11: Final[int] = 476 +KEY_FN_F12: Final[int] = 477 +KEY_FN_F2: Final[int] = 467 +KEY_FN_F3: Final[int] = 468 +KEY_FN_F4: Final[int] = 469 +KEY_FN_F5: Final[int] = 470 +KEY_FN_F6: Final[int] = 471 +KEY_FN_F7: Final[int] = 472 +KEY_FN_F8: Final[int] = 473 +KEY_FN_F9: Final[int] = 474 +KEY_FN_RIGHT_SHIFT: Final[int] = 485 +KEY_FN_S: Final[int] = 483 +KEY_FORWARD: Final[int] = 159 +KEY_FORWARDMAIL: Final[int] = 233 +KEY_FRAMEBACK: Final[int] = 436 +KEY_FRAMEFORWARD: Final[int] = 437 +KEY_FRONT: Final[int] = 132 +KEY_FULL_SCREEN: Final[int] = 372 +KEY_G: Final[int] = 34 +KEY_GAMES: Final[int] = 417 +KEY_GOTO: Final[int] = 354 +KEY_GRAPHICSEDITOR: Final[int] = 424 +KEY_GRAVE: Final[int] = 41 +KEY_GREEN: Final[int] = 399 +KEY_H: Final[int] = 35 +KEY_HANGEUL: Final[int] = 122 +KEY_HANGUEL: Final[int] = 122 +KEY_HANGUP_PHONE: Final[int] = 446 +KEY_HANJA: Final[int] = 123 +KEY_HELP: Final[int] = 138 +KEY_HENKAN: Final[int] = 92 +KEY_HIRAGANA: Final[int] = 91 +KEY_HOME: Final[int] = 102 +KEY_HOMEPAGE: Final[int] = 172 +KEY_HP: Final[int] = 211 +KEY_I: Final[int] = 23 +KEY_IMAGES: Final[int] = 442 +KEY_INFO: Final[int] = 358 +KEY_INSERT: Final[int] = 110 +KEY_INS_LINE: Final[int] = 450 +KEY_ISO: Final[int] = 170 +KEY_J: Final[int] = 36 +KEY_JOURNAL: Final[int] = 578 +KEY_K: Final[int] = 37 +KEY_KATAKANA: Final[int] = 90 +KEY_KATAKANAHIRAGANA: Final[int] = 93 +KEY_KBDILLUMDOWN: Final[int] = 229 +KEY_KBDILLUMTOGGLE: Final[int] = 228 +KEY_KBDILLUMUP: Final[int] = 230 +KEY_KBDINPUTASSIST_ACCEPT: Final[int] = 612 +KEY_KBDINPUTASSIST_CANCEL: Final[int] = 613 +KEY_KBDINPUTASSIST_NEXT: Final[int] = 609 +KEY_KBDINPUTASSIST_NEXTGROUP: Final[int] = 611 +KEY_KBDINPUTASSIST_PREV: Final[int] = 608 +KEY_KBDINPUTASSIST_PREVGROUP: Final[int] = 610 +KEY_KBD_LAYOUT_NEXT: Final[int] = 584 +KEY_KBD_LCD_MENU1: Final[int] = 696 +KEY_KBD_LCD_MENU2: Final[int] = 697 +KEY_KBD_LCD_MENU3: Final[int] = 698 +KEY_KBD_LCD_MENU4: Final[int] = 699 +KEY_KBD_LCD_MENU5: Final[int] = 700 +KEY_KEYBOARD: Final[int] = 374 +KEY_KP0: Final[int] = 82 +KEY_KP1: Final[int] = 79 +KEY_KP2: Final[int] = 80 +KEY_KP3: Final[int] = 81 +KEY_KP4: Final[int] = 75 +KEY_KP5: Final[int] = 76 +KEY_KP6: Final[int] = 77 +KEY_KP7: Final[int] = 71 +KEY_KP8: Final[int] = 72 +KEY_KP9: Final[int] = 73 +KEY_KPASTERISK: Final[int] = 55 +KEY_KPCOMMA: Final[int] = 121 +KEY_KPDOT: Final[int] = 83 +KEY_KPENTER: Final[int] = 96 +KEY_KPEQUAL: Final[int] = 117 +KEY_KPJPCOMMA: Final[int] = 95 +KEY_KPLEFTPAREN: Final[int] = 179 +KEY_KPMINUS: Final[int] = 74 +KEY_KPPLUS: Final[int] = 78 +KEY_KPPLUSMINUS: Final[int] = 118 +KEY_KPRIGHTPAREN: Final[int] = 180 +KEY_KPSLASH: Final[int] = 98 +KEY_L: Final[int] = 38 +KEY_LANGUAGE: Final[int] = 368 +KEY_LAST: Final[int] = 405 +KEY_LEFT: Final[int] = 105 +KEY_LEFTALT: Final[int] = 56 +KEY_LEFTBRACE: Final[int] = 26 +KEY_LEFTCTRL: Final[int] = 29 +KEY_LEFTMETA: Final[int] = 125 +KEY_LEFTSHIFT: Final[int] = 42 +KEY_LEFT_DOWN: Final[int] = 617 +KEY_LEFT_UP: Final[int] = 616 +KEY_LIGHTS_TOGGLE: Final[int] = 542 +KEY_LINEFEED: Final[int] = 101 +KEY_LINK_PHONE: Final[int] = 447 +KEY_LIST: Final[int] = 395 +KEY_LOGOFF: Final[int] = 433 +KEY_M: Final[int] = 50 +KEY_MACRO: Final[int] = 112 +KEY_MACRO1: Final[int] = 656 +KEY_MACRO10: Final[int] = 665 +KEY_MACRO11: Final[int] = 666 +KEY_MACRO12: Final[int] = 667 +KEY_MACRO13: Final[int] = 668 +KEY_MACRO14: Final[int] = 669 +KEY_MACRO15: Final[int] = 670 +KEY_MACRO16: Final[int] = 671 +KEY_MACRO17: Final[int] = 672 +KEY_MACRO18: Final[int] = 673 +KEY_MACRO19: Final[int] = 674 +KEY_MACRO2: Final[int] = 657 +KEY_MACRO20: Final[int] = 675 +KEY_MACRO21: Final[int] = 676 +KEY_MACRO22: Final[int] = 677 +KEY_MACRO23: Final[int] = 678 +KEY_MACRO24: Final[int] = 679 +KEY_MACRO25: Final[int] = 680 +KEY_MACRO26: Final[int] = 681 +KEY_MACRO27: Final[int] = 682 +KEY_MACRO28: Final[int] = 683 +KEY_MACRO29: Final[int] = 684 +KEY_MACRO3: Final[int] = 658 +KEY_MACRO30: Final[int] = 685 +KEY_MACRO4: Final[int] = 659 +KEY_MACRO5: Final[int] = 660 +KEY_MACRO6: Final[int] = 661 +KEY_MACRO7: Final[int] = 662 +KEY_MACRO8: Final[int] = 663 +KEY_MACRO9: Final[int] = 664 +KEY_MACRO_PRESET1: Final[int] = 691 +KEY_MACRO_PRESET2: Final[int] = 692 +KEY_MACRO_PRESET3: Final[int] = 693 +KEY_MACRO_PRESET_CYCLE: Final[int] = 690 +KEY_MACRO_RECORD_START: Final[int] = 688 +KEY_MACRO_RECORD_STOP: Final[int] = 689 +KEY_MAIL: Final[int] = 155 +KEY_MARK_WAYPOINT: Final[int] = 638 +KEY_MAX: Final[int] = 767 +KEY_MEDIA: Final[int] = 226 +KEY_MEDIA_REPEAT: Final[int] = 439 +KEY_MEDIA_TOP_MENU: Final[int] = 619 +KEY_MEMO: Final[int] = 396 +KEY_MENU: Final[int] = 139 +KEY_MESSENGER: Final[int] = 430 +KEY_MHP: Final[int] = 367 +KEY_MICMUTE: Final[int] = 248 +KEY_MINUS: Final[int] = 12 +KEY_MIN_INTERESTING: Final[int] = 113 +KEY_MODE: Final[int] = 373 +KEY_MOVE: Final[int] = 175 +KEY_MP3: Final[int] = 391 +KEY_MSDOS: Final[int] = 151 +KEY_MUHENKAN: Final[int] = 94 +KEY_MUTE: Final[int] = 113 +KEY_N: Final[int] = 49 +KEY_NAV_CHART: Final[int] = 640 +KEY_NAV_INFO: Final[int] = 648 +KEY_NEW: Final[int] = 181 +KEY_NEWS: Final[int] = 427 +KEY_NEXT: Final[int] = 407 +KEY_NEXTSONG: Final[int] = 163 +KEY_NEXT_ELEMENT: Final[int] = 635 +KEY_NEXT_FAVORITE: Final[int] = 624 +KEY_NOTIFICATION_CENTER: Final[int] = 444 +KEY_NUMERIC_0: Final[int] = 512 +KEY_NUMERIC_1: Final[int] = 513 +KEY_NUMERIC_11: Final[int] = 620 +KEY_NUMERIC_12: Final[int] = 621 +KEY_NUMERIC_2: Final[int] = 514 +KEY_NUMERIC_3: Final[int] = 515 +KEY_NUMERIC_4: Final[int] = 516 +KEY_NUMERIC_5: Final[int] = 517 +KEY_NUMERIC_6: Final[int] = 518 +KEY_NUMERIC_7: Final[int] = 519 +KEY_NUMERIC_8: Final[int] = 520 +KEY_NUMERIC_9: Final[int] = 521 +KEY_NUMERIC_A: Final[int] = 524 +KEY_NUMERIC_B: Final[int] = 525 +KEY_NUMERIC_C: Final[int] = 526 +KEY_NUMERIC_D: Final[int] = 527 +KEY_NUMERIC_POUND: Final[int] = 523 +KEY_NUMERIC_STAR: Final[int] = 522 +KEY_NUMLOCK: Final[int] = 69 +KEY_O: Final[int] = 24 +KEY_OK: Final[int] = 352 +KEY_ONSCREEN_KEYBOARD: Final[int] = 632 +KEY_OPEN: Final[int] = 134 +KEY_OPTION: Final[int] = 357 +KEY_P: Final[int] = 25 +KEY_PAGEDOWN: Final[int] = 109 +KEY_PAGEUP: Final[int] = 104 +KEY_PASTE: Final[int] = 135 +KEY_PAUSE: Final[int] = 119 +KEY_PAUSECD: Final[int] = 201 +KEY_PAUSE_RECORD: Final[int] = 626 +KEY_PC: Final[int] = 376 +KEY_PHONE: Final[int] = 169 +KEY_PICKUP_PHONE: Final[int] = 445 +KEY_PLAY: Final[int] = 207 +KEY_PLAYCD: Final[int] = 200 +KEY_PLAYER: Final[int] = 387 +KEY_PLAYPAUSE: Final[int] = 164 +KEY_POWER: Final[int] = 116 +KEY_POWER2: Final[int] = 356 +KEY_PRESENTATION: Final[int] = 425 +KEY_PREVIOUS: Final[int] = 412 +KEY_PREVIOUSSONG: Final[int] = 165 +KEY_PREVIOUS_ELEMENT: Final[int] = 636 +KEY_PRINT: Final[int] = 210 +KEY_PRIVACY_SCREEN_TOGGLE: Final[int] = 633 +KEY_PROG1: Final[int] = 148 +KEY_PROG2: Final[int] = 149 +KEY_PROG3: Final[int] = 202 +KEY_PROG4: Final[int] = 203 +KEY_PROGRAM: Final[int] = 362 +KEY_PROPS: Final[int] = 130 +KEY_PVR: Final[int] = 366 +KEY_Q: Final[int] = 16 +KEY_QUESTION: Final[int] = 214 +KEY_R: Final[int] = 19 +KEY_RADAR_OVERLAY: Final[int] = 644 +KEY_RADIO: Final[int] = 385 +KEY_RECORD: Final[int] = 167 +KEY_RED: Final[int] = 398 +KEY_REDO: Final[int] = 182 +KEY_REFRESH: Final[int] = 173 +KEY_REFRESH_RATE_TOGGLE: Final[int] = 562 +KEY_REPLY: Final[int] = 232 +KEY_RESERVED: Final[int] = 0 +KEY_RESTART: Final[int] = 408 +KEY_REWIND: Final[int] = 168 +KEY_RFKILL: Final[int] = 247 +KEY_RIGHT: Final[int] = 106 +KEY_RIGHTALT: Final[int] = 100 +KEY_RIGHTBRACE: Final[int] = 27 +KEY_RIGHTCTRL: Final[int] = 97 +KEY_RIGHTMETA: Final[int] = 126 +KEY_RIGHTSHIFT: Final[int] = 54 +KEY_RIGHT_DOWN: Final[int] = 615 +KEY_RIGHT_UP: Final[int] = 614 +KEY_RO: Final[int] = 89 +KEY_ROOT_MENU: Final[int] = 618 +KEY_ROTATE_DISPLAY: Final[int] = 153 +KEY_ROTATE_LOCK_TOGGLE: Final[int] = 561 +KEY_S: Final[int] = 31 +KEY_SAT: Final[int] = 381 +KEY_SAT2: Final[int] = 382 +KEY_SAVE: Final[int] = 234 +KEY_SCALE: Final[int] = 120 +KEY_SCREEN: Final[int] = 375 +KEY_SCREENLOCK: Final[int] = 152 +KEY_SCREENSAVER: Final[int] = 581 +KEY_SCROLLDOWN: Final[int] = 178 +KEY_SCROLLLOCK: Final[int] = 70 +KEY_SCROLLUP: Final[int] = 177 +KEY_SEARCH: Final[int] = 217 +KEY_SELECT: Final[int] = 353 +KEY_SELECTIVE_SCREENSHOT: Final[int] = 634 +KEY_SEMICOLON: Final[int] = 39 +KEY_SEND: Final[int] = 231 +KEY_SENDFILE: Final[int] = 145 +KEY_SETUP: Final[int] = 141 +KEY_SHOP: Final[int] = 221 +KEY_SHUFFLE: Final[int] = 410 +KEY_SIDEVU_SONAR: Final[int] = 647 +KEY_SINGLE_RANGE_RADAR: Final[int] = 642 +KEY_SLASH: Final[int] = 53 +KEY_SLEEP: Final[int] = 142 +KEY_SLOW: Final[int] = 409 +KEY_SLOWREVERSE: Final[int] = 630 +KEY_SOS: Final[int] = 639 +KEY_SOUND: Final[int] = 213 +KEY_SPACE: Final[int] = 57 +KEY_SPELLCHECK: Final[int] = 432 +KEY_SPORT: Final[int] = 220 +KEY_SPREADSHEET: Final[int] = 423 +KEY_STOP: Final[int] = 128 +KEY_STOPCD: Final[int] = 166 +KEY_STOP_RECORD: Final[int] = 625 +KEY_SUBTITLE: Final[int] = 370 +KEY_SUSPEND: Final[int] = 205 +KEY_SWITCHVIDEOMODE: Final[int] = 227 +KEY_SYSRQ: Final[int] = 99 +KEY_T: Final[int] = 20 +KEY_TAB: Final[int] = 15 +KEY_TAPE: Final[int] = 384 +KEY_TASKMANAGER: Final[int] = 577 +KEY_TEEN: Final[int] = 414 +KEY_TEXT: Final[int] = 388 +KEY_TIME: Final[int] = 359 +KEY_TITLE: Final[int] = 369 +KEY_TOUCHPAD_OFF: Final[int] = 532 +KEY_TOUCHPAD_ON: Final[int] = 531 +KEY_TOUCHPAD_TOGGLE: Final[int] = 530 +KEY_TRADITIONAL_SONAR: Final[int] = 645 +KEY_TUNER: Final[int] = 386 +KEY_TV: Final[int] = 377 +KEY_TV2: Final[int] = 378 +KEY_TWEN: Final[int] = 415 +KEY_U: Final[int] = 22 +KEY_UNDO: Final[int] = 131 +KEY_UNKNOWN: Final[int] = 240 +KEY_UNMUTE: Final[int] = 628 +KEY_UP: Final[int] = 103 +KEY_UWB: Final[int] = 239 +KEY_V: Final[int] = 47 +KEY_VCR: Final[int] = 379 +KEY_VCR2: Final[int] = 380 +KEY_VENDOR: Final[int] = 360 +KEY_VIDEO: Final[int] = 393 +KEY_VIDEOPHONE: Final[int] = 416 +KEY_VIDEO_NEXT: Final[int] = 241 +KEY_VIDEO_PREV: Final[int] = 242 +KEY_VOD: Final[int] = 627 +KEY_VOICECOMMAND: Final[int] = 582 +KEY_VOICEMAIL: Final[int] = 428 +KEY_VOLUMEDOWN: Final[int] = 114 +KEY_VOLUMEUP: Final[int] = 115 +KEY_W: Final[int] = 17 +KEY_WAKEUP: Final[int] = 143 +KEY_WIMAX: Final[int] = 246 +KEY_WLAN: Final[int] = 238 +KEY_WORDPROCESSOR: Final[int] = 421 +KEY_WPS_BUTTON: Final[int] = 529 +KEY_WWAN: Final[int] = 246 +KEY_WWW: Final[int] = 150 +KEY_X: Final[int] = 45 +KEY_XFER: Final[int] = 147 +KEY_Y: Final[int] = 21 +KEY_YELLOW: Final[int] = 400 +KEY_YEN: Final[int] = 124 +KEY_Z: Final[int] = 44 +KEY_ZENKAKUHANKAKU: Final[int] = 85 +KEY_ZOOM: Final[int] = 372 +KEY_ZOOMIN: Final[int] = 418 +KEY_ZOOMOUT: Final[int] = 419 +KEY_ZOOMRESET: Final[int] = 420 +LED_CAPSL: Final[int] = 1 +LED_CHARGING: Final[int] = 10 +LED_CNT: Final[int] = 16 +LED_COMPOSE: Final[int] = 3 +LED_KANA: Final[int] = 4 +LED_MAIL: Final[int] = 9 +LED_MAX: Final[int] = 15 +LED_MISC: Final[int] = 8 +LED_MUTE: Final[int] = 7 +LED_NUML: Final[int] = 0 +LED_SCROLLL: Final[int] = 2 +LED_SLEEP: Final[int] = 5 +LED_SUSPEND: Final[int] = 6 +MSC_CNT: Final[int] = 8 +MSC_GESTURE: Final[int] = 2 +MSC_MAX: Final[int] = 7 +MSC_PULSELED: Final[int] = 1 +MSC_RAW: Final[int] = 3 +MSC_SCAN: Final[int] = 4 +MSC_SERIAL: Final[int] = 0 +MSC_TIMESTAMP: Final[int] = 5 +REL_CNT: Final[int] = 16 +REL_DIAL: Final[int] = 7 +REL_HWHEEL: Final[int] = 6 +REL_HWHEEL_HI_RES: Final[int] = 12 +REL_MAX: Final[int] = 15 +REL_MISC: Final[int] = 9 +REL_RESERVED: Final[int] = 10 +REL_RX: Final[int] = 3 +REL_RY: Final[int] = 4 +REL_RZ: Final[int] = 5 +REL_WHEEL: Final[int] = 8 +REL_WHEEL_HI_RES: Final[int] = 11 +REL_X: Final[int] = 0 +REL_Y: Final[int] = 1 +REL_Z: Final[int] = 2 +REP_CNT: Final[int] = 2 +REP_DELAY: Final[int] = 0 +REP_MAX: Final[int] = 1 +REP_PERIOD: Final[int] = 1 +SND_BELL: Final[int] = 1 +SND_CLICK: Final[int] = 0 +SND_CNT: Final[int] = 8 +SND_MAX: Final[int] = 7 +SND_TONE: Final[int] = 2 +SW_CAMERA_LENS_COVER: Final[int] = 9 +SW_CNT: Final[int] = 17 +SW_DOCK: Final[int] = 5 +SW_FRONT_PROXIMITY: Final[int] = 11 +SW_HEADPHONE_INSERT: Final[int] = 2 +SW_JACK_PHYSICAL_INSERT: Final[int] = 7 +SW_KEYPAD_SLIDE: Final[int] = 10 +SW_LID: Final[int] = 0 +SW_LINEIN_INSERT: Final[int] = 13 +SW_LINEOUT_INSERT: Final[int] = 6 +SW_MACHINE_COVER: Final[int] = 16 +SW_MAX: Final[int] = 16 +SW_MICROPHONE_INSERT: Final[int] = 4 +SW_MUTE_DEVICE: Final[int] = 14 +SW_PEN_INSERTED: Final[int] = 15 +SW_RADIO: Final[int] = 3 +SW_RFKILL_ALL: Final[int] = 3 +SW_ROTATE_LOCK: Final[int] = 12 +SW_TABLET_MODE: Final[int] = 1 +SW_VIDEOOUT_INSERT: Final[int] = 8 +SYN_CNT: Final[int] = 16 +SYN_CONFIG: Final[int] = 1 +SYN_DROPPED: Final[int] = 3 +SYN_MAX: Final[int] = 15 +SYN_MT_REPORT: Final[int] = 2 +SYN_REPORT: Final[int] = 0 +UI_FF_ERASE: Final[int] = 2 +UI_FF_UPLOAD: Final[int] = 1 + +#: Mapping of names to values. +ecodes: Dict[str, int] = { 'ABS_BRAKE': 10, + 'ABS_CNT': 64, + 'ABS_DISTANCE': 25, + 'ABS_GAS': 9, + 'ABS_HAT0X': 16, + 'ABS_HAT0Y': 17, + 'ABS_HAT1X': 18, + 'ABS_HAT1Y': 19, + 'ABS_HAT2X': 20, + 'ABS_HAT2Y': 21, + 'ABS_HAT3X': 22, + 'ABS_HAT3Y': 23, + 'ABS_MAX': 63, + 'ABS_MISC': 40, + 'ABS_MT_BLOB_ID': 56, + 'ABS_MT_DISTANCE': 59, + 'ABS_MT_ORIENTATION': 52, + 'ABS_MT_POSITION_X': 53, + 'ABS_MT_POSITION_Y': 54, + 'ABS_MT_PRESSURE': 58, + 'ABS_MT_SLOT': 47, + 'ABS_MT_TOOL_TYPE': 55, + 'ABS_MT_TOOL_X': 60, + 'ABS_MT_TOOL_Y': 61, + 'ABS_MT_TOUCH_MAJOR': 48, + 'ABS_MT_TOUCH_MINOR': 49, + 'ABS_MT_TRACKING_ID': 57, + 'ABS_MT_WIDTH_MAJOR': 50, + 'ABS_MT_WIDTH_MINOR': 51, + 'ABS_PRESSURE': 24, + 'ABS_PROFILE': 33, + 'ABS_RESERVED': 46, + 'ABS_RUDDER': 7, + 'ABS_RX': 3, + 'ABS_RY': 4, + 'ABS_RZ': 5, + 'ABS_THROTTLE': 6, + 'ABS_TILT_X': 26, + 'ABS_TILT_Y': 27, + 'ABS_TOOL_WIDTH': 28, + 'ABS_VOLUME': 32, + 'ABS_WHEEL': 8, + 'ABS_X': 0, + 'ABS_Y': 1, + 'ABS_Z': 2, + 'BTN_0': 256, + 'BTN_1': 257, + 'BTN_2': 258, + 'BTN_3': 259, + 'BTN_4': 260, + 'BTN_5': 261, + 'BTN_6': 262, + 'BTN_7': 263, + 'BTN_8': 264, + 'BTN_9': 265, + 'BTN_A': 304, + 'BTN_B': 305, + 'BTN_BACK': 278, + 'BTN_BASE': 294, + 'BTN_BASE2': 295, + 'BTN_BASE3': 296, + 'BTN_BASE4': 297, + 'BTN_BASE5': 298, + 'BTN_BASE6': 299, + 'BTN_C': 306, + 'BTN_DEAD': 303, + 'BTN_DIGI': 320, + 'BTN_DPAD_DOWN': 545, + 'BTN_DPAD_LEFT': 546, + 'BTN_DPAD_RIGHT': 547, + 'BTN_DPAD_UP': 544, + 'BTN_EAST': 305, + 'BTN_EXTRA': 276, + 'BTN_FORWARD': 277, + 'BTN_GAMEPAD': 304, + 'BTN_GEAR_DOWN': 336, + 'BTN_GEAR_UP': 337, + 'BTN_JOYSTICK': 288, + 'BTN_LEFT': 272, + 'BTN_MIDDLE': 274, + 'BTN_MISC': 256, + 'BTN_MODE': 316, + 'BTN_MOUSE': 272, + 'BTN_NORTH': 307, + 'BTN_PINKIE': 293, + 'BTN_RIGHT': 273, + 'BTN_SELECT': 314, + 'BTN_SIDE': 275, + 'BTN_SOUTH': 304, + 'BTN_START': 315, + 'BTN_STYLUS': 331, + 'BTN_STYLUS2': 332, + 'BTN_STYLUS3': 329, + 'BTN_TASK': 279, + 'BTN_THUMB': 289, + 'BTN_THUMB2': 290, + 'BTN_THUMBL': 317, + 'BTN_THUMBR': 318, + 'BTN_TL': 310, + 'BTN_TL2': 312, + 'BTN_TOOL_AIRBRUSH': 324, + 'BTN_TOOL_BRUSH': 322, + 'BTN_TOOL_DOUBLETAP': 333, + 'BTN_TOOL_FINGER': 325, + 'BTN_TOOL_LENS': 327, + 'BTN_TOOL_MOUSE': 326, + 'BTN_TOOL_PEN': 320, + 'BTN_TOOL_PENCIL': 323, + 'BTN_TOOL_QUADTAP': 335, + 'BTN_TOOL_QUINTTAP': 328, + 'BTN_TOOL_RUBBER': 321, + 'BTN_TOOL_TRIPLETAP': 334, + 'BTN_TOP': 291, + 'BTN_TOP2': 292, + 'BTN_TOUCH': 330, + 'BTN_TR': 311, + 'BTN_TR2': 313, + 'BTN_TRIGGER': 288, + 'BTN_TRIGGER_HAPPY': 704, + 'BTN_TRIGGER_HAPPY1': 704, + 'BTN_TRIGGER_HAPPY10': 713, + 'BTN_TRIGGER_HAPPY11': 714, + 'BTN_TRIGGER_HAPPY12': 715, + 'BTN_TRIGGER_HAPPY13': 716, + 'BTN_TRIGGER_HAPPY14': 717, + 'BTN_TRIGGER_HAPPY15': 718, + 'BTN_TRIGGER_HAPPY16': 719, + 'BTN_TRIGGER_HAPPY17': 720, + 'BTN_TRIGGER_HAPPY18': 721, + 'BTN_TRIGGER_HAPPY19': 722, + 'BTN_TRIGGER_HAPPY2': 705, + 'BTN_TRIGGER_HAPPY20': 723, + 'BTN_TRIGGER_HAPPY21': 724, + 'BTN_TRIGGER_HAPPY22': 725, + 'BTN_TRIGGER_HAPPY23': 726, + 'BTN_TRIGGER_HAPPY24': 727, + 'BTN_TRIGGER_HAPPY25': 728, + 'BTN_TRIGGER_HAPPY26': 729, + 'BTN_TRIGGER_HAPPY27': 730, + 'BTN_TRIGGER_HAPPY28': 731, + 'BTN_TRIGGER_HAPPY29': 732, + 'BTN_TRIGGER_HAPPY3': 706, + 'BTN_TRIGGER_HAPPY30': 733, + 'BTN_TRIGGER_HAPPY31': 734, + 'BTN_TRIGGER_HAPPY32': 735, + 'BTN_TRIGGER_HAPPY33': 736, + 'BTN_TRIGGER_HAPPY34': 737, + 'BTN_TRIGGER_HAPPY35': 738, + 'BTN_TRIGGER_HAPPY36': 739, + 'BTN_TRIGGER_HAPPY37': 740, + 'BTN_TRIGGER_HAPPY38': 741, + 'BTN_TRIGGER_HAPPY39': 742, + 'BTN_TRIGGER_HAPPY4': 707, + 'BTN_TRIGGER_HAPPY40': 743, + 'BTN_TRIGGER_HAPPY5': 708, + 'BTN_TRIGGER_HAPPY6': 709, + 'BTN_TRIGGER_HAPPY7': 710, + 'BTN_TRIGGER_HAPPY8': 711, + 'BTN_TRIGGER_HAPPY9': 712, + 'BTN_WEST': 308, + 'BTN_WHEEL': 336, + 'BTN_X': 307, + 'BTN_Y': 308, + 'BTN_Z': 309, + 'BUS_ADB': 23, + 'BUS_AMD_SFH': 32, + 'BUS_AMIGA': 22, + 'BUS_ATARI': 27, + 'BUS_BLUETOOTH': 5, + 'BUS_CEC': 30, + 'BUS_GAMEPORT': 20, + 'BUS_GSC': 26, + 'BUS_HIL': 4, + 'BUS_HOST': 25, + 'BUS_I2C': 24, + 'BUS_I8042': 17, + 'BUS_INTEL_ISHTP': 31, + 'BUS_ISA': 16, + 'BUS_ISAPNP': 2, + 'BUS_PARPORT': 21, + 'BUS_PCI': 1, + 'BUS_RMI': 29, + 'BUS_RS232': 19, + 'BUS_SPI': 28, + 'BUS_USB': 3, + 'BUS_VIRTUAL': 6, + 'BUS_XTKBD': 18, + 'EV_ABS': 3, + 'EV_CNT': 32, + 'EV_FF': 21, + 'EV_FF_STATUS': 23, + 'EV_KEY': 1, + 'EV_LED': 17, + 'EV_MAX': 31, + 'EV_MSC': 4, + 'EV_PWR': 22, + 'EV_REL': 2, + 'EV_REP': 20, + 'EV_SND': 18, + 'EV_SW': 5, + 'EV_SYN': 0, + 'EV_UINPUT': 257, + 'EV_VERSION': 65537, + 'FF_AUTOCENTER': 97, + 'FF_CNT': 128, + 'FF_CONSTANT': 82, + 'FF_CUSTOM': 93, + 'FF_DAMPER': 85, + 'FF_EFFECT_MAX': 87, + 'FF_EFFECT_MIN': 80, + 'FF_FRICTION': 84, + 'FF_GAIN': 96, + 'FF_INERTIA': 86, + 'FF_MAX': 127, + 'FF_MAX_EFFECTS': 96, + 'FF_PERIODIC': 81, + 'FF_RAMP': 87, + 'FF_RUMBLE': 80, + 'FF_SAW_DOWN': 92, + 'FF_SAW_UP': 91, + 'FF_SINE': 90, + 'FF_SPRING': 83, + 'FF_SQUARE': 88, + 'FF_STATUS_MAX': 1, + 'FF_STATUS_PLAYING': 1, + 'FF_STATUS_STOPPED': 0, + 'FF_TRIANGLE': 89, + 'FF_WAVEFORM_MAX': 93, + 'FF_WAVEFORM_MIN': 88, + 'ID_BUS': 0, + 'ID_PRODUCT': 2, + 'ID_VENDOR': 1, + 'ID_VERSION': 3, + 'INPUT_PROP_ACCELEROMETER': 6, + 'INPUT_PROP_BUTTONPAD': 2, + 'INPUT_PROP_CNT': 32, + 'INPUT_PROP_DIRECT': 1, + 'INPUT_PROP_MAX': 31, + 'INPUT_PROP_POINTER': 0, + 'INPUT_PROP_POINTING_STICK': 5, + 'INPUT_PROP_SEMI_MT': 3, + 'INPUT_PROP_TOPBUTTONPAD': 4, + 'KEY_0': 11, + 'KEY_1': 2, + 'KEY_102ND': 86, + 'KEY_10CHANNELSDOWN': 441, + 'KEY_10CHANNELSUP': 440, + 'KEY_2': 3, + 'KEY_3': 4, + 'KEY_3D_MODE': 623, + 'KEY_4': 5, + 'KEY_5': 6, + 'KEY_6': 7, + 'KEY_7': 8, + 'KEY_8': 9, + 'KEY_9': 10, + 'KEY_A': 30, + 'KEY_AB': 406, + 'KEY_ACCESSIBILITY': 590, + 'KEY_ADDRESSBOOK': 429, + 'KEY_AGAIN': 129, + 'KEY_ALL_APPLICATIONS': 204, + 'KEY_ALS_TOGGLE': 560, + 'KEY_ALTERASE': 222, + 'KEY_ANGLE': 371, + 'KEY_APOSTROPHE': 40, + 'KEY_APPSELECT': 580, + 'KEY_ARCHIVE': 361, + 'KEY_ASPECT_RATIO': 375, + 'KEY_ASSISTANT': 583, + 'KEY_ATTENDANT_OFF': 540, + 'KEY_ATTENDANT_ON': 539, + 'KEY_ATTENDANT_TOGGLE': 541, + 'KEY_AUDIO': 392, + 'KEY_AUDIO_DESC': 622, + 'KEY_AUTOPILOT_ENGAGE_TOGGLE': 637, + 'KEY_AUX': 390, + 'KEY_B': 48, + 'KEY_BACK': 158, + 'KEY_BACKSLASH': 43, + 'KEY_BACKSPACE': 14, + 'KEY_BASSBOOST': 209, + 'KEY_BATTERY': 236, + 'KEY_BLUE': 401, + 'KEY_BLUETOOTH': 237, + 'KEY_BOOKMARKS': 156, + 'KEY_BREAK': 411, + 'KEY_BRIGHTNESSDOWN': 224, + 'KEY_BRIGHTNESSUP': 225, + 'KEY_BRIGHTNESS_AUTO': 244, + 'KEY_BRIGHTNESS_CYCLE': 243, + 'KEY_BRIGHTNESS_MAX': 593, + 'KEY_BRIGHTNESS_MENU': 649, + 'KEY_BRIGHTNESS_MIN': 592, + 'KEY_BRIGHTNESS_TOGGLE': 431, + 'KEY_BRIGHTNESS_ZERO': 244, + 'KEY_BRL_DOT1': 497, + 'KEY_BRL_DOT10': 506, + 'KEY_BRL_DOT2': 498, + 'KEY_BRL_DOT3': 499, + 'KEY_BRL_DOT4': 500, + 'KEY_BRL_DOT5': 501, + 'KEY_BRL_DOT6': 502, + 'KEY_BRL_DOT7': 503, + 'KEY_BRL_DOT8': 504, + 'KEY_BRL_DOT9': 505, + 'KEY_BUTTONCONFIG': 576, + 'KEY_C': 46, + 'KEY_CALC': 140, + 'KEY_CALENDAR': 397, + 'KEY_CAMERA': 212, + 'KEY_CAMERA_ACCESS_DISABLE': 588, + 'KEY_CAMERA_ACCESS_ENABLE': 587, + 'KEY_CAMERA_ACCESS_TOGGLE': 589, + 'KEY_CAMERA_DOWN': 536, + 'KEY_CAMERA_FOCUS': 528, + 'KEY_CAMERA_LEFT': 537, + 'KEY_CAMERA_RIGHT': 538, + 'KEY_CAMERA_UP': 535, + 'KEY_CAMERA_ZOOMIN': 533, + 'KEY_CAMERA_ZOOMOUT': 534, + 'KEY_CANCEL': 223, + 'KEY_CAPSLOCK': 58, + 'KEY_CD': 383, + 'KEY_CHANNEL': 363, + 'KEY_CHANNELDOWN': 403, + 'KEY_CHANNELUP': 402, + 'KEY_CHAT': 216, + 'KEY_CLEAR': 355, + 'KEY_CLEARVU_SONAR': 646, + 'KEY_CLOSE': 206, + 'KEY_CLOSECD': 160, + 'KEY_CNT': 768, + 'KEY_COFFEE': 152, + 'KEY_COMMA': 51, + 'KEY_COMPOSE': 127, + 'KEY_COMPUTER': 157, + 'KEY_CONFIG': 171, + 'KEY_CONNECT': 218, + 'KEY_CONTEXT_MENU': 438, + 'KEY_CONTROLPANEL': 579, + 'KEY_COPY': 133, + 'KEY_CUT': 137, + 'KEY_CYCLEWINDOWS': 154, + 'KEY_D': 32, + 'KEY_DASHBOARD': 204, + 'KEY_DATA': 631, + 'KEY_DATABASE': 426, + 'KEY_DELETE': 111, + 'KEY_DELETEFILE': 146, + 'KEY_DEL_EOL': 448, + 'KEY_DEL_EOS': 449, + 'KEY_DEL_LINE': 451, + 'KEY_DICTATE': 586, + 'KEY_DIGITS': 413, + 'KEY_DIRECTION': 153, + 'KEY_DIRECTORY': 394, + 'KEY_DISPLAYTOGGLE': 431, + 'KEY_DISPLAY_OFF': 245, + 'KEY_DOCUMENTS': 235, + 'KEY_DOLLAR': 434, + 'KEY_DOT': 52, + 'KEY_DOWN': 108, + 'KEY_DO_NOT_DISTURB': 591, + 'KEY_DUAL_RANGE_RADAR': 643, + 'KEY_DVD': 389, + 'KEY_E': 18, + 'KEY_EDIT': 176, + 'KEY_EDITOR': 422, + 'KEY_EJECTCD': 161, + 'KEY_EJECTCLOSECD': 162, + 'KEY_EMAIL': 215, + 'KEY_EMOJI_PICKER': 585, + 'KEY_END': 107, + 'KEY_ENTER': 28, + 'KEY_EPG': 365, + 'KEY_EQUAL': 13, + 'KEY_ESC': 1, + 'KEY_EURO': 435, + 'KEY_EXIT': 174, + 'KEY_F': 33, + 'KEY_F1': 59, + 'KEY_F10': 68, + 'KEY_F11': 87, + 'KEY_F12': 88, + 'KEY_F13': 183, + 'KEY_F14': 184, + 'KEY_F15': 185, + 'KEY_F16': 186, + 'KEY_F17': 187, + 'KEY_F18': 188, + 'KEY_F19': 189, + 'KEY_F2': 60, + 'KEY_F20': 190, + 'KEY_F21': 191, + 'KEY_F22': 192, + 'KEY_F23': 193, + 'KEY_F24': 194, + 'KEY_F3': 61, + 'KEY_F4': 62, + 'KEY_F5': 63, + 'KEY_F6': 64, + 'KEY_F7': 65, + 'KEY_F8': 66, + 'KEY_F9': 67, + 'KEY_FASTFORWARD': 208, + 'KEY_FASTREVERSE': 629, + 'KEY_FAVORITES': 364, + 'KEY_FILE': 144, + 'KEY_FINANCE': 219, + 'KEY_FIND': 136, + 'KEY_FIRST': 404, + 'KEY_FISHING_CHART': 641, + 'KEY_FN': 464, + 'KEY_FN_1': 478, + 'KEY_FN_2': 479, + 'KEY_FN_B': 484, + 'KEY_FN_D': 480, + 'KEY_FN_E': 481, + 'KEY_FN_ESC': 465, + 'KEY_FN_F': 482, + 'KEY_FN_F1': 466, + 'KEY_FN_F10': 475, + 'KEY_FN_F11': 476, + 'KEY_FN_F12': 477, + 'KEY_FN_F2': 467, + 'KEY_FN_F3': 468, + 'KEY_FN_F4': 469, + 'KEY_FN_F5': 470, + 'KEY_FN_F6': 471, + 'KEY_FN_F7': 472, + 'KEY_FN_F8': 473, + 'KEY_FN_F9': 474, + 'KEY_FN_RIGHT_SHIFT': 485, + 'KEY_FN_S': 483, + 'KEY_FORWARD': 159, + 'KEY_FORWARDMAIL': 233, + 'KEY_FRAMEBACK': 436, + 'KEY_FRAMEFORWARD': 437, + 'KEY_FRONT': 132, + 'KEY_FULL_SCREEN': 372, + 'KEY_G': 34, + 'KEY_GAMES': 417, + 'KEY_GOTO': 354, + 'KEY_GRAPHICSEDITOR': 424, + 'KEY_GRAVE': 41, + 'KEY_GREEN': 399, + 'KEY_H': 35, + 'KEY_HANGEUL': 122, + 'KEY_HANGUEL': 122, + 'KEY_HANGUP_PHONE': 446, + 'KEY_HANJA': 123, + 'KEY_HELP': 138, + 'KEY_HENKAN': 92, + 'KEY_HIRAGANA': 91, + 'KEY_HOME': 102, + 'KEY_HOMEPAGE': 172, + 'KEY_HP': 211, + 'KEY_I': 23, + 'KEY_IMAGES': 442, + 'KEY_INFO': 358, + 'KEY_INSERT': 110, + 'KEY_INS_LINE': 450, + 'KEY_ISO': 170, + 'KEY_J': 36, + 'KEY_JOURNAL': 578, + 'KEY_K': 37, + 'KEY_KATAKANA': 90, + 'KEY_KATAKANAHIRAGANA': 93, + 'KEY_KBDILLUMDOWN': 229, + 'KEY_KBDILLUMTOGGLE': 228, + 'KEY_KBDILLUMUP': 230, + 'KEY_KBDINPUTASSIST_ACCEPT': 612, + 'KEY_KBDINPUTASSIST_CANCEL': 613, + 'KEY_KBDINPUTASSIST_NEXT': 609, + 'KEY_KBDINPUTASSIST_NEXTGROUP': 611, + 'KEY_KBDINPUTASSIST_PREV': 608, + 'KEY_KBDINPUTASSIST_PREVGROUP': 610, + 'KEY_KBD_LAYOUT_NEXT': 584, + 'KEY_KBD_LCD_MENU1': 696, + 'KEY_KBD_LCD_MENU2': 697, + 'KEY_KBD_LCD_MENU3': 698, + 'KEY_KBD_LCD_MENU4': 699, + 'KEY_KBD_LCD_MENU5': 700, + 'KEY_KEYBOARD': 374, + 'KEY_KP0': 82, + 'KEY_KP1': 79, + 'KEY_KP2': 80, + 'KEY_KP3': 81, + 'KEY_KP4': 75, + 'KEY_KP5': 76, + 'KEY_KP6': 77, + 'KEY_KP7': 71, + 'KEY_KP8': 72, + 'KEY_KP9': 73, + 'KEY_KPASTERISK': 55, + 'KEY_KPCOMMA': 121, + 'KEY_KPDOT': 83, + 'KEY_KPENTER': 96, + 'KEY_KPEQUAL': 117, + 'KEY_KPJPCOMMA': 95, + 'KEY_KPLEFTPAREN': 179, + 'KEY_KPMINUS': 74, + 'KEY_KPPLUS': 78, + 'KEY_KPPLUSMINUS': 118, + 'KEY_KPRIGHTPAREN': 180, + 'KEY_KPSLASH': 98, + 'KEY_L': 38, + 'KEY_LANGUAGE': 368, + 'KEY_LAST': 405, + 'KEY_LEFT': 105, + 'KEY_LEFTALT': 56, + 'KEY_LEFTBRACE': 26, + 'KEY_LEFTCTRL': 29, + 'KEY_LEFTMETA': 125, + 'KEY_LEFTSHIFT': 42, + 'KEY_LEFT_DOWN': 617, + 'KEY_LEFT_UP': 616, + 'KEY_LIGHTS_TOGGLE': 542, + 'KEY_LINEFEED': 101, + 'KEY_LINK_PHONE': 447, + 'KEY_LIST': 395, + 'KEY_LOGOFF': 433, + 'KEY_M': 50, + 'KEY_MACRO': 112, + 'KEY_MACRO1': 656, + 'KEY_MACRO10': 665, + 'KEY_MACRO11': 666, + 'KEY_MACRO12': 667, + 'KEY_MACRO13': 668, + 'KEY_MACRO14': 669, + 'KEY_MACRO15': 670, + 'KEY_MACRO16': 671, + 'KEY_MACRO17': 672, + 'KEY_MACRO18': 673, + 'KEY_MACRO19': 674, + 'KEY_MACRO2': 657, + 'KEY_MACRO20': 675, + 'KEY_MACRO21': 676, + 'KEY_MACRO22': 677, + 'KEY_MACRO23': 678, + 'KEY_MACRO24': 679, + 'KEY_MACRO25': 680, + 'KEY_MACRO26': 681, + 'KEY_MACRO27': 682, + 'KEY_MACRO28': 683, + 'KEY_MACRO29': 684, + 'KEY_MACRO3': 658, + 'KEY_MACRO30': 685, + 'KEY_MACRO4': 659, + 'KEY_MACRO5': 660, + 'KEY_MACRO6': 661, + 'KEY_MACRO7': 662, + 'KEY_MACRO8': 663, + 'KEY_MACRO9': 664, + 'KEY_MACRO_PRESET1': 691, + 'KEY_MACRO_PRESET2': 692, + 'KEY_MACRO_PRESET3': 693, + 'KEY_MACRO_PRESET_CYCLE': 690, + 'KEY_MACRO_RECORD_START': 688, + 'KEY_MACRO_RECORD_STOP': 689, + 'KEY_MAIL': 155, + 'KEY_MARK_WAYPOINT': 638, + 'KEY_MAX': 767, + 'KEY_MEDIA': 226, + 'KEY_MEDIA_REPEAT': 439, + 'KEY_MEDIA_TOP_MENU': 619, + 'KEY_MEMO': 396, + 'KEY_MENU': 139, + 'KEY_MESSENGER': 430, + 'KEY_MHP': 367, + 'KEY_MICMUTE': 248, + 'KEY_MINUS': 12, + 'KEY_MIN_INTERESTING': 113, + 'KEY_MODE': 373, + 'KEY_MOVE': 175, + 'KEY_MP3': 391, + 'KEY_MSDOS': 151, + 'KEY_MUHENKAN': 94, + 'KEY_MUTE': 113, + 'KEY_N': 49, + 'KEY_NAV_CHART': 640, + 'KEY_NAV_INFO': 648, + 'KEY_NEW': 181, + 'KEY_NEWS': 427, + 'KEY_NEXT': 407, + 'KEY_NEXTSONG': 163, + 'KEY_NEXT_ELEMENT': 635, + 'KEY_NEXT_FAVORITE': 624, + 'KEY_NOTIFICATION_CENTER': 444, + 'KEY_NUMERIC_0': 512, + 'KEY_NUMERIC_1': 513, + 'KEY_NUMERIC_11': 620, + 'KEY_NUMERIC_12': 621, + 'KEY_NUMERIC_2': 514, + 'KEY_NUMERIC_3': 515, + 'KEY_NUMERIC_4': 516, + 'KEY_NUMERIC_5': 517, + 'KEY_NUMERIC_6': 518, + 'KEY_NUMERIC_7': 519, + 'KEY_NUMERIC_8': 520, + 'KEY_NUMERIC_9': 521, + 'KEY_NUMERIC_A': 524, + 'KEY_NUMERIC_B': 525, + 'KEY_NUMERIC_C': 526, + 'KEY_NUMERIC_D': 527, + 'KEY_NUMERIC_POUND': 523, + 'KEY_NUMERIC_STAR': 522, + 'KEY_NUMLOCK': 69, + 'KEY_O': 24, + 'KEY_OK': 352, + 'KEY_ONSCREEN_KEYBOARD': 632, + 'KEY_OPEN': 134, + 'KEY_OPTION': 357, + 'KEY_P': 25, + 'KEY_PAGEDOWN': 109, + 'KEY_PAGEUP': 104, + 'KEY_PASTE': 135, + 'KEY_PAUSE': 119, + 'KEY_PAUSECD': 201, + 'KEY_PAUSE_RECORD': 626, + 'KEY_PC': 376, + 'KEY_PHONE': 169, + 'KEY_PICKUP_PHONE': 445, + 'KEY_PLAY': 207, + 'KEY_PLAYCD': 200, + 'KEY_PLAYER': 387, + 'KEY_PLAYPAUSE': 164, + 'KEY_POWER': 116, + 'KEY_POWER2': 356, + 'KEY_PRESENTATION': 425, + 'KEY_PREVIOUS': 412, + 'KEY_PREVIOUSSONG': 165, + 'KEY_PREVIOUS_ELEMENT': 636, + 'KEY_PRINT': 210, + 'KEY_PRIVACY_SCREEN_TOGGLE': 633, + 'KEY_PROG1': 148, + 'KEY_PROG2': 149, + 'KEY_PROG3': 202, + 'KEY_PROG4': 203, + 'KEY_PROGRAM': 362, + 'KEY_PROPS': 130, + 'KEY_PVR': 366, + 'KEY_Q': 16, + 'KEY_QUESTION': 214, + 'KEY_R': 19, + 'KEY_RADAR_OVERLAY': 644, + 'KEY_RADIO': 385, + 'KEY_RECORD': 167, + 'KEY_RED': 398, + 'KEY_REDO': 182, + 'KEY_REFRESH': 173, + 'KEY_REFRESH_RATE_TOGGLE': 562, + 'KEY_REPLY': 232, + 'KEY_RESERVED': 0, + 'KEY_RESTART': 408, + 'KEY_REWIND': 168, + 'KEY_RFKILL': 247, + 'KEY_RIGHT': 106, + 'KEY_RIGHTALT': 100, + 'KEY_RIGHTBRACE': 27, + 'KEY_RIGHTCTRL': 97, + 'KEY_RIGHTMETA': 126, + 'KEY_RIGHTSHIFT': 54, + 'KEY_RIGHT_DOWN': 615, + 'KEY_RIGHT_UP': 614, + 'KEY_RO': 89, + 'KEY_ROOT_MENU': 618, + 'KEY_ROTATE_DISPLAY': 153, + 'KEY_ROTATE_LOCK_TOGGLE': 561, + 'KEY_S': 31, + 'KEY_SAT': 381, + 'KEY_SAT2': 382, + 'KEY_SAVE': 234, + 'KEY_SCALE': 120, + 'KEY_SCREEN': 375, + 'KEY_SCREENLOCK': 152, + 'KEY_SCREENSAVER': 581, + 'KEY_SCROLLDOWN': 178, + 'KEY_SCROLLLOCK': 70, + 'KEY_SCROLLUP': 177, + 'KEY_SEARCH': 217, + 'KEY_SELECT': 353, + 'KEY_SELECTIVE_SCREENSHOT': 634, + 'KEY_SEMICOLON': 39, + 'KEY_SEND': 231, + 'KEY_SENDFILE': 145, + 'KEY_SETUP': 141, + 'KEY_SHOP': 221, + 'KEY_SHUFFLE': 410, + 'KEY_SIDEVU_SONAR': 647, + 'KEY_SINGLE_RANGE_RADAR': 642, + 'KEY_SLASH': 53, + 'KEY_SLEEP': 142, + 'KEY_SLOW': 409, + 'KEY_SLOWREVERSE': 630, + 'KEY_SOS': 639, + 'KEY_SOUND': 213, + 'KEY_SPACE': 57, + 'KEY_SPELLCHECK': 432, + 'KEY_SPORT': 220, + 'KEY_SPREADSHEET': 423, + 'KEY_STOP': 128, + 'KEY_STOPCD': 166, + 'KEY_STOP_RECORD': 625, + 'KEY_SUBTITLE': 370, + 'KEY_SUSPEND': 205, + 'KEY_SWITCHVIDEOMODE': 227, + 'KEY_SYSRQ': 99, + 'KEY_T': 20, + 'KEY_TAB': 15, + 'KEY_TAPE': 384, + 'KEY_TASKMANAGER': 577, + 'KEY_TEEN': 414, + 'KEY_TEXT': 388, + 'KEY_TIME': 359, + 'KEY_TITLE': 369, + 'KEY_TOUCHPAD_OFF': 532, + 'KEY_TOUCHPAD_ON': 531, + 'KEY_TOUCHPAD_TOGGLE': 530, + 'KEY_TRADITIONAL_SONAR': 645, + 'KEY_TUNER': 386, + 'KEY_TV': 377, + 'KEY_TV2': 378, + 'KEY_TWEN': 415, + 'KEY_U': 22, + 'KEY_UNDO': 131, + 'KEY_UNKNOWN': 240, + 'KEY_UNMUTE': 628, + 'KEY_UP': 103, + 'KEY_UWB': 239, + 'KEY_V': 47, + 'KEY_VCR': 379, + 'KEY_VCR2': 380, + 'KEY_VENDOR': 360, + 'KEY_VIDEO': 393, + 'KEY_VIDEOPHONE': 416, + 'KEY_VIDEO_NEXT': 241, + 'KEY_VIDEO_PREV': 242, + 'KEY_VOD': 627, + 'KEY_VOICECOMMAND': 582, + 'KEY_VOICEMAIL': 428, + 'KEY_VOLUMEDOWN': 114, + 'KEY_VOLUMEUP': 115, + 'KEY_W': 17, + 'KEY_WAKEUP': 143, + 'KEY_WIMAX': 246, + 'KEY_WLAN': 238, + 'KEY_WORDPROCESSOR': 421, + 'KEY_WPS_BUTTON': 529, + 'KEY_WWAN': 246, + 'KEY_WWW': 150, + 'KEY_X': 45, + 'KEY_XFER': 147, + 'KEY_Y': 21, + 'KEY_YELLOW': 400, + 'KEY_YEN': 124, + 'KEY_Z': 44, + 'KEY_ZENKAKUHANKAKU': 85, + 'KEY_ZOOM': 372, + 'KEY_ZOOMIN': 418, + 'KEY_ZOOMOUT': 419, + 'KEY_ZOOMRESET': 420, + 'LED_CAPSL': 1, + 'LED_CHARGING': 10, + 'LED_CNT': 16, + 'LED_COMPOSE': 3, + 'LED_KANA': 4, + 'LED_MAIL': 9, + 'LED_MAX': 15, + 'LED_MISC': 8, + 'LED_MUTE': 7, + 'LED_NUML': 0, + 'LED_SCROLLL': 2, + 'LED_SLEEP': 5, + 'LED_SUSPEND': 6, + 'MSC_CNT': 8, + 'MSC_GESTURE': 2, + 'MSC_MAX': 7, + 'MSC_PULSELED': 1, + 'MSC_RAW': 3, + 'MSC_SCAN': 4, + 'MSC_SERIAL': 0, + 'MSC_TIMESTAMP': 5, + 'REL_CNT': 16, + 'REL_DIAL': 7, + 'REL_HWHEEL': 6, + 'REL_HWHEEL_HI_RES': 12, + 'REL_MAX': 15, + 'REL_MISC': 9, + 'REL_RESERVED': 10, + 'REL_RX': 3, + 'REL_RY': 4, + 'REL_RZ': 5, + 'REL_WHEEL': 8, + 'REL_WHEEL_HI_RES': 11, + 'REL_X': 0, + 'REL_Y': 1, + 'REL_Z': 2, + 'REP_CNT': 2, + 'REP_DELAY': 0, + 'REP_MAX': 1, + 'REP_PERIOD': 1, + 'SND_BELL': 1, + 'SND_CLICK': 0, + 'SND_CNT': 8, + 'SND_MAX': 7, + 'SND_TONE': 2, + 'SW_CAMERA_LENS_COVER': 9, + 'SW_CNT': 17, + 'SW_DOCK': 5, + 'SW_FRONT_PROXIMITY': 11, + 'SW_HEADPHONE_INSERT': 2, + 'SW_JACK_PHYSICAL_INSERT': 7, + 'SW_KEYPAD_SLIDE': 10, + 'SW_LID': 0, + 'SW_LINEIN_INSERT': 13, + 'SW_LINEOUT_INSERT': 6, + 'SW_MACHINE_COVER': 16, + 'SW_MAX': 16, + 'SW_MICROPHONE_INSERT': 4, + 'SW_MUTE_DEVICE': 14, + 'SW_PEN_INSERTED': 15, + 'SW_RADIO': 3, + 'SW_RFKILL_ALL': 3, + 'SW_ROTATE_LOCK': 12, + 'SW_TABLET_MODE': 1, + 'SW_VIDEOOUT_INSERT': 8, + 'SYN_CNT': 16, + 'SYN_CONFIG': 1, + 'SYN_DROPPED': 3, + 'SYN_MAX': 15, + 'SYN_MT_REPORT': 2, + 'SYN_REPORT': 0, + 'UI_FF_ERASE': 2, + 'UI_FF_UPLOAD': 1} + +#: Mapping of event types to other value/name mappings. +bytype: Dict[int, Dict[int, Union[str, Tuple[str]]]] = { 0: {0: 'SYN_REPORT', 1: 'SYN_CONFIG', 2: 'SYN_MT_REPORT', 3: 'SYN_DROPPED', 15: 'SYN_MAX', 16: 'SYN_CNT'}, + 1: { 0: 'KEY_RESERVED', + 1: 'KEY_ESC', + 2: 'KEY_1', + 3: 'KEY_2', + 4: 'KEY_3', + 5: 'KEY_4', + 6: 'KEY_5', + 7: 'KEY_6', + 8: 'KEY_7', + 9: 'KEY_8', + 10: 'KEY_9', + 11: 'KEY_0', + 12: 'KEY_MINUS', + 13: 'KEY_EQUAL', + 14: 'KEY_BACKSPACE', + 15: 'KEY_TAB', + 16: 'KEY_Q', + 17: 'KEY_W', + 18: 'KEY_E', + 19: 'KEY_R', + 20: 'KEY_T', + 21: 'KEY_Y', + 22: 'KEY_U', + 23: 'KEY_I', + 24: 'KEY_O', + 25: 'KEY_P', + 26: 'KEY_LEFTBRACE', + 27: 'KEY_RIGHTBRACE', + 28: 'KEY_ENTER', + 29: 'KEY_LEFTCTRL', + 30: 'KEY_A', + 31: 'KEY_S', + 32: 'KEY_D', + 33: 'KEY_F', + 34: 'KEY_G', + 35: 'KEY_H', + 36: 'KEY_J', + 37: 'KEY_K', + 38: 'KEY_L', + 39: 'KEY_SEMICOLON', + 40: 'KEY_APOSTROPHE', + 41: 'KEY_GRAVE', + 42: 'KEY_LEFTSHIFT', + 43: 'KEY_BACKSLASH', + 44: 'KEY_Z', + 45: 'KEY_X', + 46: 'KEY_C', + 47: 'KEY_V', + 48: 'KEY_B', + 49: 'KEY_N', + 50: 'KEY_M', + 51: 'KEY_COMMA', + 52: 'KEY_DOT', + 53: 'KEY_SLASH', + 54: 'KEY_RIGHTSHIFT', + 55: 'KEY_KPASTERISK', + 56: 'KEY_LEFTALT', + 57: 'KEY_SPACE', + 58: 'KEY_CAPSLOCK', + 59: 'KEY_F1', + 60: 'KEY_F2', + 61: 'KEY_F3', + 62: 'KEY_F4', + 63: 'KEY_F5', + 64: 'KEY_F6', + 65: 'KEY_F7', + 66: 'KEY_F8', + 67: 'KEY_F9', + 68: 'KEY_F10', + 69: 'KEY_NUMLOCK', + 70: 'KEY_SCROLLLOCK', + 71: 'KEY_KP7', + 72: 'KEY_KP8', + 73: 'KEY_KP9', + 74: 'KEY_KPMINUS', + 75: 'KEY_KP4', + 76: 'KEY_KP5', + 77: 'KEY_KP6', + 78: 'KEY_KPPLUS', + 79: 'KEY_KP1', + 80: 'KEY_KP2', + 81: 'KEY_KP3', + 82: 'KEY_KP0', + 83: 'KEY_KPDOT', + 85: 'KEY_ZENKAKUHANKAKU', + 86: 'KEY_102ND', + 87: 'KEY_F11', + 88: 'KEY_F12', + 89: 'KEY_RO', + 90: 'KEY_KATAKANA', + 91: 'KEY_HIRAGANA', + 92: 'KEY_HENKAN', + 93: 'KEY_KATAKANAHIRAGANA', + 94: 'KEY_MUHENKAN', + 95: 'KEY_KPJPCOMMA', + 96: 'KEY_KPENTER', + 97: 'KEY_RIGHTCTRL', + 98: 'KEY_KPSLASH', + 99: 'KEY_SYSRQ', + 100: 'KEY_RIGHTALT', + 101: 'KEY_LINEFEED', + 102: 'KEY_HOME', + 103: 'KEY_UP', + 104: 'KEY_PAGEUP', + 105: 'KEY_LEFT', + 106: 'KEY_RIGHT', + 107: 'KEY_END', + 108: 'KEY_DOWN', + 109: 'KEY_PAGEDOWN', + 110: 'KEY_INSERT', + 111: 'KEY_DELETE', + 112: 'KEY_MACRO', + 113: ('KEY_MIN_INTERESTING', 'KEY_MUTE'), + 114: 'KEY_VOLUMEDOWN', + 115: 'KEY_VOLUMEUP', + 116: 'KEY_POWER', + 117: 'KEY_KPEQUAL', + 118: 'KEY_KPPLUSMINUS', + 119: 'KEY_PAUSE', + 120: 'KEY_SCALE', + 121: 'KEY_KPCOMMA', + 122: ('KEY_HANGEUL', 'KEY_HANGUEL'), + 123: 'KEY_HANJA', + 124: 'KEY_YEN', + 125: 'KEY_LEFTMETA', + 126: 'KEY_RIGHTMETA', + 127: 'KEY_COMPOSE', + 128: 'KEY_STOP', + 129: 'KEY_AGAIN', + 130: 'KEY_PROPS', + 131: 'KEY_UNDO', + 132: 'KEY_FRONT', + 133: 'KEY_COPY', + 134: 'KEY_OPEN', + 135: 'KEY_PASTE', + 136: 'KEY_FIND', + 137: 'KEY_CUT', + 138: 'KEY_HELP', + 139: 'KEY_MENU', + 140: 'KEY_CALC', + 141: 'KEY_SETUP', + 142: 'KEY_SLEEP', + 143: 'KEY_WAKEUP', + 144: 'KEY_FILE', + 145: 'KEY_SENDFILE', + 146: 'KEY_DELETEFILE', + 147: 'KEY_XFER', + 148: 'KEY_PROG1', + 149: 'KEY_PROG2', + 150: 'KEY_WWW', + 151: 'KEY_MSDOS', + 152: ('KEY_COFFEE', 'KEY_SCREENLOCK'), + 153: ('KEY_DIRECTION', 'KEY_ROTATE_DISPLAY'), + 154: 'KEY_CYCLEWINDOWS', + 155: 'KEY_MAIL', + 156: 'KEY_BOOKMARKS', + 157: 'KEY_COMPUTER', + 158: 'KEY_BACK', + 159: 'KEY_FORWARD', + 160: 'KEY_CLOSECD', + 161: 'KEY_EJECTCD', + 162: 'KEY_EJECTCLOSECD', + 163: 'KEY_NEXTSONG', + 164: 'KEY_PLAYPAUSE', + 165: 'KEY_PREVIOUSSONG', + 166: 'KEY_STOPCD', + 167: 'KEY_RECORD', + 168: 'KEY_REWIND', + 169: 'KEY_PHONE', + 170: 'KEY_ISO', + 171: 'KEY_CONFIG', + 172: 'KEY_HOMEPAGE', + 173: 'KEY_REFRESH', + 174: 'KEY_EXIT', + 175: 'KEY_MOVE', + 176: 'KEY_EDIT', + 177: 'KEY_SCROLLUP', + 178: 'KEY_SCROLLDOWN', + 179: 'KEY_KPLEFTPAREN', + 180: 'KEY_KPRIGHTPAREN', + 181: 'KEY_NEW', + 182: 'KEY_REDO', + 183: 'KEY_F13', + 184: 'KEY_F14', + 185: 'KEY_F15', + 186: 'KEY_F16', + 187: 'KEY_F17', + 188: 'KEY_F18', + 189: 'KEY_F19', + 190: 'KEY_F20', + 191: 'KEY_F21', + 192: 'KEY_F22', + 193: 'KEY_F23', + 194: 'KEY_F24', + 200: 'KEY_PLAYCD', + 201: 'KEY_PAUSECD', + 202: 'KEY_PROG3', + 203: 'KEY_PROG4', + 204: ('KEY_ALL_APPLICATIONS', 'KEY_DASHBOARD'), + 205: 'KEY_SUSPEND', + 206: 'KEY_CLOSE', + 207: 'KEY_PLAY', + 208: 'KEY_FASTFORWARD', + 209: 'KEY_BASSBOOST', + 210: 'KEY_PRINT', + 211: 'KEY_HP', + 212: 'KEY_CAMERA', + 213: 'KEY_SOUND', + 214: 'KEY_QUESTION', + 215: 'KEY_EMAIL', + 216: 'KEY_CHAT', + 217: 'KEY_SEARCH', + 218: 'KEY_CONNECT', + 219: 'KEY_FINANCE', + 220: 'KEY_SPORT', + 221: 'KEY_SHOP', + 222: 'KEY_ALTERASE', + 223: 'KEY_CANCEL', + 224: 'KEY_BRIGHTNESSDOWN', + 225: 'KEY_BRIGHTNESSUP', + 226: 'KEY_MEDIA', + 227: 'KEY_SWITCHVIDEOMODE', + 228: 'KEY_KBDILLUMTOGGLE', + 229: 'KEY_KBDILLUMDOWN', + 230: 'KEY_KBDILLUMUP', + 231: 'KEY_SEND', + 232: 'KEY_REPLY', + 233: 'KEY_FORWARDMAIL', + 234: 'KEY_SAVE', + 235: 'KEY_DOCUMENTS', + 236: 'KEY_BATTERY', + 237: 'KEY_BLUETOOTH', + 238: 'KEY_WLAN', + 239: 'KEY_UWB', + 240: 'KEY_UNKNOWN', + 241: 'KEY_VIDEO_NEXT', + 242: 'KEY_VIDEO_PREV', + 243: 'KEY_BRIGHTNESS_CYCLE', + 244: ('KEY_BRIGHTNESS_AUTO', 'KEY_BRIGHTNESS_ZERO'), + 245: 'KEY_DISPLAY_OFF', + 246: ('KEY_WIMAX', 'KEY_WWAN'), + 247: 'KEY_RFKILL', + 248: 'KEY_MICMUTE', + 256: ('BTN_0', 'BTN_MISC'), + 257: 'BTN_1', + 258: 'BTN_2', + 259: 'BTN_3', + 260: 'BTN_4', + 261: 'BTN_5', + 262: 'BTN_6', + 263: 'BTN_7', + 264: 'BTN_8', + 265: 'BTN_9', + 272: ('BTN_LEFT', 'BTN_MOUSE'), + 273: 'BTN_RIGHT', + 274: 'BTN_MIDDLE', + 275: 'BTN_SIDE', + 276: 'BTN_EXTRA', + 277: 'BTN_FORWARD', + 278: 'BTN_BACK', + 279: 'BTN_TASK', + 288: ('BTN_JOYSTICK', 'BTN_TRIGGER'), + 289: 'BTN_THUMB', + 290: 'BTN_THUMB2', + 291: 'BTN_TOP', + 292: 'BTN_TOP2', + 293: 'BTN_PINKIE', + 294: 'BTN_BASE', + 295: 'BTN_BASE2', + 296: 'BTN_BASE3', + 297: 'BTN_BASE4', + 298: 'BTN_BASE5', + 299: 'BTN_BASE6', + 303: 'BTN_DEAD', + 304: ('BTN_A', 'BTN_GAMEPAD', 'BTN_SOUTH'), + 305: ('BTN_B', 'BTN_EAST'), + 306: 'BTN_C', + 307: ('BTN_NORTH', 'BTN_X'), + 308: ('BTN_WEST', 'BTN_Y'), + 309: 'BTN_Z', + 310: 'BTN_TL', + 311: 'BTN_TR', + 312: 'BTN_TL2', + 313: 'BTN_TR2', + 314: 'BTN_SELECT', + 315: 'BTN_START', + 316: 'BTN_MODE', + 317: 'BTN_THUMBL', + 318: 'BTN_THUMBR', + 320: ('BTN_DIGI', 'BTN_TOOL_PEN'), + 321: 'BTN_TOOL_RUBBER', + 322: 'BTN_TOOL_BRUSH', + 323: 'BTN_TOOL_PENCIL', + 324: 'BTN_TOOL_AIRBRUSH', + 325: 'BTN_TOOL_FINGER', + 326: 'BTN_TOOL_MOUSE', + 327: 'BTN_TOOL_LENS', + 328: 'BTN_TOOL_QUINTTAP', + 329: 'BTN_STYLUS3', + 330: 'BTN_TOUCH', + 331: 'BTN_STYLUS', + 332: 'BTN_STYLUS2', + 333: 'BTN_TOOL_DOUBLETAP', + 334: 'BTN_TOOL_TRIPLETAP', + 335: 'BTN_TOOL_QUADTAP', + 336: ('BTN_GEAR_DOWN', 'BTN_WHEEL'), + 337: 'BTN_GEAR_UP', + 352: 'KEY_OK', + 353: 'KEY_SELECT', + 354: 'KEY_GOTO', + 355: 'KEY_CLEAR', + 356: 'KEY_POWER2', + 357: 'KEY_OPTION', + 358: 'KEY_INFO', + 359: 'KEY_TIME', + 360: 'KEY_VENDOR', + 361: 'KEY_ARCHIVE', + 362: 'KEY_PROGRAM', + 363: 'KEY_CHANNEL', + 364: 'KEY_FAVORITES', + 365: 'KEY_EPG', + 366: 'KEY_PVR', + 367: 'KEY_MHP', + 368: 'KEY_LANGUAGE', + 369: 'KEY_TITLE', + 370: 'KEY_SUBTITLE', + 371: 'KEY_ANGLE', + 372: ('KEY_FULL_SCREEN', 'KEY_ZOOM'), + 373: 'KEY_MODE', + 374: 'KEY_KEYBOARD', + 375: ('KEY_ASPECT_RATIO', 'KEY_SCREEN'), + 376: 'KEY_PC', + 377: 'KEY_TV', + 378: 'KEY_TV2', + 379: 'KEY_VCR', + 380: 'KEY_VCR2', + 381: 'KEY_SAT', + 382: 'KEY_SAT2', + 383: 'KEY_CD', + 384: 'KEY_TAPE', + 385: 'KEY_RADIO', + 386: 'KEY_TUNER', + 387: 'KEY_PLAYER', + 388: 'KEY_TEXT', + 389: 'KEY_DVD', + 390: 'KEY_AUX', + 391: 'KEY_MP3', + 392: 'KEY_AUDIO', + 393: 'KEY_VIDEO', + 394: 'KEY_DIRECTORY', + 395: 'KEY_LIST', + 396: 'KEY_MEMO', + 397: 'KEY_CALENDAR', + 398: 'KEY_RED', + 399: 'KEY_GREEN', + 400: 'KEY_YELLOW', + 401: 'KEY_BLUE', + 402: 'KEY_CHANNELUP', + 403: 'KEY_CHANNELDOWN', + 404: 'KEY_FIRST', + 405: 'KEY_LAST', + 406: 'KEY_AB', + 407: 'KEY_NEXT', + 408: 'KEY_RESTART', + 409: 'KEY_SLOW', + 410: 'KEY_SHUFFLE', + 411: 'KEY_BREAK', + 412: 'KEY_PREVIOUS', + 413: 'KEY_DIGITS', + 414: 'KEY_TEEN', + 415: 'KEY_TWEN', + 416: 'KEY_VIDEOPHONE', + 417: 'KEY_GAMES', + 418: 'KEY_ZOOMIN', + 419: 'KEY_ZOOMOUT', + 420: 'KEY_ZOOMRESET', + 421: 'KEY_WORDPROCESSOR', + 422: 'KEY_EDITOR', + 423: 'KEY_SPREADSHEET', + 424: 'KEY_GRAPHICSEDITOR', + 425: 'KEY_PRESENTATION', + 426: 'KEY_DATABASE', + 427: 'KEY_NEWS', + 428: 'KEY_VOICEMAIL', + 429: 'KEY_ADDRESSBOOK', + 430: 'KEY_MESSENGER', + 431: ('KEY_BRIGHTNESS_TOGGLE', 'KEY_DISPLAYTOGGLE'), + 432: 'KEY_SPELLCHECK', + 433: 'KEY_LOGOFF', + 434: 'KEY_DOLLAR', + 435: 'KEY_EURO', + 436: 'KEY_FRAMEBACK', + 437: 'KEY_FRAMEFORWARD', + 438: 'KEY_CONTEXT_MENU', + 439: 'KEY_MEDIA_REPEAT', + 440: 'KEY_10CHANNELSUP', + 441: 'KEY_10CHANNELSDOWN', + 442: 'KEY_IMAGES', + 444: 'KEY_NOTIFICATION_CENTER', + 445: 'KEY_PICKUP_PHONE', + 446: 'KEY_HANGUP_PHONE', + 447: 'KEY_LINK_PHONE', + 448: 'KEY_DEL_EOL', + 449: 'KEY_DEL_EOS', + 450: 'KEY_INS_LINE', + 451: 'KEY_DEL_LINE', + 464: 'KEY_FN', + 465: 'KEY_FN_ESC', + 466: 'KEY_FN_F1', + 467: 'KEY_FN_F2', + 468: 'KEY_FN_F3', + 469: 'KEY_FN_F4', + 470: 'KEY_FN_F5', + 471: 'KEY_FN_F6', + 472: 'KEY_FN_F7', + 473: 'KEY_FN_F8', + 474: 'KEY_FN_F9', + 475: 'KEY_FN_F10', + 476: 'KEY_FN_F11', + 477: 'KEY_FN_F12', + 478: 'KEY_FN_1', + 479: 'KEY_FN_2', + 480: 'KEY_FN_D', + 481: 'KEY_FN_E', + 482: 'KEY_FN_F', + 483: 'KEY_FN_S', + 484: 'KEY_FN_B', + 485: 'KEY_FN_RIGHT_SHIFT', + 497: 'KEY_BRL_DOT1', + 498: 'KEY_BRL_DOT2', + 499: 'KEY_BRL_DOT3', + 500: 'KEY_BRL_DOT4', + 501: 'KEY_BRL_DOT5', + 502: 'KEY_BRL_DOT6', + 503: 'KEY_BRL_DOT7', + 504: 'KEY_BRL_DOT8', + 505: 'KEY_BRL_DOT9', + 506: 'KEY_BRL_DOT10', + 512: 'KEY_NUMERIC_0', + 513: 'KEY_NUMERIC_1', + 514: 'KEY_NUMERIC_2', + 515: 'KEY_NUMERIC_3', + 516: 'KEY_NUMERIC_4', + 517: 'KEY_NUMERIC_5', + 518: 'KEY_NUMERIC_6', + 519: 'KEY_NUMERIC_7', + 520: 'KEY_NUMERIC_8', + 521: 'KEY_NUMERIC_9', + 522: 'KEY_NUMERIC_STAR', + 523: 'KEY_NUMERIC_POUND', + 524: 'KEY_NUMERIC_A', + 525: 'KEY_NUMERIC_B', + 526: 'KEY_NUMERIC_C', + 527: 'KEY_NUMERIC_D', + 528: 'KEY_CAMERA_FOCUS', + 529: 'KEY_WPS_BUTTON', + 530: 'KEY_TOUCHPAD_TOGGLE', + 531: 'KEY_TOUCHPAD_ON', + 532: 'KEY_TOUCHPAD_OFF', + 533: 'KEY_CAMERA_ZOOMIN', + 534: 'KEY_CAMERA_ZOOMOUT', + 535: 'KEY_CAMERA_UP', + 536: 'KEY_CAMERA_DOWN', + 537: 'KEY_CAMERA_LEFT', + 538: 'KEY_CAMERA_RIGHT', + 539: 'KEY_ATTENDANT_ON', + 540: 'KEY_ATTENDANT_OFF', + 541: 'KEY_ATTENDANT_TOGGLE', + 542: 'KEY_LIGHTS_TOGGLE', + 544: 'BTN_DPAD_UP', + 545: 'BTN_DPAD_DOWN', + 546: 'BTN_DPAD_LEFT', + 547: 'BTN_DPAD_RIGHT', + 560: 'KEY_ALS_TOGGLE', + 561: 'KEY_ROTATE_LOCK_TOGGLE', + 562: 'KEY_REFRESH_RATE_TOGGLE', + 576: 'KEY_BUTTONCONFIG', + 577: 'KEY_TASKMANAGER', + 578: 'KEY_JOURNAL', + 579: 'KEY_CONTROLPANEL', + 580: 'KEY_APPSELECT', + 581: 'KEY_SCREENSAVER', + 582: 'KEY_VOICECOMMAND', + 583: 'KEY_ASSISTANT', + 584: 'KEY_KBD_LAYOUT_NEXT', + 585: 'KEY_EMOJI_PICKER', + 586: 'KEY_DICTATE', + 587: 'KEY_CAMERA_ACCESS_ENABLE', + 588: 'KEY_CAMERA_ACCESS_DISABLE', + 589: 'KEY_CAMERA_ACCESS_TOGGLE', + 590: 'KEY_ACCESSIBILITY', + 591: 'KEY_DO_NOT_DISTURB', + 592: 'KEY_BRIGHTNESS_MIN', + 593: 'KEY_BRIGHTNESS_MAX', + 608: 'KEY_KBDINPUTASSIST_PREV', + 609: 'KEY_KBDINPUTASSIST_NEXT', + 610: 'KEY_KBDINPUTASSIST_PREVGROUP', + 611: 'KEY_KBDINPUTASSIST_NEXTGROUP', + 612: 'KEY_KBDINPUTASSIST_ACCEPT', + 613: 'KEY_KBDINPUTASSIST_CANCEL', + 614: 'KEY_RIGHT_UP', + 615: 'KEY_RIGHT_DOWN', + 616: 'KEY_LEFT_UP', + 617: 'KEY_LEFT_DOWN', + 618: 'KEY_ROOT_MENU', + 619: 'KEY_MEDIA_TOP_MENU', + 620: 'KEY_NUMERIC_11', + 621: 'KEY_NUMERIC_12', + 622: 'KEY_AUDIO_DESC', + 623: 'KEY_3D_MODE', + 624: 'KEY_NEXT_FAVORITE', + 625: 'KEY_STOP_RECORD', + 626: 'KEY_PAUSE_RECORD', + 627: 'KEY_VOD', + 628: 'KEY_UNMUTE', + 629: 'KEY_FASTREVERSE', + 630: 'KEY_SLOWREVERSE', + 631: 'KEY_DATA', + 632: 'KEY_ONSCREEN_KEYBOARD', + 633: 'KEY_PRIVACY_SCREEN_TOGGLE', + 634: 'KEY_SELECTIVE_SCREENSHOT', + 635: 'KEY_NEXT_ELEMENT', + 636: 'KEY_PREVIOUS_ELEMENT', + 637: 'KEY_AUTOPILOT_ENGAGE_TOGGLE', + 638: 'KEY_MARK_WAYPOINT', + 639: 'KEY_SOS', + 640: 'KEY_NAV_CHART', + 641: 'KEY_FISHING_CHART', + 642: 'KEY_SINGLE_RANGE_RADAR', + 643: 'KEY_DUAL_RANGE_RADAR', + 644: 'KEY_RADAR_OVERLAY', + 645: 'KEY_TRADITIONAL_SONAR', + 646: 'KEY_CLEARVU_SONAR', + 647: 'KEY_SIDEVU_SONAR', + 648: 'KEY_NAV_INFO', + 649: 'KEY_BRIGHTNESS_MENU', + 656: 'KEY_MACRO1', + 657: 'KEY_MACRO2', + 658: 'KEY_MACRO3', + 659: 'KEY_MACRO4', + 660: 'KEY_MACRO5', + 661: 'KEY_MACRO6', + 662: 'KEY_MACRO7', + 663: 'KEY_MACRO8', + 664: 'KEY_MACRO9', + 665: 'KEY_MACRO10', + 666: 'KEY_MACRO11', + 667: 'KEY_MACRO12', + 668: 'KEY_MACRO13', + 669: 'KEY_MACRO14', + 670: 'KEY_MACRO15', + 671: 'KEY_MACRO16', + 672: 'KEY_MACRO17', + 673: 'KEY_MACRO18', + 674: 'KEY_MACRO19', + 675: 'KEY_MACRO20', + 676: 'KEY_MACRO21', + 677: 'KEY_MACRO22', + 678: 'KEY_MACRO23', + 679: 'KEY_MACRO24', + 680: 'KEY_MACRO25', + 681: 'KEY_MACRO26', + 682: 'KEY_MACRO27', + 683: 'KEY_MACRO28', + 684: 'KEY_MACRO29', + 685: 'KEY_MACRO30', + 688: 'KEY_MACRO_RECORD_START', + 689: 'KEY_MACRO_RECORD_STOP', + 690: 'KEY_MACRO_PRESET_CYCLE', + 691: 'KEY_MACRO_PRESET1', + 692: 'KEY_MACRO_PRESET2', + 693: 'KEY_MACRO_PRESET3', + 696: 'KEY_KBD_LCD_MENU1', + 697: 'KEY_KBD_LCD_MENU2', + 698: 'KEY_KBD_LCD_MENU3', + 699: 'KEY_KBD_LCD_MENU4', + 700: 'KEY_KBD_LCD_MENU5', + 704: ('BTN_TRIGGER_HAPPY', 'BTN_TRIGGER_HAPPY1'), + 705: 'BTN_TRIGGER_HAPPY2', + 706: 'BTN_TRIGGER_HAPPY3', + 707: 'BTN_TRIGGER_HAPPY4', + 708: 'BTN_TRIGGER_HAPPY5', + 709: 'BTN_TRIGGER_HAPPY6', + 710: 'BTN_TRIGGER_HAPPY7', + 711: 'BTN_TRIGGER_HAPPY8', + 712: 'BTN_TRIGGER_HAPPY9', + 713: 'BTN_TRIGGER_HAPPY10', + 714: 'BTN_TRIGGER_HAPPY11', + 715: 'BTN_TRIGGER_HAPPY12', + 716: 'BTN_TRIGGER_HAPPY13', + 717: 'BTN_TRIGGER_HAPPY14', + 718: 'BTN_TRIGGER_HAPPY15', + 719: 'BTN_TRIGGER_HAPPY16', + 720: 'BTN_TRIGGER_HAPPY17', + 721: 'BTN_TRIGGER_HAPPY18', + 722: 'BTN_TRIGGER_HAPPY19', + 723: 'BTN_TRIGGER_HAPPY20', + 724: 'BTN_TRIGGER_HAPPY21', + 725: 'BTN_TRIGGER_HAPPY22', + 726: 'BTN_TRIGGER_HAPPY23', + 727: 'BTN_TRIGGER_HAPPY24', + 728: 'BTN_TRIGGER_HAPPY25', + 729: 'BTN_TRIGGER_HAPPY26', + 730: 'BTN_TRIGGER_HAPPY27', + 731: 'BTN_TRIGGER_HAPPY28', + 732: 'BTN_TRIGGER_HAPPY29', + 733: 'BTN_TRIGGER_HAPPY30', + 734: 'BTN_TRIGGER_HAPPY31', + 735: 'BTN_TRIGGER_HAPPY32', + 736: 'BTN_TRIGGER_HAPPY33', + 737: 'BTN_TRIGGER_HAPPY34', + 738: 'BTN_TRIGGER_HAPPY35', + 739: 'BTN_TRIGGER_HAPPY36', + 740: 'BTN_TRIGGER_HAPPY37', + 741: 'BTN_TRIGGER_HAPPY38', + 742: 'BTN_TRIGGER_HAPPY39', + 743: 'BTN_TRIGGER_HAPPY40'}, + 2: { 0: 'REL_X', + 1: 'REL_Y', + 2: 'REL_Z', + 3: 'REL_RX', + 4: 'REL_RY', + 5: 'REL_RZ', + 6: 'REL_HWHEEL', + 7: 'REL_DIAL', + 8: 'REL_WHEEL', + 9: 'REL_MISC', + 10: 'REL_RESERVED', + 11: 'REL_WHEEL_HI_RES', + 12: 'REL_HWHEEL_HI_RES', + 15: 'REL_MAX', + 16: 'REL_CNT'}, + 3: { 0: 'ABS_X', + 1: 'ABS_Y', + 2: 'ABS_Z', + 3: 'ABS_RX', + 4: 'ABS_RY', + 5: 'ABS_RZ', + 6: 'ABS_THROTTLE', + 7: 'ABS_RUDDER', + 8: 'ABS_WHEEL', + 9: 'ABS_GAS', + 10: 'ABS_BRAKE', + 16: 'ABS_HAT0X', + 17: 'ABS_HAT0Y', + 18: 'ABS_HAT1X', + 19: 'ABS_HAT1Y', + 20: 'ABS_HAT2X', + 21: 'ABS_HAT2Y', + 22: 'ABS_HAT3X', + 23: 'ABS_HAT3Y', + 24: 'ABS_PRESSURE', + 25: 'ABS_DISTANCE', + 26: 'ABS_TILT_X', + 27: 'ABS_TILT_Y', + 28: 'ABS_TOOL_WIDTH', + 32: 'ABS_VOLUME', + 33: 'ABS_PROFILE', + 40: 'ABS_MISC', + 46: 'ABS_RESERVED', + 47: 'ABS_MT_SLOT', + 48: 'ABS_MT_TOUCH_MAJOR', + 49: 'ABS_MT_TOUCH_MINOR', + 50: 'ABS_MT_WIDTH_MAJOR', + 51: 'ABS_MT_WIDTH_MINOR', + 52: 'ABS_MT_ORIENTATION', + 53: 'ABS_MT_POSITION_X', + 54: 'ABS_MT_POSITION_Y', + 55: 'ABS_MT_TOOL_TYPE', + 56: 'ABS_MT_BLOB_ID', + 57: 'ABS_MT_TRACKING_ID', + 58: 'ABS_MT_PRESSURE', + 59: 'ABS_MT_DISTANCE', + 60: 'ABS_MT_TOOL_X', + 61: 'ABS_MT_TOOL_Y', + 63: 'ABS_MAX', + 64: 'ABS_CNT'}, + 4: { 0: 'MSC_SERIAL', + 1: 'MSC_PULSELED', + 2: 'MSC_GESTURE', + 3: 'MSC_RAW', + 4: 'MSC_SCAN', + 5: 'MSC_TIMESTAMP', + 7: 'MSC_MAX', + 8: 'MSC_CNT'}, + 5: { 0: 'SW_LID', + 1: 'SW_TABLET_MODE', + 2: 'SW_HEADPHONE_INSERT', + 3: ('SW_RADIO', 'SW_RFKILL_ALL'), + 4: 'SW_MICROPHONE_INSERT', + 5: 'SW_DOCK', + 6: 'SW_LINEOUT_INSERT', + 7: 'SW_JACK_PHYSICAL_INSERT', + 8: 'SW_VIDEOOUT_INSERT', + 9: 'SW_CAMERA_LENS_COVER', + 10: 'SW_KEYPAD_SLIDE', + 11: 'SW_FRONT_PROXIMITY', + 12: 'SW_ROTATE_LOCK', + 13: 'SW_LINEIN_INSERT', + 14: 'SW_MUTE_DEVICE', + 15: 'SW_PEN_INSERTED', + 16: ('SW_MACHINE_COVER', 'SW_MAX'), + 17: 'SW_CNT'}, + 17: { 0: 'LED_NUML', + 1: 'LED_CAPSL', + 2: 'LED_SCROLLL', + 3: 'LED_COMPOSE', + 4: 'LED_KANA', + 5: 'LED_SLEEP', + 6: 'LED_SUSPEND', + 7: 'LED_MUTE', + 8: 'LED_MISC', + 9: 'LED_MAIL', + 10: 'LED_CHARGING', + 15: 'LED_MAX', + 16: 'LED_CNT'}, + 18: {0: 'SND_CLICK', 1: 'SND_BELL', 2: 'SND_TONE', 7: 'SND_MAX', 8: 'SND_CNT'}, + 20: {0: 'REP_DELAY', 1: ('REP_MAX', 'REP_PERIOD'), 2: 'REP_CNT'}, + 21: { 80: ('FF_EFFECT_MIN', 'FF_RUMBLE'), + 81: 'FF_PERIODIC', + 82: 'FF_CONSTANT', + 83: 'FF_SPRING', + 84: 'FF_FRICTION', + 85: 'FF_DAMPER', + 86: 'FF_INERTIA', + 87: ('FF_EFFECT_MAX', 'FF_RAMP'), + 88: ('FF_SQUARE', 'FF_WAVEFORM_MIN'), + 89: 'FF_TRIANGLE', + 90: 'FF_SINE', + 91: 'FF_SAW_UP', + 92: 'FF_SAW_DOWN', + 93: ('FF_CUSTOM', 'FF_WAVEFORM_MAX'), + 96: ('FF_GAIN', 'FF_MAX_EFFECTS'), + 97: 'FF_AUTOCENTER', + 127: 'FF_MAX', + 128: 'FF_CNT'}, + 23: {0: 'FF_STATUS_STOPPED', 1: ('FF_STATUS_MAX', 'FF_STATUS_PLAYING')}} + +#: Keys are a combination of all BTN and KEY codes. +keys: Dict[int, Union[str, Tuple[str]]] = { 0: 'KEY_RESERVED', + 1: 'KEY_ESC', + 2: 'KEY_1', + 3: 'KEY_2', + 4: 'KEY_3', + 5: 'KEY_4', + 6: 'KEY_5', + 7: 'KEY_6', + 8: 'KEY_7', + 9: 'KEY_8', + 10: 'KEY_9', + 11: 'KEY_0', + 12: 'KEY_MINUS', + 13: 'KEY_EQUAL', + 14: 'KEY_BACKSPACE', + 15: 'KEY_TAB', + 16: 'KEY_Q', + 17: 'KEY_W', + 18: 'KEY_E', + 19: 'KEY_R', + 20: 'KEY_T', + 21: 'KEY_Y', + 22: 'KEY_U', + 23: 'KEY_I', + 24: 'KEY_O', + 25: 'KEY_P', + 26: 'KEY_LEFTBRACE', + 27: 'KEY_RIGHTBRACE', + 28: 'KEY_ENTER', + 29: 'KEY_LEFTCTRL', + 30: 'KEY_A', + 31: 'KEY_S', + 32: 'KEY_D', + 33: 'KEY_F', + 34: 'KEY_G', + 35: 'KEY_H', + 36: 'KEY_J', + 37: 'KEY_K', + 38: 'KEY_L', + 39: 'KEY_SEMICOLON', + 40: 'KEY_APOSTROPHE', + 41: 'KEY_GRAVE', + 42: 'KEY_LEFTSHIFT', + 43: 'KEY_BACKSLASH', + 44: 'KEY_Z', + 45: 'KEY_X', + 46: 'KEY_C', + 47: 'KEY_V', + 48: 'KEY_B', + 49: 'KEY_N', + 50: 'KEY_M', + 51: 'KEY_COMMA', + 52: 'KEY_DOT', + 53: 'KEY_SLASH', + 54: 'KEY_RIGHTSHIFT', + 55: 'KEY_KPASTERISK', + 56: 'KEY_LEFTALT', + 57: 'KEY_SPACE', + 58: 'KEY_CAPSLOCK', + 59: 'KEY_F1', + 60: 'KEY_F2', + 61: 'KEY_F3', + 62: 'KEY_F4', + 63: 'KEY_F5', + 64: 'KEY_F6', + 65: 'KEY_F7', + 66: 'KEY_F8', + 67: 'KEY_F9', + 68: 'KEY_F10', + 69: 'KEY_NUMLOCK', + 70: 'KEY_SCROLLLOCK', + 71: 'KEY_KP7', + 72: 'KEY_KP8', + 73: 'KEY_KP9', + 74: 'KEY_KPMINUS', + 75: 'KEY_KP4', + 76: 'KEY_KP5', + 77: 'KEY_KP6', + 78: 'KEY_KPPLUS', + 79: 'KEY_KP1', + 80: 'KEY_KP2', + 81: 'KEY_KP3', + 82: 'KEY_KP0', + 83: 'KEY_KPDOT', + 85: 'KEY_ZENKAKUHANKAKU', + 86: 'KEY_102ND', + 87: 'KEY_F11', + 88: 'KEY_F12', + 89: 'KEY_RO', + 90: 'KEY_KATAKANA', + 91: 'KEY_HIRAGANA', + 92: 'KEY_HENKAN', + 93: 'KEY_KATAKANAHIRAGANA', + 94: 'KEY_MUHENKAN', + 95: 'KEY_KPJPCOMMA', + 96: 'KEY_KPENTER', + 97: 'KEY_RIGHTCTRL', + 98: 'KEY_KPSLASH', + 99: 'KEY_SYSRQ', + 100: 'KEY_RIGHTALT', + 101: 'KEY_LINEFEED', + 102: 'KEY_HOME', + 103: 'KEY_UP', + 104: 'KEY_PAGEUP', + 105: 'KEY_LEFT', + 106: 'KEY_RIGHT', + 107: 'KEY_END', + 108: 'KEY_DOWN', + 109: 'KEY_PAGEDOWN', + 110: 'KEY_INSERT', + 111: 'KEY_DELETE', + 112: 'KEY_MACRO', + 113: ('KEY_MIN_INTERESTING', 'KEY_MUTE'), + 114: 'KEY_VOLUMEDOWN', + 115: 'KEY_VOLUMEUP', + 116: 'KEY_POWER', + 117: 'KEY_KPEQUAL', + 118: 'KEY_KPPLUSMINUS', + 119: 'KEY_PAUSE', + 120: 'KEY_SCALE', + 121: 'KEY_KPCOMMA', + 122: ('KEY_HANGEUL', 'KEY_HANGUEL'), + 123: 'KEY_HANJA', + 124: 'KEY_YEN', + 125: 'KEY_LEFTMETA', + 126: 'KEY_RIGHTMETA', + 127: 'KEY_COMPOSE', + 128: 'KEY_STOP', + 129: 'KEY_AGAIN', + 130: 'KEY_PROPS', + 131: 'KEY_UNDO', + 132: 'KEY_FRONT', + 133: 'KEY_COPY', + 134: 'KEY_OPEN', + 135: 'KEY_PASTE', + 136: 'KEY_FIND', + 137: 'KEY_CUT', + 138: 'KEY_HELP', + 139: 'KEY_MENU', + 140: 'KEY_CALC', + 141: 'KEY_SETUP', + 142: 'KEY_SLEEP', + 143: 'KEY_WAKEUP', + 144: 'KEY_FILE', + 145: 'KEY_SENDFILE', + 146: 'KEY_DELETEFILE', + 147: 'KEY_XFER', + 148: 'KEY_PROG1', + 149: 'KEY_PROG2', + 150: 'KEY_WWW', + 151: 'KEY_MSDOS', + 152: ('KEY_COFFEE', 'KEY_SCREENLOCK'), + 153: ('KEY_DIRECTION', 'KEY_ROTATE_DISPLAY'), + 154: 'KEY_CYCLEWINDOWS', + 155: 'KEY_MAIL', + 156: 'KEY_BOOKMARKS', + 157: 'KEY_COMPUTER', + 158: 'KEY_BACK', + 159: 'KEY_FORWARD', + 160: 'KEY_CLOSECD', + 161: 'KEY_EJECTCD', + 162: 'KEY_EJECTCLOSECD', + 163: 'KEY_NEXTSONG', + 164: 'KEY_PLAYPAUSE', + 165: 'KEY_PREVIOUSSONG', + 166: 'KEY_STOPCD', + 167: 'KEY_RECORD', + 168: 'KEY_REWIND', + 169: 'KEY_PHONE', + 170: 'KEY_ISO', + 171: 'KEY_CONFIG', + 172: 'KEY_HOMEPAGE', + 173: 'KEY_REFRESH', + 174: 'KEY_EXIT', + 175: 'KEY_MOVE', + 176: 'KEY_EDIT', + 177: 'KEY_SCROLLUP', + 178: 'KEY_SCROLLDOWN', + 179: 'KEY_KPLEFTPAREN', + 180: 'KEY_KPRIGHTPAREN', + 181: 'KEY_NEW', + 182: 'KEY_REDO', + 183: 'KEY_F13', + 184: 'KEY_F14', + 185: 'KEY_F15', + 186: 'KEY_F16', + 187: 'KEY_F17', + 188: 'KEY_F18', + 189: 'KEY_F19', + 190: 'KEY_F20', + 191: 'KEY_F21', + 192: 'KEY_F22', + 193: 'KEY_F23', + 194: 'KEY_F24', + 200: 'KEY_PLAYCD', + 201: 'KEY_PAUSECD', + 202: 'KEY_PROG3', + 203: 'KEY_PROG4', + 204: ('KEY_ALL_APPLICATIONS', 'KEY_DASHBOARD'), + 205: 'KEY_SUSPEND', + 206: 'KEY_CLOSE', + 207: 'KEY_PLAY', + 208: 'KEY_FASTFORWARD', + 209: 'KEY_BASSBOOST', + 210: 'KEY_PRINT', + 211: 'KEY_HP', + 212: 'KEY_CAMERA', + 213: 'KEY_SOUND', + 214: 'KEY_QUESTION', + 215: 'KEY_EMAIL', + 216: 'KEY_CHAT', + 217: 'KEY_SEARCH', + 218: 'KEY_CONNECT', + 219: 'KEY_FINANCE', + 220: 'KEY_SPORT', + 221: 'KEY_SHOP', + 222: 'KEY_ALTERASE', + 223: 'KEY_CANCEL', + 224: 'KEY_BRIGHTNESSDOWN', + 225: 'KEY_BRIGHTNESSUP', + 226: 'KEY_MEDIA', + 227: 'KEY_SWITCHVIDEOMODE', + 228: 'KEY_KBDILLUMTOGGLE', + 229: 'KEY_KBDILLUMDOWN', + 230: 'KEY_KBDILLUMUP', + 231: 'KEY_SEND', + 232: 'KEY_REPLY', + 233: 'KEY_FORWARDMAIL', + 234: 'KEY_SAVE', + 235: 'KEY_DOCUMENTS', + 236: 'KEY_BATTERY', + 237: 'KEY_BLUETOOTH', + 238: 'KEY_WLAN', + 239: 'KEY_UWB', + 240: 'KEY_UNKNOWN', + 241: 'KEY_VIDEO_NEXT', + 242: 'KEY_VIDEO_PREV', + 243: 'KEY_BRIGHTNESS_CYCLE', + 244: ('KEY_BRIGHTNESS_AUTO', 'KEY_BRIGHTNESS_ZERO'), + 245: 'KEY_DISPLAY_OFF', + 246: ('KEY_WIMAX', 'KEY_WWAN'), + 247: 'KEY_RFKILL', + 248: 'KEY_MICMUTE', + 256: ('BTN_0', 'BTN_MISC'), + 257: 'BTN_1', + 258: 'BTN_2', + 259: 'BTN_3', + 260: 'BTN_4', + 261: 'BTN_5', + 262: 'BTN_6', + 263: 'BTN_7', + 264: 'BTN_8', + 265: 'BTN_9', + 272: ('BTN_LEFT', 'BTN_MOUSE'), + 273: 'BTN_RIGHT', + 274: 'BTN_MIDDLE', + 275: 'BTN_SIDE', + 276: 'BTN_EXTRA', + 277: 'BTN_FORWARD', + 278: 'BTN_BACK', + 279: 'BTN_TASK', + 288: ('BTN_JOYSTICK', 'BTN_TRIGGER'), + 289: 'BTN_THUMB', + 290: 'BTN_THUMB2', + 291: 'BTN_TOP', + 292: 'BTN_TOP2', + 293: 'BTN_PINKIE', + 294: 'BTN_BASE', + 295: 'BTN_BASE2', + 296: 'BTN_BASE3', + 297: 'BTN_BASE4', + 298: 'BTN_BASE5', + 299: 'BTN_BASE6', + 303: 'BTN_DEAD', + 304: ('BTN_A', 'BTN_GAMEPAD', 'BTN_SOUTH'), + 305: ('BTN_B', 'BTN_EAST'), + 306: 'BTN_C', + 307: ('BTN_NORTH', 'BTN_X'), + 308: ('BTN_WEST', 'BTN_Y'), + 309: 'BTN_Z', + 310: 'BTN_TL', + 311: 'BTN_TR', + 312: 'BTN_TL2', + 313: 'BTN_TR2', + 314: 'BTN_SELECT', + 315: 'BTN_START', + 316: 'BTN_MODE', + 317: 'BTN_THUMBL', + 318: 'BTN_THUMBR', + 320: ('BTN_DIGI', 'BTN_TOOL_PEN'), + 321: 'BTN_TOOL_RUBBER', + 322: 'BTN_TOOL_BRUSH', + 323: 'BTN_TOOL_PENCIL', + 324: 'BTN_TOOL_AIRBRUSH', + 325: 'BTN_TOOL_FINGER', + 326: 'BTN_TOOL_MOUSE', + 327: 'BTN_TOOL_LENS', + 328: 'BTN_TOOL_QUINTTAP', + 329: 'BTN_STYLUS3', + 330: 'BTN_TOUCH', + 331: 'BTN_STYLUS', + 332: 'BTN_STYLUS2', + 333: 'BTN_TOOL_DOUBLETAP', + 334: 'BTN_TOOL_TRIPLETAP', + 335: 'BTN_TOOL_QUADTAP', + 336: ('BTN_GEAR_DOWN', 'BTN_WHEEL'), + 337: 'BTN_GEAR_UP', + 352: 'KEY_OK', + 353: 'KEY_SELECT', + 354: 'KEY_GOTO', + 355: 'KEY_CLEAR', + 356: 'KEY_POWER2', + 357: 'KEY_OPTION', + 358: 'KEY_INFO', + 359: 'KEY_TIME', + 360: 'KEY_VENDOR', + 361: 'KEY_ARCHIVE', + 362: 'KEY_PROGRAM', + 363: 'KEY_CHANNEL', + 364: 'KEY_FAVORITES', + 365: 'KEY_EPG', + 366: 'KEY_PVR', + 367: 'KEY_MHP', + 368: 'KEY_LANGUAGE', + 369: 'KEY_TITLE', + 370: 'KEY_SUBTITLE', + 371: 'KEY_ANGLE', + 372: ('KEY_FULL_SCREEN', 'KEY_ZOOM'), + 373: 'KEY_MODE', + 374: 'KEY_KEYBOARD', + 375: ('KEY_ASPECT_RATIO', 'KEY_SCREEN'), + 376: 'KEY_PC', + 377: 'KEY_TV', + 378: 'KEY_TV2', + 379: 'KEY_VCR', + 380: 'KEY_VCR2', + 381: 'KEY_SAT', + 382: 'KEY_SAT2', + 383: 'KEY_CD', + 384: 'KEY_TAPE', + 385: 'KEY_RADIO', + 386: 'KEY_TUNER', + 387: 'KEY_PLAYER', + 388: 'KEY_TEXT', + 389: 'KEY_DVD', + 390: 'KEY_AUX', + 391: 'KEY_MP3', + 392: 'KEY_AUDIO', + 393: 'KEY_VIDEO', + 394: 'KEY_DIRECTORY', + 395: 'KEY_LIST', + 396: 'KEY_MEMO', + 397: 'KEY_CALENDAR', + 398: 'KEY_RED', + 399: 'KEY_GREEN', + 400: 'KEY_YELLOW', + 401: 'KEY_BLUE', + 402: 'KEY_CHANNELUP', + 403: 'KEY_CHANNELDOWN', + 404: 'KEY_FIRST', + 405: 'KEY_LAST', + 406: 'KEY_AB', + 407: 'KEY_NEXT', + 408: 'KEY_RESTART', + 409: 'KEY_SLOW', + 410: 'KEY_SHUFFLE', + 411: 'KEY_BREAK', + 412: 'KEY_PREVIOUS', + 413: 'KEY_DIGITS', + 414: 'KEY_TEEN', + 415: 'KEY_TWEN', + 416: 'KEY_VIDEOPHONE', + 417: 'KEY_GAMES', + 418: 'KEY_ZOOMIN', + 419: 'KEY_ZOOMOUT', + 420: 'KEY_ZOOMRESET', + 421: 'KEY_WORDPROCESSOR', + 422: 'KEY_EDITOR', + 423: 'KEY_SPREADSHEET', + 424: 'KEY_GRAPHICSEDITOR', + 425: 'KEY_PRESENTATION', + 426: 'KEY_DATABASE', + 427: 'KEY_NEWS', + 428: 'KEY_VOICEMAIL', + 429: 'KEY_ADDRESSBOOK', + 430: 'KEY_MESSENGER', + 431: ('KEY_BRIGHTNESS_TOGGLE', 'KEY_DISPLAYTOGGLE'), + 432: 'KEY_SPELLCHECK', + 433: 'KEY_LOGOFF', + 434: 'KEY_DOLLAR', + 435: 'KEY_EURO', + 436: 'KEY_FRAMEBACK', + 437: 'KEY_FRAMEFORWARD', + 438: 'KEY_CONTEXT_MENU', + 439: 'KEY_MEDIA_REPEAT', + 440: 'KEY_10CHANNELSUP', + 441: 'KEY_10CHANNELSDOWN', + 442: 'KEY_IMAGES', + 444: 'KEY_NOTIFICATION_CENTER', + 445: 'KEY_PICKUP_PHONE', + 446: 'KEY_HANGUP_PHONE', + 447: 'KEY_LINK_PHONE', + 448: 'KEY_DEL_EOL', + 449: 'KEY_DEL_EOS', + 450: 'KEY_INS_LINE', + 451: 'KEY_DEL_LINE', + 464: 'KEY_FN', + 465: 'KEY_FN_ESC', + 466: 'KEY_FN_F1', + 467: 'KEY_FN_F2', + 468: 'KEY_FN_F3', + 469: 'KEY_FN_F4', + 470: 'KEY_FN_F5', + 471: 'KEY_FN_F6', + 472: 'KEY_FN_F7', + 473: 'KEY_FN_F8', + 474: 'KEY_FN_F9', + 475: 'KEY_FN_F10', + 476: 'KEY_FN_F11', + 477: 'KEY_FN_F12', + 478: 'KEY_FN_1', + 479: 'KEY_FN_2', + 480: 'KEY_FN_D', + 481: 'KEY_FN_E', + 482: 'KEY_FN_F', + 483: 'KEY_FN_S', + 484: 'KEY_FN_B', + 485: 'KEY_FN_RIGHT_SHIFT', + 497: 'KEY_BRL_DOT1', + 498: 'KEY_BRL_DOT2', + 499: 'KEY_BRL_DOT3', + 500: 'KEY_BRL_DOT4', + 501: 'KEY_BRL_DOT5', + 502: 'KEY_BRL_DOT6', + 503: 'KEY_BRL_DOT7', + 504: 'KEY_BRL_DOT8', + 505: 'KEY_BRL_DOT9', + 506: 'KEY_BRL_DOT10', + 512: 'KEY_NUMERIC_0', + 513: 'KEY_NUMERIC_1', + 514: 'KEY_NUMERIC_2', + 515: 'KEY_NUMERIC_3', + 516: 'KEY_NUMERIC_4', + 517: 'KEY_NUMERIC_5', + 518: 'KEY_NUMERIC_6', + 519: 'KEY_NUMERIC_7', + 520: 'KEY_NUMERIC_8', + 521: 'KEY_NUMERIC_9', + 522: 'KEY_NUMERIC_STAR', + 523: 'KEY_NUMERIC_POUND', + 524: 'KEY_NUMERIC_A', + 525: 'KEY_NUMERIC_B', + 526: 'KEY_NUMERIC_C', + 527: 'KEY_NUMERIC_D', + 528: 'KEY_CAMERA_FOCUS', + 529: 'KEY_WPS_BUTTON', + 530: 'KEY_TOUCHPAD_TOGGLE', + 531: 'KEY_TOUCHPAD_ON', + 532: 'KEY_TOUCHPAD_OFF', + 533: 'KEY_CAMERA_ZOOMIN', + 534: 'KEY_CAMERA_ZOOMOUT', + 535: 'KEY_CAMERA_UP', + 536: 'KEY_CAMERA_DOWN', + 537: 'KEY_CAMERA_LEFT', + 538: 'KEY_CAMERA_RIGHT', + 539: 'KEY_ATTENDANT_ON', + 540: 'KEY_ATTENDANT_OFF', + 541: 'KEY_ATTENDANT_TOGGLE', + 542: 'KEY_LIGHTS_TOGGLE', + 544: 'BTN_DPAD_UP', + 545: 'BTN_DPAD_DOWN', + 546: 'BTN_DPAD_LEFT', + 547: 'BTN_DPAD_RIGHT', + 560: 'KEY_ALS_TOGGLE', + 561: 'KEY_ROTATE_LOCK_TOGGLE', + 562: 'KEY_REFRESH_RATE_TOGGLE', + 576: 'KEY_BUTTONCONFIG', + 577: 'KEY_TASKMANAGER', + 578: 'KEY_JOURNAL', + 579: 'KEY_CONTROLPANEL', + 580: 'KEY_APPSELECT', + 581: 'KEY_SCREENSAVER', + 582: 'KEY_VOICECOMMAND', + 583: 'KEY_ASSISTANT', + 584: 'KEY_KBD_LAYOUT_NEXT', + 585: 'KEY_EMOJI_PICKER', + 586: 'KEY_DICTATE', + 587: 'KEY_CAMERA_ACCESS_ENABLE', + 588: 'KEY_CAMERA_ACCESS_DISABLE', + 589: 'KEY_CAMERA_ACCESS_TOGGLE', + 590: 'KEY_ACCESSIBILITY', + 591: 'KEY_DO_NOT_DISTURB', + 592: 'KEY_BRIGHTNESS_MIN', + 593: 'KEY_BRIGHTNESS_MAX', + 608: 'KEY_KBDINPUTASSIST_PREV', + 609: 'KEY_KBDINPUTASSIST_NEXT', + 610: 'KEY_KBDINPUTASSIST_PREVGROUP', + 611: 'KEY_KBDINPUTASSIST_NEXTGROUP', + 612: 'KEY_KBDINPUTASSIST_ACCEPT', + 613: 'KEY_KBDINPUTASSIST_CANCEL', + 614: 'KEY_RIGHT_UP', + 615: 'KEY_RIGHT_DOWN', + 616: 'KEY_LEFT_UP', + 617: 'KEY_LEFT_DOWN', + 618: 'KEY_ROOT_MENU', + 619: 'KEY_MEDIA_TOP_MENU', + 620: 'KEY_NUMERIC_11', + 621: 'KEY_NUMERIC_12', + 622: 'KEY_AUDIO_DESC', + 623: 'KEY_3D_MODE', + 624: 'KEY_NEXT_FAVORITE', + 625: 'KEY_STOP_RECORD', + 626: 'KEY_PAUSE_RECORD', + 627: 'KEY_VOD', + 628: 'KEY_UNMUTE', + 629: 'KEY_FASTREVERSE', + 630: 'KEY_SLOWREVERSE', + 631: 'KEY_DATA', + 632: 'KEY_ONSCREEN_KEYBOARD', + 633: 'KEY_PRIVACY_SCREEN_TOGGLE', + 634: 'KEY_SELECTIVE_SCREENSHOT', + 635: 'KEY_NEXT_ELEMENT', + 636: 'KEY_PREVIOUS_ELEMENT', + 637: 'KEY_AUTOPILOT_ENGAGE_TOGGLE', + 638: 'KEY_MARK_WAYPOINT', + 639: 'KEY_SOS', + 640: 'KEY_NAV_CHART', + 641: 'KEY_FISHING_CHART', + 642: 'KEY_SINGLE_RANGE_RADAR', + 643: 'KEY_DUAL_RANGE_RADAR', + 644: 'KEY_RADAR_OVERLAY', + 645: 'KEY_TRADITIONAL_SONAR', + 646: 'KEY_CLEARVU_SONAR', + 647: 'KEY_SIDEVU_SONAR', + 648: 'KEY_NAV_INFO', + 649: 'KEY_BRIGHTNESS_MENU', + 656: 'KEY_MACRO1', + 657: 'KEY_MACRO2', + 658: 'KEY_MACRO3', + 659: 'KEY_MACRO4', + 660: 'KEY_MACRO5', + 661: 'KEY_MACRO6', + 662: 'KEY_MACRO7', + 663: 'KEY_MACRO8', + 664: 'KEY_MACRO9', + 665: 'KEY_MACRO10', + 666: 'KEY_MACRO11', + 667: 'KEY_MACRO12', + 668: 'KEY_MACRO13', + 669: 'KEY_MACRO14', + 670: 'KEY_MACRO15', + 671: 'KEY_MACRO16', + 672: 'KEY_MACRO17', + 673: 'KEY_MACRO18', + 674: 'KEY_MACRO19', + 675: 'KEY_MACRO20', + 676: 'KEY_MACRO21', + 677: 'KEY_MACRO22', + 678: 'KEY_MACRO23', + 679: 'KEY_MACRO24', + 680: 'KEY_MACRO25', + 681: 'KEY_MACRO26', + 682: 'KEY_MACRO27', + 683: 'KEY_MACRO28', + 684: 'KEY_MACRO29', + 685: 'KEY_MACRO30', + 688: 'KEY_MACRO_RECORD_START', + 689: 'KEY_MACRO_RECORD_STOP', + 690: 'KEY_MACRO_PRESET_CYCLE', + 691: 'KEY_MACRO_PRESET1', + 692: 'KEY_MACRO_PRESET2', + 693: 'KEY_MACRO_PRESET3', + 696: 'KEY_KBD_LCD_MENU1', + 697: 'KEY_KBD_LCD_MENU2', + 698: 'KEY_KBD_LCD_MENU3', + 699: 'KEY_KBD_LCD_MENU4', + 700: 'KEY_KBD_LCD_MENU5', + 704: ('BTN_TRIGGER_HAPPY', 'BTN_TRIGGER_HAPPY1'), + 705: 'BTN_TRIGGER_HAPPY2', + 706: 'BTN_TRIGGER_HAPPY3', + 707: 'BTN_TRIGGER_HAPPY4', + 708: 'BTN_TRIGGER_HAPPY5', + 709: 'BTN_TRIGGER_HAPPY6', + 710: 'BTN_TRIGGER_HAPPY7', + 711: 'BTN_TRIGGER_HAPPY8', + 712: 'BTN_TRIGGER_HAPPY9', + 713: 'BTN_TRIGGER_HAPPY10', + 714: 'BTN_TRIGGER_HAPPY11', + 715: 'BTN_TRIGGER_HAPPY12', + 716: 'BTN_TRIGGER_HAPPY13', + 717: 'BTN_TRIGGER_HAPPY14', + 718: 'BTN_TRIGGER_HAPPY15', + 719: 'BTN_TRIGGER_HAPPY16', + 720: 'BTN_TRIGGER_HAPPY17', + 721: 'BTN_TRIGGER_HAPPY18', + 722: 'BTN_TRIGGER_HAPPY19', + 723: 'BTN_TRIGGER_HAPPY20', + 724: 'BTN_TRIGGER_HAPPY21', + 725: 'BTN_TRIGGER_HAPPY22', + 726: 'BTN_TRIGGER_HAPPY23', + 727: 'BTN_TRIGGER_HAPPY24', + 728: 'BTN_TRIGGER_HAPPY25', + 729: 'BTN_TRIGGER_HAPPY26', + 730: 'BTN_TRIGGER_HAPPY27', + 731: 'BTN_TRIGGER_HAPPY28', + 732: 'BTN_TRIGGER_HAPPY29', + 733: 'BTN_TRIGGER_HAPPY30', + 734: 'BTN_TRIGGER_HAPPY31', + 735: 'BTN_TRIGGER_HAPPY32', + 736: 'BTN_TRIGGER_HAPPY33', + 737: 'BTN_TRIGGER_HAPPY34', + 738: 'BTN_TRIGGER_HAPPY35', + 739: 'BTN_TRIGGER_HAPPY36', + 740: 'BTN_TRIGGER_HAPPY37', + 741: 'BTN_TRIGGER_HAPPY38', + 742: 'BTN_TRIGGER_HAPPY39', + 743: 'BTN_TRIGGER_HAPPY40'} + +KEY: Dict[int, Union[str, Tuple[str]]] = { 0: 'KEY_RESERVED', + 1: 'KEY_ESC', + 2: 'KEY_1', + 3: 'KEY_2', + 4: 'KEY_3', + 5: 'KEY_4', + 6: 'KEY_5', + 7: 'KEY_6', + 8: 'KEY_7', + 9: 'KEY_8', + 10: 'KEY_9', + 11: 'KEY_0', + 12: 'KEY_MINUS', + 13: 'KEY_EQUAL', + 14: 'KEY_BACKSPACE', + 15: 'KEY_TAB', + 16: 'KEY_Q', + 17: 'KEY_W', + 18: 'KEY_E', + 19: 'KEY_R', + 20: 'KEY_T', + 21: 'KEY_Y', + 22: 'KEY_U', + 23: 'KEY_I', + 24: 'KEY_O', + 25: 'KEY_P', + 26: 'KEY_LEFTBRACE', + 27: 'KEY_RIGHTBRACE', + 28: 'KEY_ENTER', + 29: 'KEY_LEFTCTRL', + 30: 'KEY_A', + 31: 'KEY_S', + 32: 'KEY_D', + 33: 'KEY_F', + 34: 'KEY_G', + 35: 'KEY_H', + 36: 'KEY_J', + 37: 'KEY_K', + 38: 'KEY_L', + 39: 'KEY_SEMICOLON', + 40: 'KEY_APOSTROPHE', + 41: 'KEY_GRAVE', + 42: 'KEY_LEFTSHIFT', + 43: 'KEY_BACKSLASH', + 44: 'KEY_Z', + 45: 'KEY_X', + 46: 'KEY_C', + 47: 'KEY_V', + 48: 'KEY_B', + 49: 'KEY_N', + 50: 'KEY_M', + 51: 'KEY_COMMA', + 52: 'KEY_DOT', + 53: 'KEY_SLASH', + 54: 'KEY_RIGHTSHIFT', + 55: 'KEY_KPASTERISK', + 56: 'KEY_LEFTALT', + 57: 'KEY_SPACE', + 58: 'KEY_CAPSLOCK', + 59: 'KEY_F1', + 60: 'KEY_F2', + 61: 'KEY_F3', + 62: 'KEY_F4', + 63: 'KEY_F5', + 64: 'KEY_F6', + 65: 'KEY_F7', + 66: 'KEY_F8', + 67: 'KEY_F9', + 68: 'KEY_F10', + 69: 'KEY_NUMLOCK', + 70: 'KEY_SCROLLLOCK', + 71: 'KEY_KP7', + 72: 'KEY_KP8', + 73: 'KEY_KP9', + 74: 'KEY_KPMINUS', + 75: 'KEY_KP4', + 76: 'KEY_KP5', + 77: 'KEY_KP6', + 78: 'KEY_KPPLUS', + 79: 'KEY_KP1', + 80: 'KEY_KP2', + 81: 'KEY_KP3', + 82: 'KEY_KP0', + 83: 'KEY_KPDOT', + 85: 'KEY_ZENKAKUHANKAKU', + 86: 'KEY_102ND', + 87: 'KEY_F11', + 88: 'KEY_F12', + 89: 'KEY_RO', + 90: 'KEY_KATAKANA', + 91: 'KEY_HIRAGANA', + 92: 'KEY_HENKAN', + 93: 'KEY_KATAKANAHIRAGANA', + 94: 'KEY_MUHENKAN', + 95: 'KEY_KPJPCOMMA', + 96: 'KEY_KPENTER', + 97: 'KEY_RIGHTCTRL', + 98: 'KEY_KPSLASH', + 99: 'KEY_SYSRQ', + 100: 'KEY_RIGHTALT', + 101: 'KEY_LINEFEED', + 102: 'KEY_HOME', + 103: 'KEY_UP', + 104: 'KEY_PAGEUP', + 105: 'KEY_LEFT', + 106: 'KEY_RIGHT', + 107: 'KEY_END', + 108: 'KEY_DOWN', + 109: 'KEY_PAGEDOWN', + 110: 'KEY_INSERT', + 111: 'KEY_DELETE', + 112: 'KEY_MACRO', + 113: ('KEY_MIN_INTERESTING', 'KEY_MUTE'), + 114: 'KEY_VOLUMEDOWN', + 115: 'KEY_VOLUMEUP', + 116: 'KEY_POWER', + 117: 'KEY_KPEQUAL', + 118: 'KEY_KPPLUSMINUS', + 119: 'KEY_PAUSE', + 120: 'KEY_SCALE', + 121: 'KEY_KPCOMMA', + 122: ('KEY_HANGEUL', 'KEY_HANGUEL'), + 123: 'KEY_HANJA', + 124: 'KEY_YEN', + 125: 'KEY_LEFTMETA', + 126: 'KEY_RIGHTMETA', + 127: 'KEY_COMPOSE', + 128: 'KEY_STOP', + 129: 'KEY_AGAIN', + 130: 'KEY_PROPS', + 131: 'KEY_UNDO', + 132: 'KEY_FRONT', + 133: 'KEY_COPY', + 134: 'KEY_OPEN', + 135: 'KEY_PASTE', + 136: 'KEY_FIND', + 137: 'KEY_CUT', + 138: 'KEY_HELP', + 139: 'KEY_MENU', + 140: 'KEY_CALC', + 141: 'KEY_SETUP', + 142: 'KEY_SLEEP', + 143: 'KEY_WAKEUP', + 144: 'KEY_FILE', + 145: 'KEY_SENDFILE', + 146: 'KEY_DELETEFILE', + 147: 'KEY_XFER', + 148: 'KEY_PROG1', + 149: 'KEY_PROG2', + 150: 'KEY_WWW', + 151: 'KEY_MSDOS', + 152: ('KEY_COFFEE', 'KEY_SCREENLOCK'), + 153: ('KEY_DIRECTION', 'KEY_ROTATE_DISPLAY'), + 154: 'KEY_CYCLEWINDOWS', + 155: 'KEY_MAIL', + 156: 'KEY_BOOKMARKS', + 157: 'KEY_COMPUTER', + 158: 'KEY_BACK', + 159: 'KEY_FORWARD', + 160: 'KEY_CLOSECD', + 161: 'KEY_EJECTCD', + 162: 'KEY_EJECTCLOSECD', + 163: 'KEY_NEXTSONG', + 164: 'KEY_PLAYPAUSE', + 165: 'KEY_PREVIOUSSONG', + 166: 'KEY_STOPCD', + 167: 'KEY_RECORD', + 168: 'KEY_REWIND', + 169: 'KEY_PHONE', + 170: 'KEY_ISO', + 171: 'KEY_CONFIG', + 172: 'KEY_HOMEPAGE', + 173: 'KEY_REFRESH', + 174: 'KEY_EXIT', + 175: 'KEY_MOVE', + 176: 'KEY_EDIT', + 177: 'KEY_SCROLLUP', + 178: 'KEY_SCROLLDOWN', + 179: 'KEY_KPLEFTPAREN', + 180: 'KEY_KPRIGHTPAREN', + 181: 'KEY_NEW', + 182: 'KEY_REDO', + 183: 'KEY_F13', + 184: 'KEY_F14', + 185: 'KEY_F15', + 186: 'KEY_F16', + 187: 'KEY_F17', + 188: 'KEY_F18', + 189: 'KEY_F19', + 190: 'KEY_F20', + 191: 'KEY_F21', + 192: 'KEY_F22', + 193: 'KEY_F23', + 194: 'KEY_F24', + 200: 'KEY_PLAYCD', + 201: 'KEY_PAUSECD', + 202: 'KEY_PROG3', + 203: 'KEY_PROG4', + 204: ('KEY_ALL_APPLICATIONS', 'KEY_DASHBOARD'), + 205: 'KEY_SUSPEND', + 206: 'KEY_CLOSE', + 207: 'KEY_PLAY', + 208: 'KEY_FASTFORWARD', + 209: 'KEY_BASSBOOST', + 210: 'KEY_PRINT', + 211: 'KEY_HP', + 212: 'KEY_CAMERA', + 213: 'KEY_SOUND', + 214: 'KEY_QUESTION', + 215: 'KEY_EMAIL', + 216: 'KEY_CHAT', + 217: 'KEY_SEARCH', + 218: 'KEY_CONNECT', + 219: 'KEY_FINANCE', + 220: 'KEY_SPORT', + 221: 'KEY_SHOP', + 222: 'KEY_ALTERASE', + 223: 'KEY_CANCEL', + 224: 'KEY_BRIGHTNESSDOWN', + 225: 'KEY_BRIGHTNESSUP', + 226: 'KEY_MEDIA', + 227: 'KEY_SWITCHVIDEOMODE', + 228: 'KEY_KBDILLUMTOGGLE', + 229: 'KEY_KBDILLUMDOWN', + 230: 'KEY_KBDILLUMUP', + 231: 'KEY_SEND', + 232: 'KEY_REPLY', + 233: 'KEY_FORWARDMAIL', + 234: 'KEY_SAVE', + 235: 'KEY_DOCUMENTS', + 236: 'KEY_BATTERY', + 237: 'KEY_BLUETOOTH', + 238: 'KEY_WLAN', + 239: 'KEY_UWB', + 240: 'KEY_UNKNOWN', + 241: 'KEY_VIDEO_NEXT', + 242: 'KEY_VIDEO_PREV', + 243: 'KEY_BRIGHTNESS_CYCLE', + 244: ('KEY_BRIGHTNESS_AUTO', 'KEY_BRIGHTNESS_ZERO'), + 245: 'KEY_DISPLAY_OFF', + 246: ('KEY_WIMAX', 'KEY_WWAN'), + 247: 'KEY_RFKILL', + 248: 'KEY_MICMUTE', + 352: 'KEY_OK', + 353: 'KEY_SELECT', + 354: 'KEY_GOTO', + 355: 'KEY_CLEAR', + 356: 'KEY_POWER2', + 357: 'KEY_OPTION', + 358: 'KEY_INFO', + 359: 'KEY_TIME', + 360: 'KEY_VENDOR', + 361: 'KEY_ARCHIVE', + 362: 'KEY_PROGRAM', + 363: 'KEY_CHANNEL', + 364: 'KEY_FAVORITES', + 365: 'KEY_EPG', + 366: 'KEY_PVR', + 367: 'KEY_MHP', + 368: 'KEY_LANGUAGE', + 369: 'KEY_TITLE', + 370: 'KEY_SUBTITLE', + 371: 'KEY_ANGLE', + 372: ('KEY_FULL_SCREEN', 'KEY_ZOOM'), + 373: 'KEY_MODE', + 374: 'KEY_KEYBOARD', + 375: ('KEY_ASPECT_RATIO', 'KEY_SCREEN'), + 376: 'KEY_PC', + 377: 'KEY_TV', + 378: 'KEY_TV2', + 379: 'KEY_VCR', + 380: 'KEY_VCR2', + 381: 'KEY_SAT', + 382: 'KEY_SAT2', + 383: 'KEY_CD', + 384: 'KEY_TAPE', + 385: 'KEY_RADIO', + 386: 'KEY_TUNER', + 387: 'KEY_PLAYER', + 388: 'KEY_TEXT', + 389: 'KEY_DVD', + 390: 'KEY_AUX', + 391: 'KEY_MP3', + 392: 'KEY_AUDIO', + 393: 'KEY_VIDEO', + 394: 'KEY_DIRECTORY', + 395: 'KEY_LIST', + 396: 'KEY_MEMO', + 397: 'KEY_CALENDAR', + 398: 'KEY_RED', + 399: 'KEY_GREEN', + 400: 'KEY_YELLOW', + 401: 'KEY_BLUE', + 402: 'KEY_CHANNELUP', + 403: 'KEY_CHANNELDOWN', + 404: 'KEY_FIRST', + 405: 'KEY_LAST', + 406: 'KEY_AB', + 407: 'KEY_NEXT', + 408: 'KEY_RESTART', + 409: 'KEY_SLOW', + 410: 'KEY_SHUFFLE', + 411: 'KEY_BREAK', + 412: 'KEY_PREVIOUS', + 413: 'KEY_DIGITS', + 414: 'KEY_TEEN', + 415: 'KEY_TWEN', + 416: 'KEY_VIDEOPHONE', + 417: 'KEY_GAMES', + 418: 'KEY_ZOOMIN', + 419: 'KEY_ZOOMOUT', + 420: 'KEY_ZOOMRESET', + 421: 'KEY_WORDPROCESSOR', + 422: 'KEY_EDITOR', + 423: 'KEY_SPREADSHEET', + 424: 'KEY_GRAPHICSEDITOR', + 425: 'KEY_PRESENTATION', + 426: 'KEY_DATABASE', + 427: 'KEY_NEWS', + 428: 'KEY_VOICEMAIL', + 429: 'KEY_ADDRESSBOOK', + 430: 'KEY_MESSENGER', + 431: ('KEY_BRIGHTNESS_TOGGLE', 'KEY_DISPLAYTOGGLE'), + 432: 'KEY_SPELLCHECK', + 433: 'KEY_LOGOFF', + 434: 'KEY_DOLLAR', + 435: 'KEY_EURO', + 436: 'KEY_FRAMEBACK', + 437: 'KEY_FRAMEFORWARD', + 438: 'KEY_CONTEXT_MENU', + 439: 'KEY_MEDIA_REPEAT', + 440: 'KEY_10CHANNELSUP', + 441: 'KEY_10CHANNELSDOWN', + 442: 'KEY_IMAGES', + 444: 'KEY_NOTIFICATION_CENTER', + 445: 'KEY_PICKUP_PHONE', + 446: 'KEY_HANGUP_PHONE', + 447: 'KEY_LINK_PHONE', + 448: 'KEY_DEL_EOL', + 449: 'KEY_DEL_EOS', + 450: 'KEY_INS_LINE', + 451: 'KEY_DEL_LINE', + 464: 'KEY_FN', + 465: 'KEY_FN_ESC', + 466: 'KEY_FN_F1', + 467: 'KEY_FN_F2', + 468: 'KEY_FN_F3', + 469: 'KEY_FN_F4', + 470: 'KEY_FN_F5', + 471: 'KEY_FN_F6', + 472: 'KEY_FN_F7', + 473: 'KEY_FN_F8', + 474: 'KEY_FN_F9', + 475: 'KEY_FN_F10', + 476: 'KEY_FN_F11', + 477: 'KEY_FN_F12', + 478: 'KEY_FN_1', + 479: 'KEY_FN_2', + 480: 'KEY_FN_D', + 481: 'KEY_FN_E', + 482: 'KEY_FN_F', + 483: 'KEY_FN_S', + 484: 'KEY_FN_B', + 485: 'KEY_FN_RIGHT_SHIFT', + 497: 'KEY_BRL_DOT1', + 498: 'KEY_BRL_DOT2', + 499: 'KEY_BRL_DOT3', + 500: 'KEY_BRL_DOT4', + 501: 'KEY_BRL_DOT5', + 502: 'KEY_BRL_DOT6', + 503: 'KEY_BRL_DOT7', + 504: 'KEY_BRL_DOT8', + 505: 'KEY_BRL_DOT9', + 506: 'KEY_BRL_DOT10', + 512: 'KEY_NUMERIC_0', + 513: 'KEY_NUMERIC_1', + 514: 'KEY_NUMERIC_2', + 515: 'KEY_NUMERIC_3', + 516: 'KEY_NUMERIC_4', + 517: 'KEY_NUMERIC_5', + 518: 'KEY_NUMERIC_6', + 519: 'KEY_NUMERIC_7', + 520: 'KEY_NUMERIC_8', + 521: 'KEY_NUMERIC_9', + 522: 'KEY_NUMERIC_STAR', + 523: 'KEY_NUMERIC_POUND', + 524: 'KEY_NUMERIC_A', + 525: 'KEY_NUMERIC_B', + 526: 'KEY_NUMERIC_C', + 527: 'KEY_NUMERIC_D', + 528: 'KEY_CAMERA_FOCUS', + 529: 'KEY_WPS_BUTTON', + 530: 'KEY_TOUCHPAD_TOGGLE', + 531: 'KEY_TOUCHPAD_ON', + 532: 'KEY_TOUCHPAD_OFF', + 533: 'KEY_CAMERA_ZOOMIN', + 534: 'KEY_CAMERA_ZOOMOUT', + 535: 'KEY_CAMERA_UP', + 536: 'KEY_CAMERA_DOWN', + 537: 'KEY_CAMERA_LEFT', + 538: 'KEY_CAMERA_RIGHT', + 539: 'KEY_ATTENDANT_ON', + 540: 'KEY_ATTENDANT_OFF', + 541: 'KEY_ATTENDANT_TOGGLE', + 542: 'KEY_LIGHTS_TOGGLE', + 560: 'KEY_ALS_TOGGLE', + 561: 'KEY_ROTATE_LOCK_TOGGLE', + 562: 'KEY_REFRESH_RATE_TOGGLE', + 576: 'KEY_BUTTONCONFIG', + 577: 'KEY_TASKMANAGER', + 578: 'KEY_JOURNAL', + 579: 'KEY_CONTROLPANEL', + 580: 'KEY_APPSELECT', + 581: 'KEY_SCREENSAVER', + 582: 'KEY_VOICECOMMAND', + 583: 'KEY_ASSISTANT', + 584: 'KEY_KBD_LAYOUT_NEXT', + 585: 'KEY_EMOJI_PICKER', + 586: 'KEY_DICTATE', + 587: 'KEY_CAMERA_ACCESS_ENABLE', + 588: 'KEY_CAMERA_ACCESS_DISABLE', + 589: 'KEY_CAMERA_ACCESS_TOGGLE', + 590: 'KEY_ACCESSIBILITY', + 591: 'KEY_DO_NOT_DISTURB', + 592: 'KEY_BRIGHTNESS_MIN', + 593: 'KEY_BRIGHTNESS_MAX', + 608: 'KEY_KBDINPUTASSIST_PREV', + 609: 'KEY_KBDINPUTASSIST_NEXT', + 610: 'KEY_KBDINPUTASSIST_PREVGROUP', + 611: 'KEY_KBDINPUTASSIST_NEXTGROUP', + 612: 'KEY_KBDINPUTASSIST_ACCEPT', + 613: 'KEY_KBDINPUTASSIST_CANCEL', + 614: 'KEY_RIGHT_UP', + 615: 'KEY_RIGHT_DOWN', + 616: 'KEY_LEFT_UP', + 617: 'KEY_LEFT_DOWN', + 618: 'KEY_ROOT_MENU', + 619: 'KEY_MEDIA_TOP_MENU', + 620: 'KEY_NUMERIC_11', + 621: 'KEY_NUMERIC_12', + 622: 'KEY_AUDIO_DESC', + 623: 'KEY_3D_MODE', + 624: 'KEY_NEXT_FAVORITE', + 625: 'KEY_STOP_RECORD', + 626: 'KEY_PAUSE_RECORD', + 627: 'KEY_VOD', + 628: 'KEY_UNMUTE', + 629: 'KEY_FASTREVERSE', + 630: 'KEY_SLOWREVERSE', + 631: 'KEY_DATA', + 632: 'KEY_ONSCREEN_KEYBOARD', + 633: 'KEY_PRIVACY_SCREEN_TOGGLE', + 634: 'KEY_SELECTIVE_SCREENSHOT', + 635: 'KEY_NEXT_ELEMENT', + 636: 'KEY_PREVIOUS_ELEMENT', + 637: 'KEY_AUTOPILOT_ENGAGE_TOGGLE', + 638: 'KEY_MARK_WAYPOINT', + 639: 'KEY_SOS', + 640: 'KEY_NAV_CHART', + 641: 'KEY_FISHING_CHART', + 642: 'KEY_SINGLE_RANGE_RADAR', + 643: 'KEY_DUAL_RANGE_RADAR', + 644: 'KEY_RADAR_OVERLAY', + 645: 'KEY_TRADITIONAL_SONAR', + 646: 'KEY_CLEARVU_SONAR', + 647: 'KEY_SIDEVU_SONAR', + 648: 'KEY_NAV_INFO', + 649: 'KEY_BRIGHTNESS_MENU', + 656: 'KEY_MACRO1', + 657: 'KEY_MACRO2', + 658: 'KEY_MACRO3', + 659: 'KEY_MACRO4', + 660: 'KEY_MACRO5', + 661: 'KEY_MACRO6', + 662: 'KEY_MACRO7', + 663: 'KEY_MACRO8', + 664: 'KEY_MACRO9', + 665: 'KEY_MACRO10', + 666: 'KEY_MACRO11', + 667: 'KEY_MACRO12', + 668: 'KEY_MACRO13', + 669: 'KEY_MACRO14', + 670: 'KEY_MACRO15', + 671: 'KEY_MACRO16', + 672: 'KEY_MACRO17', + 673: 'KEY_MACRO18', + 674: 'KEY_MACRO19', + 675: 'KEY_MACRO20', + 676: 'KEY_MACRO21', + 677: 'KEY_MACRO22', + 678: 'KEY_MACRO23', + 679: 'KEY_MACRO24', + 680: 'KEY_MACRO25', + 681: 'KEY_MACRO26', + 682: 'KEY_MACRO27', + 683: 'KEY_MACRO28', + 684: 'KEY_MACRO29', + 685: 'KEY_MACRO30', + 688: 'KEY_MACRO_RECORD_START', + 689: 'KEY_MACRO_RECORD_STOP', + 690: 'KEY_MACRO_PRESET_CYCLE', + 691: 'KEY_MACRO_PRESET1', + 692: 'KEY_MACRO_PRESET2', + 693: 'KEY_MACRO_PRESET3', + 696: 'KEY_KBD_LCD_MENU1', + 697: 'KEY_KBD_LCD_MENU2', + 698: 'KEY_KBD_LCD_MENU3', + 699: 'KEY_KBD_LCD_MENU4', + 700: 'KEY_KBD_LCD_MENU5', + 767: 'KEY_MAX', + 768: 'KEY_CNT'} + +ABS: Dict[int, Union[str, Tuple[str]]] = { 0: 'ABS_X', + 1: 'ABS_Y', + 2: 'ABS_Z', + 3: 'ABS_RX', + 4: 'ABS_RY', + 5: 'ABS_RZ', + 6: 'ABS_THROTTLE', + 7: 'ABS_RUDDER', + 8: 'ABS_WHEEL', + 9: 'ABS_GAS', + 10: 'ABS_BRAKE', + 16: 'ABS_HAT0X', + 17: 'ABS_HAT0Y', + 18: 'ABS_HAT1X', + 19: 'ABS_HAT1Y', + 20: 'ABS_HAT2X', + 21: 'ABS_HAT2Y', + 22: 'ABS_HAT3X', + 23: 'ABS_HAT3Y', + 24: 'ABS_PRESSURE', + 25: 'ABS_DISTANCE', + 26: 'ABS_TILT_X', + 27: 'ABS_TILT_Y', + 28: 'ABS_TOOL_WIDTH', + 32: 'ABS_VOLUME', + 33: 'ABS_PROFILE', + 40: 'ABS_MISC', + 46: 'ABS_RESERVED', + 47: 'ABS_MT_SLOT', + 48: 'ABS_MT_TOUCH_MAJOR', + 49: 'ABS_MT_TOUCH_MINOR', + 50: 'ABS_MT_WIDTH_MAJOR', + 51: 'ABS_MT_WIDTH_MINOR', + 52: 'ABS_MT_ORIENTATION', + 53: 'ABS_MT_POSITION_X', + 54: 'ABS_MT_POSITION_Y', + 55: 'ABS_MT_TOOL_TYPE', + 56: 'ABS_MT_BLOB_ID', + 57: 'ABS_MT_TRACKING_ID', + 58: 'ABS_MT_PRESSURE', + 59: 'ABS_MT_DISTANCE', + 60: 'ABS_MT_TOOL_X', + 61: 'ABS_MT_TOOL_Y', + 63: 'ABS_MAX', + 64: 'ABS_CNT'} + +REL: Dict[int, Union[str, Tuple[str]]] = { 0: 'REL_X', + 1: 'REL_Y', + 2: 'REL_Z', + 3: 'REL_RX', + 4: 'REL_RY', + 5: 'REL_RZ', + 6: 'REL_HWHEEL', + 7: 'REL_DIAL', + 8: 'REL_WHEEL', + 9: 'REL_MISC', + 10: 'REL_RESERVED', + 11: 'REL_WHEEL_HI_RES', + 12: 'REL_HWHEEL_HI_RES', + 15: 'REL_MAX', + 16: 'REL_CNT'} + +SW: Dict[int, Union[str, Tuple[str]]] = { 0: 'SW_LID', + 1: 'SW_TABLET_MODE', + 2: 'SW_HEADPHONE_INSERT', + 3: ('SW_RADIO', 'SW_RFKILL_ALL'), + 4: 'SW_MICROPHONE_INSERT', + 5: 'SW_DOCK', + 6: 'SW_LINEOUT_INSERT', + 7: 'SW_JACK_PHYSICAL_INSERT', + 8: 'SW_VIDEOOUT_INSERT', + 9: 'SW_CAMERA_LENS_COVER', + 10: 'SW_KEYPAD_SLIDE', + 11: 'SW_FRONT_PROXIMITY', + 12: 'SW_ROTATE_LOCK', + 13: 'SW_LINEIN_INSERT', + 14: 'SW_MUTE_DEVICE', + 15: 'SW_PEN_INSERTED', + 16: ('SW_MACHINE_COVER', 'SW_MAX'), + 17: 'SW_CNT'} + +MSC: Dict[int, Union[str, Tuple[str]]] = { 0: 'MSC_SERIAL', + 1: 'MSC_PULSELED', + 2: 'MSC_GESTURE', + 3: 'MSC_RAW', + 4: 'MSC_SCAN', + 5: 'MSC_TIMESTAMP', + 7: 'MSC_MAX', + 8: 'MSC_CNT'} + +LED: Dict[int, Union[str, Tuple[str]]] = { 0: 'LED_NUML', + 1: 'LED_CAPSL', + 2: 'LED_SCROLLL', + 3: 'LED_COMPOSE', + 4: 'LED_KANA', + 5: 'LED_SLEEP', + 6: 'LED_SUSPEND', + 7: 'LED_MUTE', + 8: 'LED_MISC', + 9: 'LED_MAIL', + 10: 'LED_CHARGING', + 15: 'LED_MAX', + 16: 'LED_CNT'} + +BTN: Dict[int, Union[str, Tuple[str]]] = { 256: ('BTN_0', 'BTN_MISC'), + 257: 'BTN_1', + 258: 'BTN_2', + 259: 'BTN_3', + 260: 'BTN_4', + 261: 'BTN_5', + 262: 'BTN_6', + 263: 'BTN_7', + 264: 'BTN_8', + 265: 'BTN_9', + 272: ('BTN_LEFT', 'BTN_MOUSE'), + 273: 'BTN_RIGHT', + 274: 'BTN_MIDDLE', + 275: 'BTN_SIDE', + 276: 'BTN_EXTRA', + 277: 'BTN_FORWARD', + 278: 'BTN_BACK', + 279: 'BTN_TASK', + 288: ('BTN_JOYSTICK', 'BTN_TRIGGER'), + 289: 'BTN_THUMB', + 290: 'BTN_THUMB2', + 291: 'BTN_TOP', + 292: 'BTN_TOP2', + 293: 'BTN_PINKIE', + 294: 'BTN_BASE', + 295: 'BTN_BASE2', + 296: 'BTN_BASE3', + 297: 'BTN_BASE4', + 298: 'BTN_BASE5', + 299: 'BTN_BASE6', + 303: 'BTN_DEAD', + 304: ('BTN_A', 'BTN_GAMEPAD', 'BTN_SOUTH'), + 305: ('BTN_B', 'BTN_EAST'), + 306: 'BTN_C', + 307: ('BTN_NORTH', 'BTN_X'), + 308: ('BTN_WEST', 'BTN_Y'), + 309: 'BTN_Z', + 310: 'BTN_TL', + 311: 'BTN_TR', + 312: 'BTN_TL2', + 313: 'BTN_TR2', + 314: 'BTN_SELECT', + 315: 'BTN_START', + 316: 'BTN_MODE', + 317: 'BTN_THUMBL', + 318: 'BTN_THUMBR', + 320: ('BTN_DIGI', 'BTN_TOOL_PEN'), + 321: 'BTN_TOOL_RUBBER', + 322: 'BTN_TOOL_BRUSH', + 323: 'BTN_TOOL_PENCIL', + 324: 'BTN_TOOL_AIRBRUSH', + 325: 'BTN_TOOL_FINGER', + 326: 'BTN_TOOL_MOUSE', + 327: 'BTN_TOOL_LENS', + 328: 'BTN_TOOL_QUINTTAP', + 329: 'BTN_STYLUS3', + 330: 'BTN_TOUCH', + 331: 'BTN_STYLUS', + 332: 'BTN_STYLUS2', + 333: 'BTN_TOOL_DOUBLETAP', + 334: 'BTN_TOOL_TRIPLETAP', + 335: 'BTN_TOOL_QUADTAP', + 336: ('BTN_GEAR_DOWN', 'BTN_WHEEL'), + 337: 'BTN_GEAR_UP', + 544: 'BTN_DPAD_UP', + 545: 'BTN_DPAD_DOWN', + 546: 'BTN_DPAD_LEFT', + 547: 'BTN_DPAD_RIGHT', + 704: ('BTN_TRIGGER_HAPPY', 'BTN_TRIGGER_HAPPY1'), + 705: 'BTN_TRIGGER_HAPPY2', + 706: 'BTN_TRIGGER_HAPPY3', + 707: 'BTN_TRIGGER_HAPPY4', + 708: 'BTN_TRIGGER_HAPPY5', + 709: 'BTN_TRIGGER_HAPPY6', + 710: 'BTN_TRIGGER_HAPPY7', + 711: 'BTN_TRIGGER_HAPPY8', + 712: 'BTN_TRIGGER_HAPPY9', + 713: 'BTN_TRIGGER_HAPPY10', + 714: 'BTN_TRIGGER_HAPPY11', + 715: 'BTN_TRIGGER_HAPPY12', + 716: 'BTN_TRIGGER_HAPPY13', + 717: 'BTN_TRIGGER_HAPPY14', + 718: 'BTN_TRIGGER_HAPPY15', + 719: 'BTN_TRIGGER_HAPPY16', + 720: 'BTN_TRIGGER_HAPPY17', + 721: 'BTN_TRIGGER_HAPPY18', + 722: 'BTN_TRIGGER_HAPPY19', + 723: 'BTN_TRIGGER_HAPPY20', + 724: 'BTN_TRIGGER_HAPPY21', + 725: 'BTN_TRIGGER_HAPPY22', + 726: 'BTN_TRIGGER_HAPPY23', + 727: 'BTN_TRIGGER_HAPPY24', + 728: 'BTN_TRIGGER_HAPPY25', + 729: 'BTN_TRIGGER_HAPPY26', + 730: 'BTN_TRIGGER_HAPPY27', + 731: 'BTN_TRIGGER_HAPPY28', + 732: 'BTN_TRIGGER_HAPPY29', + 733: 'BTN_TRIGGER_HAPPY30', + 734: 'BTN_TRIGGER_HAPPY31', + 735: 'BTN_TRIGGER_HAPPY32', + 736: 'BTN_TRIGGER_HAPPY33', + 737: 'BTN_TRIGGER_HAPPY34', + 738: 'BTN_TRIGGER_HAPPY35', + 739: 'BTN_TRIGGER_HAPPY36', + 740: 'BTN_TRIGGER_HAPPY37', + 741: 'BTN_TRIGGER_HAPPY38', + 742: 'BTN_TRIGGER_HAPPY39', + 743: 'BTN_TRIGGER_HAPPY40'} + +REP: Dict[int, Union[str, Tuple[str]]] = {0: 'REP_DELAY', 1: ('REP_MAX', 'REP_PERIOD'), 2: 'REP_CNT'} + +SND: Dict[int, Union[str, Tuple[str]]] = {0: 'SND_CLICK', 1: 'SND_BELL', 2: 'SND_TONE', 7: 'SND_MAX', 8: 'SND_CNT'} + +ID: Dict[int, Union[str, Tuple[str]]] = {0: 'ID_BUS', 1: 'ID_VENDOR', 2: 'ID_PRODUCT', 3: 'ID_VERSION'} + +EV: Dict[int, Union[str, Tuple[str]]] = { 0: 'EV_SYN', + 1: 'EV_KEY', + 2: 'EV_REL', + 3: 'EV_ABS', + 4: 'EV_MSC', + 5: 'EV_SW', + 17: 'EV_LED', + 18: 'EV_SND', + 20: 'EV_REP', + 21: 'EV_FF', + 22: 'EV_PWR', + 23: 'EV_FF_STATUS', + 31: 'EV_MAX', + 32: 'EV_CNT', + 257: 'EV_UINPUT', + 65537: 'EV_VERSION'} + +BUS: Dict[int, Union[str, Tuple[str]]] = { 1: 'BUS_PCI', + 2: 'BUS_ISAPNP', + 3: 'BUS_USB', + 4: 'BUS_HIL', + 5: 'BUS_BLUETOOTH', + 6: 'BUS_VIRTUAL', + 16: 'BUS_ISA', + 17: 'BUS_I8042', + 18: 'BUS_XTKBD', + 19: 'BUS_RS232', + 20: 'BUS_GAMEPORT', + 21: 'BUS_PARPORT', + 22: 'BUS_AMIGA', + 23: 'BUS_ADB', + 24: 'BUS_I2C', + 25: 'BUS_HOST', + 26: 'BUS_GSC', + 27: 'BUS_ATARI', + 28: 'BUS_SPI', + 29: 'BUS_RMI', + 30: 'BUS_CEC', + 31: 'BUS_INTEL_ISHTP', + 32: 'BUS_AMD_SFH'} + +SYN: Dict[int, Union[str, Tuple[str]]] = {0: 'SYN_REPORT', 1: 'SYN_CONFIG', 2: 'SYN_MT_REPORT', 3: 'SYN_DROPPED', 15: 'SYN_MAX', 16: 'SYN_CNT'} + +FF: Dict[int, Union[str, Tuple[str]]] = { 80: ('FF_EFFECT_MIN', 'FF_RUMBLE'), + 81: 'FF_PERIODIC', + 82: 'FF_CONSTANT', + 83: 'FF_SPRING', + 84: 'FF_FRICTION', + 85: 'FF_DAMPER', + 86: 'FF_INERTIA', + 87: ('FF_EFFECT_MAX', 'FF_RAMP'), + 88: ('FF_SQUARE', 'FF_WAVEFORM_MIN'), + 89: 'FF_TRIANGLE', + 90: 'FF_SINE', + 91: 'FF_SAW_UP', + 92: 'FF_SAW_DOWN', + 93: ('FF_CUSTOM', 'FF_WAVEFORM_MAX'), + 96: ('FF_GAIN', 'FF_MAX_EFFECTS'), + 97: 'FF_AUTOCENTER', + 127: 'FF_MAX', + 128: 'FF_CNT'} + +UI_FF: Dict[int, Union[str, Tuple[str]]] = {1: 'UI_FF_UPLOAD', 2: 'UI_FF_ERASE'} + +FF_STATUS: Dict[int, Union[str, Tuple[str]]] = {0: 'FF_STATUS_STOPPED', 1: ('FF_STATUS_MAX', 'FF_STATUS_PLAYING')} + +INPUT_PROP: Dict[int, Union[str, Tuple[str]]] = { 0: 'INPUT_PROP_POINTER', + 1: 'INPUT_PROP_DIRECT', + 2: 'INPUT_PROP_BUTTONPAD', + 3: 'INPUT_PROP_SEMI_MT', + 4: 'INPUT_PROP_TOPBUTTONPAD', + 5: 'INPUT_PROP_POINTING_STICK', + 6: 'INPUT_PROP_ACCELEROMETER', + 31: 'INPUT_PROP_MAX', + 32: 'INPUT_PROP_CNT'} + diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/ecodes_runtime.py b/CLI/venv/lib/python3.12/site-packages/evdev/ecodes_runtime.py new file mode 100644 index 0000000..47f3b23 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/ecodes_runtime.py @@ -0,0 +1,111 @@ +# pylint: disable=undefined-variable +""" +This modules exposes the integer constants defined in ``linux/input.h`` and +``linux/input-event-codes.h``. + +Exposed constants:: + + KEY, ABS, REL, SW, MSC, LED, BTN, REP, SND, ID, EV, + BUS, SYN, FF, FF_STATUS, INPUT_PROP + +This module also provides reverse and forward mappings of the names and values +of the above mentioned constants:: + + >>> evdev.ecodes.KEY_A + 30 + + >>> evdev.ecodes.ecodes['KEY_A'] + 30 + + >>> evdev.ecodes.KEY[30] + 'KEY_A' + + >>> evdev.ecodes.REL[0] + 'REL_X' + + >>> evdev.ecodes.EV[evdev.ecodes.EV_KEY] + 'EV_KEY' + + >>> evdev.ecodes.bytype[evdev.ecodes.EV_REL][0] + 'REL_X' + +Keep in mind that values in reverse mappings may point to one or more event +codes. For example:: + + >>> evdev.ecodes.FF[80] + ('FF_EFFECT_MIN', 'FF_RUMBLE') + + >>> evdev.ecodes.FF[81] + 'FF_PERIODIC' +""" + +from inspect import getmembers + +from . import _ecodes + +#: Mapping of names to values. +ecodes = {} + +prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP UI_FF".split() +prev_prefix = "" +g = globals() + +# eg. code: 'REL_Z', val: 2 +for code, val in getmembers(_ecodes): + for prefix in prefixes: # eg. 'REL' + if code.startswith(prefix): + ecodes[code] = val + # FF_STATUS codes should not appear in the FF reverse mapping + if not code.startswith(prev_prefix): + d = g.setdefault(prefix, {}) + # codes that share the same value will be added to a list. eg: + # >>> ecodes.FF_STATUS + # {0: 'FF_STATUS_STOPPED', 1: ['FF_STATUS_MAX', 'FF_STATUS_PLAYING']} + if val in d: + if isinstance(d[val], list): + d[val].append(code) + else: + d[val] = [d[val], code] + else: + d[val] = code + + prev_prefix = prefix + + +# Convert lists to tuples. +k, v = None, None +for prefix in prefixes: + for k, v in g[prefix].items(): + if isinstance(v, list): + g[prefix][k] = tuple(v) + + +#: Keys are a combination of all BTN and KEY codes. +keys = {} +keys.update(BTN) +keys.update(KEY) + +# make keys safe to use for the default list of uinput device +# capabilities +del keys[_ecodes.KEY_MAX] +del keys[_ecodes.KEY_CNT] + +#: Mapping of event types to other value/name mappings. +bytype = { + _ecodes.EV_KEY: keys, + _ecodes.EV_ABS: ABS, + _ecodes.EV_REL: REL, + _ecodes.EV_SW: SW, + _ecodes.EV_MSC: MSC, + _ecodes.EV_LED: LED, + _ecodes.EV_REP: REP, + _ecodes.EV_SND: SND, + _ecodes.EV_SYN: SYN, + _ecodes.EV_FF: FF, + _ecodes.EV_FF_STATUS: FF_STATUS, +} + +from evdev._ecodes import * + +# cheaper than whitelisting in an __all__ +del code, val, prefix, getmembers, g, d, k, v, prefixes, prev_prefix diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/eventio.py b/CLI/venv/lib/python3.12/site-packages/evdev/eventio.py new file mode 100644 index 0000000..bdb91a4 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/eventio.py @@ -0,0 +1,152 @@ +import fcntl +import functools +import os +import select +from typing import Iterator, Union + +from . import _input, _uinput, ecodes +from .events import InputEvent + + +# -------------------------------------------------------------------------- +class EvdevError(Exception): + pass + + +class EventIO: + """ + Base class for reading and writing input events. + + This class is used by :class:`InputDevice` and :class:`UInput`. + + - On, :class:`InputDevice` it used for reading user-generated events (e.g. + key presses, mouse movements) and writing feedback events (e.g. leds, + beeps). + + - On, :class:`UInput` it used for writing user-generated events (e.g. + key presses, mouse movements) and reading feedback events (e.g. leds, + beeps). + """ + + def fileno(self): + """ + Return the file descriptor to the open event device. This makes + it possible to pass instances directly to :func:`select.select()` and + :class:`asyncore.file_dispatcher`. + """ + return self.fd + + def read_loop(self) -> Iterator[InputEvent]: + """ + Enter an endless :func:`select.select()` loop that yields input events. + """ + + while True: + r, w, x = select.select([self.fd], [], []) + for event in self.read(): + yield event + + def read_one(self) -> Union[InputEvent, None]: + """ + Read and return a single input event as an instance of + :class:`InputEvent `. + + Return ``None`` if there are no pending input events. + """ + + # event -> (sec, usec, type, code, val) + event = _input.device_read(self.fd) + + if event: + return InputEvent(*event) + + def read(self) -> Iterator[InputEvent]: + """ + Read multiple input events from device. Return a generator object that + yields :class:`InputEvent ` instances. Raises + `BlockingIOError` if there are no available events at the moment. + """ + + # events -> ((sec, usec, type, code, val), ...) + events = _input.device_read_many(self.fd) + + for event in events: + yield InputEvent(*event) + + # pylint: disable=no-self-argument + def need_write(func): + """ + Decorator that raises :class:`EvdevError` if there is no write access to the + input device. + """ + + @functools.wraps(func) + def wrapper(*args): + fd = args[0].fd + if fcntl.fcntl(fd, fcntl.F_GETFL) & os.O_RDWR: + # pylint: disable=not-callable + return func(*args) + msg = 'no write access to device "%s"' % args[0].path + raise EvdevError(msg) + + return wrapper + + def write_event(self, event): + """ + Inject an input event into the input subsystem. Events are + queued until a synchronization event is received. + + Arguments + --------- + event: InputEvent + InputEvent instance or an object with an ``event`` attribute + (:class:`KeyEvent `, :class:`RelEvent + ` etc). + + Example + ------- + >>> ev = InputEvent(1334414993, 274296, ecodes.EV_KEY, ecodes.KEY_A, 1) + >>> ui.write_event(ev) + """ + + if hasattr(event, "event"): + event = event.event + + self.write(event.type, event.code, event.value) + + @need_write + def write(self, etype: int, code: int, value: int): + """ + Inject an input event into the input subsystem. Events are + queued until a synchronization event is received. + + Arguments + --------- + etype + event type (e.g. ``EV_KEY``). + + code + event code (e.g. ``KEY_A``). + + value + event value (e.g. 0 1 2 - depends on event type). + + Example + --------- + >>> ui.write(e.EV_KEY, e.KEY_A, 1) # key A - down + >>> ui.write(e.EV_KEY, e.KEY_A, 0) # key A - up + """ + + _uinput.write(self.fd, etype, code, value) + + def syn(self): + """ + Inject a ``SYN_REPORT`` event into the input subsystem. Events + queued by :func:`write()` will be fired. If possible, events + will be merged into an 'atomic' event. + """ + + self.write(ecodes.EV_SYN, ecodes.SYN_REPORT, 0) + + def close(self): + pass diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/eventio_async.py b/CLI/venv/lib/python3.12/site-packages/evdev/eventio_async.py new file mode 100644 index 0000000..4af1aab --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/eventio_async.py @@ -0,0 +1,106 @@ +import asyncio +import select +import sys + +from . import eventio +from .events import InputEvent + +# needed for compatibility +from .eventio import EvdevError + +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing import Any as Self + + +class ReadIterator: + def __init__(self, device): + self.current_batch = iter(()) + self.device = device + + # Standard iterator protocol. + def __iter__(self) -> Self: + return self + + def __next__(self) -> InputEvent: + try: + # Read from the previous batch of events. + return next(self.current_batch) + except StopIteration: + r, w, x = select.select([self.device.fd], [], []) + self.current_batch = self.device.read() + return next(self.current_batch) + + def __aiter__(self) -> Self: + return self + + def __anext__(self) -> "asyncio.Future[InputEvent]": + future = asyncio.Future() + try: + # Read from the previous batch of events. + future.set_result(next(self.current_batch)) + except StopIteration: + + def next_batch_ready(batch): + try: + self.current_batch = batch.result() + future.set_result(next(self.current_batch)) + except Exception as e: + future.set_exception(e) + + self.device.async_read().add_done_callback(next_batch_ready) + return future + + +class EventIO(eventio.EventIO): + def _do_when_readable(self, callback): + loop = asyncio.get_event_loop() + + def ready(): + loop.remove_reader(self.fileno()) + callback() + + loop.add_reader(self.fileno(), ready) + + def _set_result(self, future, cb): + try: + future.set_result(cb()) + except Exception as error: + future.set_exception(error) + + def async_read_one(self): + """ + Asyncio coroutine to read and return a single input event as + an instance of :class:`InputEvent `. + """ + future = asyncio.Future() + self._do_when_readable(lambda: self._set_result(future, self.read_one)) + return future + + def async_read(self): + """ + Asyncio coroutine to read multiple input events from device. Return + a generator object that yields :class:`InputEvent ` + instances. + """ + future = asyncio.Future() + self._do_when_readable(lambda: self._set_result(future, self.read)) + return future + + def async_read_loop(self) -> ReadIterator: + """ + Return an iterator that yields input events. This iterator is + compatible with the ``async for`` syntax. + + """ + return ReadIterator(self) + + def close(self): + try: + loop = asyncio.get_event_loop() + loop.remove_reader(self.fileno()) + except RuntimeError: + # no event loop present, so there is nothing to + # remove the reader from. Ignore + pass diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/events.py b/CLI/venv/lib/python3.12/site-packages/evdev/events.py new file mode 100644 index 0000000..922bfe6 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/events.py @@ -0,0 +1,192 @@ +""" +This module provides the :class:`InputEvent` class, which closely +resembles the ``input_event`` struct defined in ``linux/input.h``: + +.. code-block:: c + + struct input_event { + struct timeval time; + __u16 type; + __u16 code; + __s32 value; + }; + +This module also defines several :class:`InputEvent` sub-classes that +know more about the different types of events (key, abs, rel etc). The +:data:`event_factory` dictionary maps event types to these classes. + +Assuming you use the :func:`evdev.util.categorize()` function to +categorize events according to their type, adding or replacing a class +for a specific event type becomes a matter of modifying +:data:`event_factory`. + +All classes in this module have reasonable ``str()`` and ``repr()`` +methods:: + + >>> print(event) + event at 1337197425.477827, code 04, type 04, val 458792 + >>> print(repr(event)) + InputEvent(1337197425L, 477827L, 4, 4, 458792L) + + >>> print(key_event) + key event at 1337197425.477835, 28 (KEY_ENTER), up + >>> print(repr(key_event)) + KeyEvent(InputEvent(1337197425L, 477835L, 1, 28, 0L)) +""" + +# event type descriptions have been taken mot-a-mot from: +# http://www.kernel.org/doc/Documentation/input/event-codes.txt + +# pylint: disable=no-name-in-module +from typing import Final +from .ecodes import ABS, EV_ABS, EV_KEY, EV_REL, EV_SYN, KEY, REL, SYN, keys + + +class InputEvent: + """A generic input event.""" + + __slots__ = "sec", "usec", "type", "code", "value" + + def __init__(self, sec, usec, type, code, value): + #: Time in seconds since epoch at which event occurred. + self.sec: int = sec + + #: Microsecond portion of the timestamp. + self.usec: int = usec + + #: Event type - one of ``ecodes.EV_*``. + self.type: int = type + + #: Event code related to the event type. + self.code: int = code + + #: Event value related to the event type. + self.value: int = value + + def timestamp(self) -> float: + """Return event timestamp as a float.""" + return self.sec + (self.usec / 1000000.0) + + def __str__(self): + msg = "event at {:f}, code {:02d}, type {:02d}, val {:02d}" + return msg.format(self.timestamp(), self.code, self.type, self.value) + + def __repr__(self): + msg = "{}({!r}, {!r}, {!r}, {!r}, {!r})" + return msg.format(self.__class__.__name__, self.sec, self.usec, self.type, self.code, self.value) + + +class KeyEvent: + """An event generated by a keyboard, button or other key-like devices.""" + + key_up: Final[int] = 0x0 + key_down: Final[int] = 0x1 + key_hold: Final[int] = 0x2 + + __slots__ = "scancode", "keycode", "keystate", "event" + + def __init__(self, event: InputEvent, allow_unknown: bool = False): + """ + The ``allow_unknown`` argument determines what to do in the event of an event code + for which a key code cannot be found. If ``False`` a ``KeyError`` will be raised. + If ``True`` the keycode will be set to the hex value of the event code. + """ + + self.scancode: int = event.code + + if event.value == 0: + self.keystate = KeyEvent.key_up + elif event.value == 2: + self.keystate = KeyEvent.key_hold + elif event.value == 1: + self.keystate = KeyEvent.key_down + + try: + self.keycode = keys[event.code] + except KeyError: + if allow_unknown: + self.keycode = "0x{:02X}".format(event.code) + else: + raise + + #: Reference to an :class:`InputEvent` instance. + self.event: InputEvent = event + + def __str__(self): + try: + ks = ("up", "down", "hold")[self.keystate] + except IndexError: + ks = "unknown" + + msg = "key event at {:f}, {} ({}), {}" + return msg.format(self.event.timestamp(), self.scancode, self.keycode, ks) + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) + + +class RelEvent: + """A relative axis event (e.g moving the mouse 5 units to the left).""" + + __slots__ = "event" + + def __init__(self, event: InputEvent): + #: Reference to an :class:`InputEvent` instance. + self.event: InputEvent = event + + def __str__(self): + msg = "relative axis event at {:f}, {}" + return msg.format(self.event.timestamp(), REL[self.event.code]) + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) + + +class AbsEvent: + """An absolute axis event (e.g the coordinates of a tap on a touchscreen).""" + + __slots__ = "event" + + def __init__(self, event: InputEvent): + #: Reference to an :class:`InputEvent` instance. + self.event: InputEvent = event + + def __str__(self): + msg = "absolute axis event at {:f}, {}" + return msg.format(self.event.timestamp(), ABS[self.event.code]) + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) + + +class SynEvent: + """ + A synchronization event. Used as markers to separate events. Events may be + separated in time or in space, such as with the multitouch protocol. + """ + + __slots__ = "event" + + def __init__(self, event: InputEvent): + #: Reference to an :class:`InputEvent` instance. + self.event: InputEvent = event + + def __str__(self): + msg = "synchronization event at {:f}, {}" + return msg.format(self.event.timestamp(), SYN[self.event.code]) + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) + + +#: A mapping of event types to :class:`InputEvent` sub-classes. Used +#: by :func:`evdev.util.categorize()` +event_factory = { + EV_KEY: KeyEvent, + EV_REL: RelEvent, + EV_ABS: AbsEvent, + EV_SYN: SynEvent, +} + + +__all__ = ("InputEvent", "KeyEvent", "RelEvent", "SynEvent", "AbsEvent", "event_factory") diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/evtest.py b/CLI/venv/lib/python3.12/site-packages/evdev/evtest.py new file mode 100644 index 0000000..6ea3bb5 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/evtest.py @@ -0,0 +1,181 @@ +""" +Usage: evtest [options] [, ...] + +Input device enumerator and event monitor. + +Running evtest without any arguments will let you select +from a list of all readable input devices. + +Options: + -h, --help Show this help message and exit. + -c, --capabilities List device capabilities and exit. + -g, --grab Other applications will not receive events from + the selected devices while evtest is running. + +Examples: + evtest /dev/input/event0 /dev/input/event1 +""" + +import atexit +import optparse +import re +import select +import sys +import termios + +from . import AbsInfo, InputDevice, ecodes, list_devices + + +def parseopt(): + parser = optparse.OptionParser(add_help_option=False) + parser.add_option("-h", "--help", action="store_true") + parser.add_option("-g", "--grab", action="store_true") + parser.add_option("-c", "--capabilities", action="store_true") + return parser.parse_args() + + +def main(): + opts, devices = parseopt() + if opts.help: + print(__doc__.strip()) + return 0 + + if not devices: + devices = select_devices() + else: + devices = [InputDevice(path) for path in devices] + + if opts.capabilities: + for device in devices: + print_capabilities(device) + return 0 + + if opts.grab: + for device in devices: + device.grab() + + # Disable tty echoing if stdin is a tty. + if sys.stdin.isatty(): + toggle_tty_echo(sys.stdin, enable=False) + atexit.register(toggle_tty_echo, sys.stdin, enable=True) + + print("Listening for events (press ctrl-c to exit) ...") + fd_to_device = {dev.fd: dev for dev in devices} + while True: + r, w, e = select.select(fd_to_device, [], []) + + for fd in r: + for event in fd_to_device[fd].read(): + print_event(event) + + +def select_devices(device_dir="/dev/input"): + """ + Select one or more devices from a list of accessible input devices. + """ + + def devicenum(device_path): + digits = re.findall(r"\d+$", device_path) + return [int(i) for i in digits] + + devices = sorted(list_devices(device_dir), key=devicenum) + devices = [InputDevice(path) for path in devices] + if not devices: + msg = "error: no input devices found (do you have rw permission on %s/*?)" + print(msg % device_dir, file=sys.stderr) + sys.exit(1) + + dev_format = "{0:<3} {1.path:<20} {1.name:<35} {1.phys:<35} {1.uniq:<4}" + dev_lines = [dev_format.format(num, dev) for num, dev in enumerate(devices)] + + print("ID {:<20} {:<35} {:<35} {}".format("Device", "Name", "Phys", "Uniq")) + print("-" * len(max(dev_lines, key=len))) + print("\n".join(dev_lines)) + print() + + choices = input("Select devices [0-%s]: " % (len(dev_lines) - 1)) + + try: + choices = choices.split() + choices = [devices[int(num)] for num in choices] + except ValueError: + choices = None + + if not choices: + msg = "error: invalid input - please enter one or more numbers separated by spaces" + print(msg, file=sys.stderr) + sys.exit(1) + + return choices + + +def print_capabilities(device): + capabilities = device.capabilities(verbose=True) + input_props = device.input_props(verbose=True) + + print("Device name: {.name}".format(device)) + print("Device info: {.info}".format(device)) + print("Repeat settings: {}\n".format(device.repeat)) + + if ("EV_LED", ecodes.EV_LED) in capabilities: + leds = ",".join(i[0] for i in device.leds(True)) + print("Active LEDs: %s" % leds) + + active_keys = ",".join(k[0] for k in device.active_keys(True)) + print("Active keys: %s\n" % active_keys) + + if input_props: + print("Input properties:") + for type, code in input_props: + print(" %s %s" % (type, code)) + print() + + print("Device capabilities:") + for type, codes in capabilities.items(): + print(" Type {} {}:".format(*type)) + for code in codes: + # code <- ('BTN_RIGHT', 273) or (['BTN_LEFT', 'BTN_MOUSE'], 272) + if isinstance(code[1], AbsInfo): + print(" Code {:<4} {}:".format(*code[0])) + print(" {}".format(code[1])) + else: + # Multiple names may resolve to one value. + s = ", ".join(code[0]) if isinstance(code[0], list) else code[0] + print(" Code {:<4} {}".format(s, code[1])) + print("") + + +def print_event(e): + if e.type == ecodes.EV_SYN: + if e.code == ecodes.SYN_MT_REPORT: + msg = "time {:<17} +++++++++++++ {} +++++++++++++" + elif e.code == ecodes.SYN_DROPPED: + msg = "time {:<17} !!!!!!!!!!!!! {} !!!!!!!!!!!!!" + else: + msg = "time {:<17} ------------- {} -------------" + print(msg.format(e.timestamp(), ecodes.SYN[e.code])) + else: + if e.type in ecodes.bytype: + codename = ecodes.bytype[e.type][e.code] + else: + codename = "?" + + evfmt = "time {:<17} type {} ({}), code {:<4} ({}), value {}" + print(evfmt.format(e.timestamp(), e.type, ecodes.EV[e.type], e.code, codename, e.value)) + + +def toggle_tty_echo(fh, enable=True): + flags = termios.tcgetattr(fh.fileno()) + if enable: + flags[3] |= termios.ECHO + else: + flags[3] &= ~termios.ECHO + termios.tcsetattr(fh.fileno(), termios.TCSANOW, flags) + + +if __name__ == "__main__": + try: + ret = main() + except (KeyboardInterrupt, EOFError): + ret = 0 + sys.exit(ret) diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/ff.py b/CLI/venv/lib/python3.12/site-packages/evdev/ff.py new file mode 100644 index 0000000..260c362 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/ff.py @@ -0,0 +1,198 @@ +import ctypes + +from . import ecodes + +_u8 = ctypes.c_uint8 +_u16 = ctypes.c_uint16 +_u32 = ctypes.c_uint32 +_s16 = ctypes.c_int16 +_s32 = ctypes.c_int32 + + +class Replay(ctypes.Structure): + """ + Defines scheduling of the force-feedback effect + @length: duration of the effect + @delay: delay before effect should start playing + """ + + _fields_ = [ + ("length", _u16), + ("delay", _u16), + ] + + +class Trigger(ctypes.Structure): + """ + Defines what triggers the force-feedback effect + @button: number of the button triggering the effect + @interval: controls how soon the effect can be re-triggered + """ + + _fields_ = [ + ("button", _u16), + ("interval", _u16), + ] + + +class Envelope(ctypes.Structure): + """ + Generic force-feedback effect envelope + @attack_length: duration of the attack (ms) + @attack_level: level at the beginning of the attack + @fade_length: duration of fade (ms) + @fade_level: level at the end of fade + + The @attack_level and @fade_level are absolute values; when applying + envelope force-feedback core will convert to positive/negative + value based on polarity of the default level of the effect. + Valid range for the attack and fade levels is 0x0000 - 0x7fff + """ + + _fields_ = [ + ("attack_length", _u16), + ("attack_level", _u16), + ("fade_length", _u16), + ("fade_level", _u16), + ] + + +class Constant(ctypes.Structure): + """ + Defines parameters of a constant force-feedback effect + @level: strength of the effect; may be negative + @envelope: envelope data + """ + + _fields_ = [ + ("level", _s16), + ("ff_envelope", Envelope), + ] + + +class Ramp(ctypes.Structure): + """ + Defines parameters of a ramp force-feedback effect + @start_level: beginning strength of the effect; may be negative + @end_level: final strength of the effect; may be negative + @envelope: envelope data + """ + + _fields_ = [ + ("start_level", _s16), + ("end_level", _s16), + ("ff_envelope", Envelope), + ] + + +class Condition(ctypes.Structure): + """ + Defines a spring or friction force-feedback effect + @right_saturation: maximum level when joystick moved all way to the right + @left_saturation: same for the left side + @right_coeff: controls how fast the force grows when the joystick moves to the right + @left_coeff: same for the left side + @deadband: size of the dead zone, where no force is produced + @center: position of the dead zone + """ + + _fields_ = [ + ("right_saturation", _u16), + ("left_saturation", _u16), + ("right_coeff", _s16), + ("left_coeff", _s16), + ("deadband", _u16), + ("center", _s16), + ] + + +class Periodic(ctypes.Structure): + """ + Defines parameters of a periodic force-feedback effect + @waveform: kind of the effect (wave) + @period: period of the wave (ms) + @magnitude: peak value + @offset: mean value of the wave (roughly) + @phase: 'horizontal' shift + @envelope: envelope data + @custom_len: number of samples (FF_CUSTOM only) + @custom_data: buffer of samples (FF_CUSTOM only) + """ + + _fields_ = [ + ("waveform", _u16), + ("period", _u16), + ("magnitude", _s16), + ("offset", _s16), + ("phase", _u16), + ("envelope", Envelope), + ("custom_len", _u32), + ("custom_data", ctypes.POINTER(_s16)), + ] + + +class Rumble(ctypes.Structure): + """ + Defines parameters of a periodic force-feedback effect + @strong_magnitude: magnitude of the heavy motor + @weak_magnitude: magnitude of the light one + + Some rumble pads have two motors of different weight. Strong_magnitude + represents the magnitude of the vibration generated by the heavy one. + """ + + _fields_ = [ + ("strong_magnitude", _u16), + ("weak_magnitude", _u16), + ] + + +class EffectType(ctypes.Union): + _fields_ = [ + ("ff_constant_effect", Constant), + ("ff_ramp_effect", Ramp), + ("ff_periodic_effect", Periodic), + ("ff_condition_effect", Condition * 2), # one for each axis + ("ff_rumble_effect", Rumble), + ] + + +class Effect(ctypes.Structure): + _fields_ = [ + ("type", _u16), + ("id", _s16), + ("direction", _u16), + ("ff_trigger", Trigger), + ("ff_replay", Replay), + ("u", EffectType), + ] + + +class UInputUpload(ctypes.Structure): + _fields_ = [ + ("request_id", _u32), + ("retval", _s32), + ("effect", Effect), + ("old", Effect), + ] + + +class UInputErase(ctypes.Structure): + _fields_ = [ + ("request_id", _u32), + ("retval", _s32), + ("effect_id", _u32), + ] + + +# ff_types = { +# ecodes.FF_CONSTANT, +# ecodes.FF_PERIODIC, +# ecodes.FF_RAMP, +# ecodes.FF_SPRING, +# ecodes.FF_FRICTION, +# ecodes.FF_DAMPER, +# ecodes.FF_RUMBLE, +# ecodes.FF_INERTIA, +# ecodes.FF_CUSTOM, +# } diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/genecodes_c.py b/CLI/venv/lib/python3.12/site-packages/evdev/genecodes_c.py new file mode 100644 index 0000000..15a6693 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/genecodes_c.py @@ -0,0 +1,147 @@ +""" +Generate a Python extension module with the constants defined in linux/input.h. +""" + +import getopt +import os +import re +import sys + +# ----------------------------------------------------------------------------- +# The default header file locations to try. +headers = [ + "/usr/include/linux/input.h", + "/usr/include/linux/input-event-codes.h", + "/usr/include/linux/uinput.h", +] + +opts, args = getopt.getopt(sys.argv[1:], "", ["ecodes", "stubs", "reproducible"]) +if not opts: + print("usage: genecodes.py [--ecodes|--stubs] [--reproducible] ") + exit(2) + +if args: + headers = args + +reproducible = ("--reproducible", "") in opts + + +# ----------------------------------------------------------------------------- +macro_regex = r"#define\s+((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)" +macro_regex = re.compile(macro_regex) + +if reproducible: + uname = "hidden for reproducibility" +else: + # Uname without hostname. + uname = list(os.uname()) + uname = " ".join((uname[0], *uname[2:])) + + +# ----------------------------------------------------------------------------- +template_ecodes = r""" +#include +#ifdef __FreeBSD__ +#include +#include +#else +#include +#include +#endif + +/* Automatically generated by evdev.genecodes */ +/* Generated on %s */ +/* Generated from %s */ + +#define MODULE_NAME "_ecodes" +#define MODULE_HELP "linux/input.h macros" + +static PyMethodDef MethodTable[] = { + { NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + MODULE_NAME, + MODULE_HELP, + -1, /* m_size */ + MethodTable, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC +PyInit__ecodes(void) +{ + PyObject* m = PyModule_Create(&moduledef); + if (m == NULL) return NULL; + +%s + + return m; +} +""" + + +template_stubs = r""" +# Automatically generated by evdev.genecodes +# Generated on %s +# Generated from %s + +# pylint: skip-file + +ecodes: dict[str, int] +keys: dict[int, str|list[str]] +bytype: dict[int, dict[int, str|list[str]]] + +KEY: dict[int, str|list[str]] +ABS: dict[int, str|list[str]] +REL: dict[int, str|list[str]] +SW: dict[int, str|list[str]] +MSC: dict[int, str|list[str]] +LED: dict[int, str|list[str]] +BTN: dict[int, str|list[str]] +REP: dict[int, str|list[str]] +SND: dict[int, str|list[str]] +ID: dict[int, str|list[str]] +EV: dict[int, str|list[str]] +BUS: dict[int, str|list[str]] +SYN: dict[int, str|list[str]] +FF_STATUS: dict[int, str|list[str]] +FF_INPUT_PROP: dict[int, str|list[str]] + +%s +""" + + +def parse_headers(headers=headers): + for header in headers: + try: + fh = open(header) + except (IOError, OSError): + continue + + for line in fh: + macro = macro_regex.search(line) + if macro: + yield macro.group(1) + + +all_macros = list(parse_headers()) +if not all_macros: + print("no input macros found in: %s" % " ".join(headers), file=sys.stderr) + sys.exit(1) + +# pylint: disable=possibly-used-before-assignment, used-before-assignment +if ("--ecodes", "") in opts: + body = (" PyModule_AddIntMacro(m, %s);" % macro for macro in all_macros) + template = template_ecodes +elif ("--stubs", "") in opts: + body = ("%s: int" % macro for macro in all_macros) + template = template_stubs + +body = os.linesep.join(body) +text = template % (uname, headers if not reproducible else ["hidden for reproducibility"], body) +print(text.strip()) diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/genecodes_py.py b/CLI/venv/lib/python3.12/site-packages/evdev/genecodes_py.py new file mode 100644 index 0000000..f00020c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/genecodes_py.py @@ -0,0 +1,54 @@ +import sys +from unittest import mock +from pprint import PrettyPrinter + +sys.modules["evdev.ecodes"] = mock.Mock() +from evdev import ecodes_runtime as ecodes + +pprint = PrettyPrinter(indent=2, sort_dicts=True, width=120).pprint + + +print("# Automatically generated by evdev.genecodes_py") +print() +print('"""') +print(ecodes.__doc__.strip()) +print('"""') + +print() +print("from typing import Final, Dict, Tuple, Union") +print() + +for name, value in ecodes.ecodes.items(): + print(f"{name}: Final[int] = {value}") +print() + +entries = [ + ("ecodes", "Dict[str, int]", "#: Mapping of names to values."), + ("bytype", "Dict[int, Dict[int, Union[str, Tuple[str]]]]", "#: Mapping of event types to other value/name mappings."), + ("keys", "Dict[int, Union[str, Tuple[str]]]", "#: Keys are a combination of all BTN and KEY codes."), + ("KEY", "Dict[int, Union[str, Tuple[str]]]", None), + ("ABS", "Dict[int, Union[str, Tuple[str]]]", None), + ("REL", "Dict[int, Union[str, Tuple[str]]]", None), + ("SW", "Dict[int, Union[str, Tuple[str]]]", None), + ("MSC", "Dict[int, Union[str, Tuple[str]]]", None), + ("LED", "Dict[int, Union[str, Tuple[str]]]", None), + ("BTN", "Dict[int, Union[str, Tuple[str]]]", None), + ("REP", "Dict[int, Union[str, Tuple[str]]]", None), + ("SND", "Dict[int, Union[str, Tuple[str]]]", None), + ("ID", "Dict[int, Union[str, Tuple[str]]]", None), + ("EV", "Dict[int, Union[str, Tuple[str]]]", None), + ("BUS", "Dict[int, Union[str, Tuple[str]]]", None), + ("SYN", "Dict[int, Union[str, Tuple[str]]]", None), + ("FF", "Dict[int, Union[str, Tuple[str]]]", None), + ("UI_FF", "Dict[int, Union[str, Tuple[str]]]", None), + ("FF_STATUS", "Dict[int, Union[str, Tuple[str]]]", None), + ("INPUT_PROP", "Dict[int, Union[str, Tuple[str]]]", None) +] + +for key, annotation, doc in entries: + if doc: + print(doc) + + print(f"{key}: {annotation} = ", end="") + pprint(getattr(ecodes, key)) + print() \ No newline at end of file diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/input.c b/CLI/venv/lib/python3.12/site-packages/evdev/input.c new file mode 100644 index 0000000..4ad0408 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/input.c @@ -0,0 +1,579 @@ + +/* + * Python bindings to certain linux input subsystem functions. + * + * While everything here can be implemented in pure Python with struct and + * fcntl.ioctl, imho, it is much more straightforward to do so in C. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#else +#include +#endif + +#ifndef input_event_sec +#define input_event_sec time.tv_sec +#define input_event_usec time.tv_usec +#endif + +#define MAX_NAME_SIZE 256 + +extern char* EV_NAME[EV_CNT]; +extern int EV_TYPE_MAX[EV_CNT]; +extern char** EV_TYPE_NAME[EV_CNT]; +extern char* BUS_NAME[]; + + +int test_bit(const char* bitmask, int bit) { + return bitmask[bit/8] & (1 << (bit % 8)); +} + + +// Read input event from a device and return a tuple that mimics input_event +static PyObject * +device_read(PyObject *self, PyObject *args) +{ + struct input_event event; + + // get device file descriptor (O_RDONLY|O_NONBLOCK) + int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0)); + + int n = read(fd, &event, sizeof(event)); + + if (n < 0) { + if (errno == EAGAIN) { + Py_INCREF(Py_None); + return Py_None; + } + + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + PyObject* sec = PyLong_FromLong(event.input_event_sec); + PyObject* usec = PyLong_FromLong(event.input_event_usec); + PyObject* val = PyLong_FromLong(event.value); + PyObject* type = PyLong_FromLong(event.type); + PyObject* code = PyLong_FromLong(event.code); + PyObject* py_input_event = PyTuple_Pack(5, sec, usec, type, code, val); + + return py_input_event; +} + + +// Read multiple input events from a device and return a list of tuples +static PyObject * +device_read_many(PyObject *self, PyObject *args) +{ + // get device file descriptor (O_RDONLY|O_NONBLOCK) + int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0)); + + PyObject* py_input_event = NULL; + PyObject* events = NULL; + PyObject* sec = NULL; + PyObject* usec = NULL; + PyObject* val = NULL; + PyObject* type = NULL; + PyObject* code = NULL; + + struct input_event event[64]; + + size_t event_size = sizeof(struct input_event); + ssize_t nread = read(fd, event, event_size*64); + + if (nread < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + // Construct a tuple of event tuples. Each tuple is the arguments to InputEvent. + size_t num_events = nread / event_size; + events = PyTuple_New(num_events); + for (size_t i = 0 ; i < num_events; i++) { + sec = PyLong_FromLong(event[i].input_event_sec); + usec = PyLong_FromLong(event[i].input_event_usec); + val = PyLong_FromLong(event[i].value); + type = PyLong_FromLong(event[i].type); + code = PyLong_FromLong(event[i].code); + + py_input_event = PyTuple_Pack(5, sec, usec, type, code, val); + PyTuple_SET_ITEM(events, i, py_input_event); + } + + return events; +} + + +// Get the event types and event codes that the input device supports +static PyObject * +ioctl_capabilities(PyObject *self, PyObject *args) +{ + int fd, ev_type, ev_code; + char ev_bits[EV_MAX/8 + 1], code_bits[KEY_MAX/8 + 1]; + struct input_absinfo absinfo; + + int ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + // @todo: figure out why fd gets zeroed on an ioctl after the + // refactoring and get rid of this workaround + const int _fd = fd; + + // Capabilities is a mapping of supported event types to lists of handled + // events e.g: {1: [272, 273, 274, 275], 2: [0, 1, 6, 8]} + PyObject* capabilities = PyDict_New(); + PyObject* eventcodes = NULL; + PyObject* evlong = NULL; + PyObject* capability = NULL; + PyObject* py_absinfo = NULL; + PyObject* absitem = NULL; + + memset(&ev_bits, 0, sizeof(ev_bits)); + + if (ioctl(_fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) + goto on_err; + + // Build a dictionary of the device's capabilities + for (ev_type=0 ; ev_type tuple(ABS_X, (0, 255, 0, 0)) + PyList_Append(eventcodes, absitem); + + Py_DECREF(absitem); + Py_DECREF(py_absinfo); + } + else { + evlong = PyLong_FromLong(ev_code); + PyList_Append(eventcodes, evlong); + } + + Py_DECREF(evlong); + } + } + // capabilities[EV_KEY] = [KEY_A, KEY_B, KEY_C, ...] + // capabilities[EV_ABS] = [(ABS_X, (0, 255, 0, 0)), ...] + PyDict_SetItem(capabilities, capability, eventcodes); + + Py_DECREF(capability); + Py_DECREF(eventcodes); + } + } + + return capabilities; + + on_err: + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + + +// An all-in-one function for describing an input device +static PyObject * +ioctl_devinfo(PyObject *self, PyObject *args) +{ + int fd; + + struct input_id iid; + char name[MAX_NAME_SIZE]; + char phys[MAX_NAME_SIZE] = {0}; + char uniq[MAX_NAME_SIZE] = {0}; + + int ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + memset(&iid, 0, sizeof(iid)); + + if (ioctl(fd, EVIOCGID, &iid) < 0) goto on_err; + if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) goto on_err; + + // Some devices do not have a physical topology associated with them + ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys); + + // Some kernels have started reporting bluetooth controller MACs as phys. + // This lets us get the real physical address. As with phys, it may be blank. + ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq); + + return Py_BuildValue("hhhhsss", iid.bustype, iid.vendor, iid.product, iid.version, + name, phys, uniq); + + on_err: + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + + +static PyObject * +ioctl_EVIOCGABS(PyObject *self, PyObject *args) +{ + int fd, ev_code; + struct input_absinfo absinfo; + PyObject* py_absinfo = NULL; + + int ret = PyArg_ParseTuple(args, "ii", &fd, &ev_code); + if (!ret) return NULL; + + memset(&absinfo, 0, sizeof(absinfo)); + ret = ioctl(fd, EVIOCGABS(ev_code), &absinfo); + if (ret == -1) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + py_absinfo = Py_BuildValue("(iiiiii)", + absinfo.value, + absinfo.minimum, + absinfo.maximum, + absinfo.fuzz, + absinfo.flat, + absinfo.resolution); + return py_absinfo; +} + + +static PyObject * +ioctl_EVIOCSABS(PyObject *self, PyObject *args) +{ + int fd, ev_code; + struct input_absinfo absinfo; + + int ret = PyArg_ParseTuple(args, + "ii(iiiiii)", + &fd, + &ev_code, + &absinfo.value, + &absinfo.minimum, + &absinfo.maximum, + &absinfo.fuzz, + &absinfo.flat, + &absinfo.resolution); + if (!ret) return NULL; + + ret = ioctl(fd, EVIOCSABS(ev_code), &absinfo); + if (ret == -1) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + + +static PyObject * +ioctl_EVIOCGREP(PyObject *self, PyObject *args) +{ + int fd, ret; + unsigned int rep[REP_CNT] = {0}; + ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + ret = ioctl(fd, EVIOCGREP, &rep); + if (ret == -1) + return NULL; + + return Py_BuildValue("(ii)", rep[REP_DELAY], rep[REP_PERIOD]); +} + + +static PyObject * +ioctl_EVIOCSREP(PyObject *self, PyObject *args) +{ + int fd, ret; + unsigned int rep[REP_CNT] = {0}; + + ret = PyArg_ParseTuple(args, "iii", &fd, &rep[0], &rep[1]); + if (!ret) return NULL; + + ret = ioctl(fd, EVIOCSREP, &rep); + if (ret == -1) + return NULL; + + return Py_BuildValue("i", ret); +} + + +static PyObject * +ioctl_EVIOCGVERSION(PyObject *self, PyObject *args) +{ + int fd, ret, res; + ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + ret = ioctl(fd, EVIOCGVERSION, &res); + if (ret == -1) + return NULL; + + return Py_BuildValue("i", res); +} + + +static PyObject * +ioctl_EVIOCGRAB(PyObject *self, PyObject *args) +{ + int fd, ret, flag; + ret = PyArg_ParseTuple(args, "ii", &fd, &flag); + if (!ret) return NULL; + + ret = ioctl(fd, EVIOCGRAB, (intptr_t)flag); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + + +static PyObject * +ioctl_EVIOCG_bits(PyObject *self, PyObject *args) +{ + int max, fd, evtype, ret; + + ret = PyArg_ParseTuple(args, "ii", &fd, &evtype); + if (!ret) return NULL; + + switch (evtype) { + case EV_LED: + max = LED_MAX; break; + case EV_SND: + max = SND_MAX; break; + case EV_KEY: + max = KEY_MAX; break; + case EV_SW: + max = SW_MAX; break; + default: + return NULL; + } + + char bytes[(max+7)/8]; + memset(bytes, 0, sizeof bytes); + + switch (evtype) { + case EV_LED: + ret = ioctl(fd, EVIOCGLED(sizeof(bytes)), &bytes); + break; + case EV_SND: + ret = ioctl(fd, EVIOCGSND(sizeof(bytes)), &bytes); + break; + case EV_KEY: + ret = ioctl(fd, EVIOCGKEY(sizeof(bytes)), &bytes); + break; + case EV_SW: + ret = ioctl(fd, EVIOCGSW(sizeof(bytes)), &bytes); + break; + } + + if (ret == -1) + return NULL; + + PyObject* res = PyList_New(0); + for (int i=0; i<=max; i++) { + if (test_bit(bytes, i)) { + PyList_Append(res, Py_BuildValue("i", i)); + } + } + + return res; +} + + +static PyObject * +ioctl_EVIOCGEFFECTS(PyObject *self, PyObject *args) +{ + int fd, ret, res; + ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + ret = ioctl(fd, EVIOCGEFFECTS, &res); + if (ret == -1) + return NULL; + + return Py_BuildValue("i", res); +} + +void print_ff_effect(struct ff_effect* effect) { + fprintf(stderr, + "ff_effect:\n" + " type: %d \n" + " id: %d \n" + " direction: %d\n" + " trigger: (%d, %d)\n" + " replay: (%d, %d)\n", + effect->type, effect->id, effect->direction, + effect->trigger.button, effect->trigger.interval, + effect->replay.length, effect->replay.delay + ); + + + switch (effect->type) { + case FF_CONSTANT: + fprintf(stderr, " constant: (%d, (%d, %d, %d, %d))\n", effect->u.constant.level, + effect->u.constant.envelope.attack_length, + effect->u.constant.envelope.attack_level, + effect->u.constant.envelope.fade_length, + effect->u.constant.envelope.fade_level); + break; + case FF_RUMBLE: + fprintf(stderr, " rumble: (%d, %d)\n", + effect->u.rumble.strong_magnitude, + effect->u.rumble.weak_magnitude); + break; + } +} + + +static PyObject * +upload_effect(PyObject *self, PyObject *args) +{ + int fd, ret; + PyObject* effect_data; + ret = PyArg_ParseTuple(args, "iO", &fd, &effect_data); + if (!ret) return NULL; + + void* data = PyBytes_AsString(effect_data); + struct ff_effect effect = {}; + memmove(&effect, data, sizeof(struct ff_effect)); + + // print_ff_effect(&effect); + + ret = ioctl(fd, EVIOCSFF, &effect); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + return Py_BuildValue("i", effect.id); +} + + +static PyObject * +erase_effect(PyObject *self, PyObject *args) +{ + int fd, ret; + PyObject* ff_id_obj; + ret = PyArg_ParseTuple(args, "iO", &fd, &ff_id_obj); + if (!ret) return NULL; + + long ff_id = PyLong_AsLong(ff_id_obj); + ret = ioctl(fd, EVIOCRMFF, ff_id); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +ioctl_EVIOCGPROP(PyObject *self, PyObject *args) +{ + int fd, ret; + + ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + char bytes[(INPUT_PROP_MAX+7)/8]; + memset(bytes, 0, sizeof bytes); + + ret = ioctl(fd, EVIOCGPROP(sizeof(bytes)), &bytes); + + if (ret == -1) + return NULL; + + PyObject* res = PyList_New(0); + for (int i=0; i + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#include +#else +#include +#include +#endif + +#ifndef input_event_sec +#define input_event_sec time.tv_sec +#define input_event_usec time.tv_usec +#endif + +// Workaround for installing on kernels newer than 4.4. +#ifndef FF_MAX_EFFECTS +#define FF_MAX_EFFECTS FF_GAIN; +#endif + +int _uinput_close(int fd) +{ + if (ioctl(fd, UI_DEV_DESTROY) < 0) { + int oerrno = errno; + close(fd); + errno = oerrno; + return -1; + } + + return close(fd); +} + + +static PyObject * +uinput_open(PyObject *self, PyObject *args) +{ + const char* devnode; + + int ret = PyArg_ParseTuple(args, "s", &devnode); + if (!ret) return NULL; + + int fd = open(devnode, O_RDWR | O_NONBLOCK); + if (fd < 0) { + PyErr_SetString(PyExc_OSError, "could not open uinput device in write mode"); + return NULL; + } + + return Py_BuildValue("i", fd); +} + + +static PyObject * +uinput_set_phys(PyObject *self, PyObject *args) +{ + int fd; + const char* phys; + + int ret = PyArg_ParseTuple(args, "is", &fd, &phys); + if (!ret) return NULL; + + if (ioctl(fd, UI_SET_PHYS, phys) < 0) + goto on_err; + + Py_RETURN_NONE; + + on_err: + _uinput_close(fd); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + +static PyObject * +uinput_set_prop(PyObject *self, PyObject *args) +{ + int fd; + uint16_t prop; + + int ret = PyArg_ParseTuple(args, "ih", &fd, &prop); + if (!ret) return NULL; + + if (ioctl(fd, UI_SET_PROPBIT, prop) < 0) + goto on_err; + + Py_RETURN_NONE; + + on_err: + _uinput_close(fd); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + +static PyObject * +uinput_get_sysname(PyObject *self, PyObject *args) +{ + int fd; + char sysname[64]; + + int ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + #ifdef UI_GET_SYSNAME + if (ioctl(fd, UI_GET_SYSNAME(sizeof(sysname)), &sysname) < 0) + goto on_err; + + return Py_BuildValue("s", &sysname); + #endif + + on_err: + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + +// Different kernel versions have different device setup methods. You can read +// more about it here: +// https://github.com/torvalds/linux/commit/052876f8e5aec887d22c4d06e54aa5531ffcec75 + +// Setup function for kernel >= v4.5 +#if defined(UI_DEV_SETUP) && defined(UI_ABS_SETUP) +static PyObject * +uinput_setup(PyObject *self, PyObject *args) { + int fd, len, i; + uint16_t vendor, product, version, bustype; + uint32_t max_effects; + + PyObject *absinfo = NULL, *item = NULL; + + struct uinput_abs_setup abs_setup; + + const char* name; + int ret = PyArg_ParseTuple(args, "isHHHHOI", &fd, &name, &vendor, + &product, &version, &bustype, &absinfo, &max_effects); + if (!ret) return NULL; + + // Setup absinfo: + len = PyList_Size(absinfo); + for (i=0; i (ABS_X, 0, 255, 0, 0, 0, 0) + item = PyList_GetItem(absinfo, i); + + memset(&abs_setup, 0, sizeof(abs_setup)); // Clear struct + abs_setup.code = PyLong_AsLong(PyList_GetItem(item, 0)); + abs_setup.absinfo.value = PyLong_AsLong(PyList_GetItem(item, 1)); + abs_setup.absinfo.minimum = PyLong_AsLong(PyList_GetItem(item, 2)); + abs_setup.absinfo.maximum = PyLong_AsLong(PyList_GetItem(item, 3)); + abs_setup.absinfo.fuzz = PyLong_AsLong(PyList_GetItem(item, 4)); + abs_setup.absinfo.flat = PyLong_AsLong(PyList_GetItem(item, 5)); + abs_setup.absinfo.resolution = PyLong_AsLong(PyList_GetItem(item, 6)); + + if(ioctl(fd, UI_ABS_SETUP, &abs_setup) < 0) + goto on_err; + } + + // Setup evdev: + struct uinput_setup usetup; + + memset(&usetup, 0, sizeof(usetup)); + strncpy(usetup.name, name, sizeof(usetup.name) - 1); + usetup.id.vendor = vendor; + usetup.id.product = product; + usetup.id.version = version; + usetup.id.bustype = bustype; + usetup.ff_effects_max = max_effects; + + if(ioctl(fd, UI_DEV_SETUP, &usetup) < 0) + goto on_err; + + Py_RETURN_NONE; + + on_err: + _uinput_close(fd); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + +// Fallback setup function (Linux <= 4.5 and FreeBSD). +#else +static PyObject * +uinput_setup(PyObject *self, PyObject *args) { + int fd, len, i, abscode; + uint16_t vendor, product, version, bustype; + uint32_t max_effects; + + PyObject *absinfo = NULL, *item = NULL; + + struct uinput_user_dev uidev; + const char* name; + + int ret = PyArg_ParseTuple(args, "isHHHHOI", &fd, &name, &vendor, + &product, &version, &bustype, &absinfo, &max_effects); + if (!ret) return NULL; + + memset(&uidev, 0, sizeof(uidev)); + strncpy(uidev.name, name, sizeof(uidev.name) - 1); + uidev.id.vendor = vendor; + uidev.id.product = product; + uidev.id.version = version; + uidev.id.bustype = bustype; + uidev.ff_effects_max = max_effects; + + len = PyList_Size(absinfo); + for (i=0; i (ABS_X, 0, 255, 0, 0, 0, 0) + item = PyList_GetItem(absinfo, i); + abscode = (int)PyLong_AsLong(PyList_GetItem(item, 0)); + + /* min/max/fuzz/flat start from index 2 because index 1 is value */ + uidev.absmin[abscode] = PyLong_AsLong(PyList_GetItem(item, 2)); + uidev.absmax[abscode] = PyLong_AsLong(PyList_GetItem(item, 3)); + uidev.absfuzz[abscode] = PyLong_AsLong(PyList_GetItem(item, 4)); + uidev.absflat[abscode] = PyLong_AsLong(PyList_GetItem(item, 5)); + } + + if (write(fd, &uidev, sizeof(uidev)) != sizeof(uidev)) + goto on_err; + + Py_RETURN_NONE; + + on_err: + _uinput_close(fd); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} +#endif + + +static PyObject * +uinput_create(PyObject *self, PyObject *args) +{ + int fd; + + int ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + if (ioctl(fd, UI_DEV_CREATE) < 0) + goto on_err; + + Py_RETURN_NONE; + + on_err: + _uinput_close(fd); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + + +static PyObject * +uinput_close(PyObject *self, PyObject *args) +{ + int fd; + + int ret = PyArg_ParseTuple(args, "i", &fd); + if (!ret) return NULL; + + if (_uinput_close(fd) < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + Py_RETURN_NONE; +} + + +static PyObject * +uinput_write(PyObject *self, PyObject *args) +{ + int fd, type, code, value; + + int ret = PyArg_ParseTuple(args, "iiii", &fd, &type, &code, &value); + if (!ret) return NULL; + + struct input_event event; + struct timeval tval; + memset(&event, 0, sizeof(event)); + gettimeofday(&tval, 0); + event.input_event_usec = tval.tv_usec; + event.input_event_sec = tval.tv_sec; + event.type = type; + event.code = code; + event.value = value; + + if (write(fd, &event, sizeof(event)) != sizeof(event)) { + // @todo: elaborate + // PyErr_SetString(PyExc_OSError, "error writing event to uinput device"); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + Py_RETURN_NONE; +} + + +static PyObject * +uinput_enable_event(PyObject *self, PyObject *args) +{ + int fd; + uint16_t type, code; + unsigned long req; + + int ret = PyArg_ParseTuple(args, "ihh", &fd, &type, &code); + if (!ret) return NULL; + + switch (type) { + case EV_KEY: req = UI_SET_KEYBIT; break; + case EV_ABS: req = UI_SET_ABSBIT; break; + case EV_REL: req = UI_SET_RELBIT; break; + case EV_MSC: req = UI_SET_MSCBIT; break; + case EV_SW: req = UI_SET_SWBIT; break; + case EV_LED: req = UI_SET_LEDBIT; break; + case EV_FF: req = UI_SET_FFBIT; break; + case EV_SND: req = UI_SET_SNDBIT; break; + default: + errno = EINVAL; + goto on_err; + } + + if (ioctl(fd, UI_SET_EVBIT, type) < 0) + goto on_err; + + if (ioctl(fd, req, code) < 0) + goto on_err; + + Py_RETURN_NONE; + + on_err: + _uinput_close(fd); + PyErr_SetFromErrno(PyExc_OSError); + return NULL; +} + +int _uinput_begin_upload(int fd, struct uinput_ff_upload *upload) +{ + return ioctl(fd, UI_BEGIN_FF_UPLOAD, upload); +} + +int _uinput_end_upload(int fd, struct uinput_ff_upload *upload) +{ + return ioctl(fd, UI_END_FF_UPLOAD, upload); +} + +int _uinput_begin_erase(int fd, struct uinput_ff_erase *upload) +{ + return ioctl(fd, UI_BEGIN_FF_ERASE, upload); +} + +int _uinput_end_erase(int fd, struct uinput_ff_erase *upload) +{ + return ioctl(fd, UI_END_FF_ERASE, upload); +} + + +static PyMethodDef MethodTable[] = { + { "open", uinput_open, METH_VARARGS, + "Open uinput device node."}, + + { "setup", uinput_setup, METH_VARARGS, + "Set an uinput device up."}, + + { "create", uinput_create, METH_VARARGS, + "Create an uinput device."}, + + { "close", uinput_close, METH_VARARGS, + "Destroy uinput device."}, + + { "write", uinput_write, METH_VARARGS, + "Write event to uinput device."}, + + { "enable", uinput_enable_event, METH_VARARGS, + "Enable a type of event."}, + + { "set_phys", uinput_set_phys, METH_VARARGS, + "Set physical path"}, + + { "get_sysname", uinput_get_sysname, METH_VARARGS, + "Obtain the sysname of the uinput device."}, + + { "set_prop", uinput_set_prop, METH_VARARGS, + "Set device input property"}, + + { NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_uinput", + "Python bindings for parts of linux/uinput.c", + -1, /* m_size */ + MethodTable, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +static PyObject * +moduleinit(void) +{ + PyObject* m = PyModule_Create(&moduledef); + if (m == NULL) return NULL; + + PyModule_AddIntConstant(m, "maxnamelen", UINPUT_MAX_NAME_SIZE); + return m; +} + +PyMODINIT_FUNC +PyInit__uinput(void) +{ + return moduleinit(); +} diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/uinput.py b/CLI/venv/lib/python3.12/site-packages/evdev/uinput.py new file mode 100644 index 0000000..2c69c2b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/uinput.py @@ -0,0 +1,375 @@ +import ctypes +import os +import platform +import re +import stat +import time +from collections import defaultdict +from typing import Union, Tuple, Dict, Sequence, Optional + +from . import _uinput, ecodes, ff, util +from .device import InputDevice, AbsInfo +from .events import InputEvent + +try: + from evdev.eventio_async import EventIO +except ImportError: + from evdev.eventio import EventIO + + +class UInputError(Exception): + pass + + +class UInput(EventIO): + """ + A userland input device and that can inject input events into the + linux input subsystem. + """ + + __slots__ = ( + "name", + "vendor", + "product", + "version", + "bustype", + "events", + "devnode", + "fd", + "device", + ) + + @classmethod + def from_device( + cls, + *devices: Union[InputDevice, Union[str, bytes, os.PathLike]], + filtered_types: Tuple[int] = (ecodes.EV_SYN, ecodes.EV_FF), + **kwargs, + ): + """ + Create an UInput device with the capabilities of one or more input + devices. + + Arguments + --------- + devices : InputDevice|str + Varargs of InputDevice instances or paths to input devices. + + filtered_types : Tuple[event type codes] + Event types to exclude from the capabilities of the uinput device. + + **kwargs + Keyword arguments to UInput constructor (i.e. name, vendor etc.). + """ + + device_instances = [] + for dev in devices: + if not isinstance(dev, InputDevice): + dev = InputDevice(str(dev)) + device_instances.append(dev) + + all_capabilities = defaultdict(set) + + if "max_effects" not in kwargs: + kwargs["max_effects"] = min([dev.ff_effects_count for dev in device_instances]) + + # Merge the capabilities of all devices into one dictionary. + for dev in device_instances: + for ev_type, ev_codes in dev.capabilities().items(): + all_capabilities[ev_type].update(ev_codes) + + for evtype in filtered_types: + if evtype in all_capabilities: + del all_capabilities[evtype] + + return cls(events=all_capabilities, **kwargs) + + def __init__( + self, + events: Optional[Dict[int, Sequence[int]]] = None, + name: str = "py-evdev-uinput", + vendor: int = 0x1, + product: int = 0x1, + version: int = 0x1, + bustype: int = 0x3, + devnode: str = "/dev/uinput", + phys: str = "py-evdev-uinput", + input_props=None, + # CentOS 7 has sufficiently old headers that FF_MAX_EFFECTS is not defined there, + # which causes the whole module to fail loading. Fallback on a hardcoded value of + # FF_MAX_EFFECTS if it is not defined in the ecodes. + max_effects=ecodes.ecodes.get("FF_MAX_EFFECTS", 96), + ): + """ + Arguments + --------- + events : dict + Dictionary of event types mapping to lists of event codes. The + event types and codes that the uinput device will be able to + inject - defaults to all key codes. + + name + The name of the input device. + + vendor + Vendor identifier. + + product + Product identifier. + + version + Version identifier. + + bustype + Bustype identifier. + + phys + Physical path. + + input_props + Input properties and quirks. + + max_effects + Maximum simultaneous force-feedback effects. + + Note + ---- + If you do not specify any events, the uinput device will be able + to inject only ``KEY_*`` and ``BTN_*`` event codes. + """ + + self.name: str = name #: Uinput device name. + self.vendor: int = vendor #: Device vendor identifier. + self.product: int = product #: Device product identifier. + self.version: int = version #: Device version identifier. + self.bustype: int = bustype #: Device bustype - e.g. ``BUS_USB``. + self.phys: str = phys #: Uinput device physical path. + self.devnode: str = devnode #: Uinput device node - e.g. ``/dev/uinput/``. + + if not events: + events = {ecodes.EV_KEY: ecodes.keys.keys()} + + self._verify() + + #: Write-only, non-blocking file descriptor to the uinput device node. + self.fd = _uinput.open(devnode) + + # Prepare the list of events for passing to _uinput.enable and _uinput.setup. + absinfo, prepared_events = self._prepare_events(events) + + # Set phys name + _uinput.set_phys(self.fd, phys) + + # Set properties + input_props = input_props or [] + for prop in input_props: + _uinput.set_prop(self.fd, prop) + + for etype, code in prepared_events: + _uinput.enable(self.fd, etype, code) + + _uinput.setup(self.fd, name, vendor, product, version, bustype, absinfo, max_effects) + + # Create the uinput device. + _uinput.create(self.fd) + + self.dll = ctypes.CDLL(_uinput.__file__) + self.dll._uinput_begin_upload.restype = ctypes.c_int + self.dll._uinput_end_upload.restype = ctypes.c_int + + #: An :class:`InputDevice ` instance + #: for the fake input device. ``None`` if the device cannot be + #: opened for reading and writing. + self.device: InputDevice = self._find_device(self.fd) + + def _prepare_events(self, events): + """Prepare events for passing to _uinput.enable and _uinput.setup""" + absinfo, prepared_events = [], [] + for etype, codes in events.items(): + for code in codes: + # Handle max, min, fuzz, flat. + if isinstance(code, (tuple, list, AbsInfo)): + # Flatten (ABS_Y, (0, 255, 0, 0, 0, 0)) to (ABS_Y, 0, 255, 0, 0, 0, 0). + f = [code[0]] + f.extend(code[1]) + # Ensure the tuple is always 6 ints long, since uinput.c:uinput_create + # does little in the way of checking the length. + f.extend([0] * (6 - len(code[1]))) + absinfo.append(f) + code = code[0] + prepared_events.append((etype, code)) + return absinfo, prepared_events + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + if hasattr(self, "fd"): + self.close() + + def __repr__(self): + # TODO: + v = (repr(getattr(self, i)) for i in ("name", "bustype", "vendor", "product", "version", "phys")) + return "{}({})".format(self.__class__.__name__, ", ".join(v)) + + def __str__(self): + msg = 'name "{}", bus "{}", vendor "{:04x}", product "{:04x}", version "{:04x}", phys "{}"\nevent types: {}' + + evtypes = [i[0] for i in self.capabilities(True).keys()] + msg = msg.format( + self.name, ecodes.BUS[self.bustype], self.vendor, self.product, self.version, self.phys, " ".join(evtypes) + ) + + return msg + + def close(self): + # Close the associated InputDevice, if it was previously opened. + if self.device is not None: + self.device.close() + + # Destroy the uinput device. + if self.fd > -1: + _uinput.close(self.fd) + self.fd = -1 + + def capabilities(self, verbose: bool = False, absinfo: bool = True): + """See :func:`capabilities `.""" + if self.device is None: + raise UInputError("input device not opened - cannot read capabilities") + + return self.device.capabilities(verbose, absinfo) + + def begin_upload(self, effect_id): + upload = ff.UInputUpload() + upload.effect_id = effect_id + + ret = self.dll._uinput_begin_upload(self.fd, ctypes.byref(upload)) + if ret: + raise UInputError("Failed to begin uinput upload: " + os.strerror(ret)) + + return upload + + def end_upload(self, upload): + ret = self.dll._uinput_end_upload(self.fd, ctypes.byref(upload)) + if ret: + raise UInputError("Failed to end uinput upload: " + os.strerror(ret)) + + def begin_erase(self, effect_id): + erase = ff.UInputErase() + erase.effect_id = effect_id + + ret = self.dll._uinput_begin_erase(self.fd, ctypes.byref(erase)) + if ret: + raise UInputError("Failed to begin uinput erase: " + os.strerror(ret)) + return erase + + def end_erase(self, erase): + ret = self.dll._uinput_end_erase(self.fd, ctypes.byref(erase)) + if ret: + raise UInputError("Failed to end uinput erase: " + os.strerror(ret)) + + def _verify(self): + """ + Verify that an uinput device exists and is readable and writable + by the current process. + """ + try: + m = os.stat(self.devnode)[stat.ST_MODE] + assert stat.S_ISCHR(m) + except (IndexError, OSError, AssertionError): + msg = '"{}" does not exist or is not a character device file - verify that the uinput module is loaded' + raise UInputError(msg.format(self.devnode)) + + if not os.access(self.devnode, os.W_OK): + msg = '"{}" cannot be opened for writing' + raise UInputError(msg.format(self.devnode)) + + if len(self.name) > _uinput.maxnamelen: + msg = "uinput device name must not be longer than {} characters" + raise UInputError(msg.format(_uinput.maxnamelen)) + + def _find_device(self, fd: int) -> InputDevice: + """ + Tries to find the device node. Will delegate this task to one of + several platform-specific functions. + """ + if platform.system() == "Linux": + try: + sysname = _uinput.get_sysname(fd) + return self._find_device_linux(sysname) + except OSError: + # UI_GET_SYSNAME returned an error code. We're likely dealing with + # an old kernel. Guess the device based on the filesystem. + pass + + # If we're not running or Linux or the above method fails for any reason, + # use the generic fallback method. + return self._find_device_fallback() + + def _find_device_linux(self, sysname: str) -> InputDevice: + """ + Tries to find the device node when running on Linux. + """ + + syspath = f"/sys/devices/virtual/input/{sysname}" + + # The sysfs entry for event devices should contain exactly one folder + # whose name matches the format "event[0-9]+". It is then assumed that + # the device node in /dev/input uses the same name. + regex = re.compile("event[0-9]+") + for entry in os.listdir(syspath): + if regex.fullmatch(entry): + device_path = f"/dev/input/{entry}" + break + else: # no break + raise FileNotFoundError() + + # It is possible that there is some delay before /dev/input/event* shows + # up on old systems that do not use devtmpfs, so if the device cannot be + # found, wait for a short amount and then try again once. + # + # Furthermore, even if devtmpfs is in use, it is possible that the device + # does show up immediately, but without the correct permissions that + # still need to be set by udev. Wait for up to two seconds for either the + # device to show up or the permissions to be set. + for attempt in range(19): + try: + return InputDevice(device_path) + except (FileNotFoundError, PermissionError): + time.sleep(0.1) + + # Last attempt. If this fails, whatever exception the last attempt raises + # shall be the exception that this function raises. + return InputDevice(device_path) + + def _find_device_fallback(self) -> Union[InputDevice, None]: + """ + Tries to find the device node when UI_GET_SYSNAME is not available or + we're running on a system sufficiently exotic that we do not know how + to interpret its return value. + """ + #:bug: the device node might not be immediately available + time.sleep(0.1) + + # There could also be another device with the same name already present, + # make sure to select the newest one. + # Strictly speaking, we cannot be certain that everything returned by list_devices() + # ends at event[0-9]+: it might return something like "/dev/input/events_all". Find + # the devices that have the expected structure and extract their device number. + path_number_pairs = [] + regex = re.compile("/dev/input/event([0-9]+)") + for path in util.list_devices("/dev/input/"): + regex_match = regex.fullmatch(path) + if not regex_match: + continue + device_number = int(regex_match[1]) + path_number_pairs.append((path, device_number)) + + # The modification date of the devnode is not reliable unfortunately, so we + # are sorting by the number in the name + path_number_pairs.sort(key=lambda pair: pair[1], reverse=True) + + for path, _ in path_number_pairs: + d = InputDevice(path) + if d.name == self.name: + return d diff --git a/CLI/venv/lib/python3.12/site-packages/evdev/util.py b/CLI/venv/lib/python3.12/site-packages/evdev/util.py new file mode 100644 index 0000000..db89a22 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/evdev/util.py @@ -0,0 +1,146 @@ +import collections +import glob +import os +import re +import stat +from typing import Union, List + +from . import ecodes +from .events import InputEvent, event_factory, KeyEvent, RelEvent, AbsEvent, SynEvent + + +def list_devices(input_device_dir: Union[str, bytes, os.PathLike] = "/dev/input") -> List[str]: + """List readable character devices in ``input_device_dir``.""" + + fns = glob.glob("{}/event*".format(input_device_dir)) + return list(filter(is_device, fns)) + + +def is_device(fn: Union[str, bytes, os.PathLike]) -> bool: + """Check if ``fn`` is a readable and writable character device.""" + + if not os.path.exists(fn): + return False + + m = os.stat(fn)[stat.ST_MODE] + if not stat.S_ISCHR(m): + return False + + if not os.access(fn, os.R_OK | os.W_OK): + return False + + return True + + +def categorize(event: InputEvent) -> Union[InputEvent, KeyEvent, RelEvent, AbsEvent, SynEvent]: + """ + Categorize an event according to its type. + + The :data:`event_factory ` dictionary + maps event types to sub-classes of :class:`InputEvent + `. If the event cannot be categorized, it + is returned unmodified.""" + + if event.type in event_factory: + return event_factory[event.type](event) + else: + return event + + +def resolve_ecodes_dict(typecodemap, unknown="?"): + """ + Resolve event codes and types to their verbose names. + + :param typecodemap: mapping of event types to lists of event codes. + :param unknown: symbol to which unknown types or codes will be resolved. + + Example + ------- + >>> resolve_ecodes_dict({ 1: [272, 273, 274] }) + { ('EV_KEY', 1): [('BTN_MOUSE', 272), + ('BTN_RIGHT', 273), + ('BTN_MIDDLE', 274)] } + + If ``typecodemap`` contains absolute axis info (instances of + :class:`AbsInfo ` ) the result would look + like: + + >>> resolve_ecodes_dict({ 3: [(0, AbsInfo(...))] }) + { ('EV_ABS', 3L): [(('ABS_X', 0L), AbsInfo(...))] } + """ + + for etype, codes in typecodemap.items(): + type_name = ecodes.EV[etype] + + # ecodes.keys are a combination of KEY_ and BTN_ codes + if etype == ecodes.EV_KEY: + ecode_dict = ecodes.keys + else: + ecode_dict = getattr(ecodes, type_name.split("_")[-1]) + + resolved = resolve_ecodes(ecode_dict, codes, unknown) + yield (type_name, etype), resolved + + +def resolve_ecodes(ecode_dict, ecode_list, unknown="?"): + """ + Resolve event codes and types to their verbose names. + + Example + ------- + >>> resolve_ecodes(ecodes.BTN, [272, 273, 274]) + [(['BTN_LEFT', 'BTN_MOUSE'], 272), ('BTN_RIGHT', 273), ('BTN_MIDDLE', 274)] + """ + res = [] + for ecode in ecode_list: + # elements with AbsInfo(), eg { 3 : [(0, AbsInfo(...)), (1, AbsInfo(...))] } + if isinstance(ecode, tuple): + if ecode[0] in ecode_dict: + l = ((ecode_dict[ecode[0]], ecode[0]), ecode[1]) + else: + l = ((unknown, ecode[0]), ecode[1]) + + # just ecodes, e.g: { 0 : [0, 1, 3], 1 : [30, 48] } + else: + if ecode in ecode_dict: + l = (ecode_dict[ecode], ecode) + else: + l = (unknown, ecode) + res.append(l) + + return res + + +def find_ecodes_by_regex(regex): + """ + Find ecodes matching a regex and return a mapping of event type to event codes. + + regex can be a pattern string or a compiled regular expression object. + + Example + ------- + >>> find_ecodes_by_regex(r'(ABS|KEY)_BR(AKE|EAK)') + {1: [411], 3: [10]} + >>> res = find_ecodes_by_regex(r'(ABS|KEY)_BR(AKE|EAK)') + >>> resolve_ecodes_dict(res) + { + ('EV_KEY', 1): [('KEY_BREAK', 411)], + ('EV_ABS', 3): [('ABS_BRAKE', 10)] + } + """ + + regex = re.compile(regex) # re.compile is idempotent + result = collections.defaultdict(list) + + for type_code, codes in ecodes.bytype.items(): + for code, names in codes.items(): + names = (names,) if isinstance(names, str) else names + for name in names: + if regex.match(name): + result[type_code].append(code) + break + + return dict(result) + + +__all__ = ("list_devices", "is_device", "categorize", "resolve_ecodes", "resolve_ecodes_dict", "find_ecodes_by_regex") diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/INSTALLER b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/LICENSE.txt b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/LICENSE.txt new file mode 100644 index 0000000..4f3cb7b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Lucas Boppre Niehues + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/METADATA b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/METADATA new file mode 100644 index 0000000..0bafc4c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/METADATA @@ -0,0 +1,101 @@ +Metadata-Version: 2.1 +Name: keyboard +Version: 0.13.5 +Summary: Hook and simulate keyboard events on Windows and Linux +Home-page: https://github.com/boppreh/keyboard +Author: BoppreH +Author-email: boppreh@gmail.com +License: MIT +Keywords: keyboard hook simulate hotkey +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: Unix +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Utilities +Description-Content-Type: text/markdown +Requires-Dist: pyobjc ; sys_platform == "darwin" + + +keyboard +======== + +Take full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more. + +## Features + +- **Global event hook** on all keyboards (captures keys regardless of focus). +- **Listen** and **send** keyboard events. +- Works with **Windows** and **Linux** (requires sudo), with experimental **OS X** support (thanks @glitchassassin!). +- **Pure Python**, no C modules to be compiled. +- **Zero dependencies**. Trivial to install and deploy, just copy the files. +- **Python 2 and 3**. +- Complex hotkey support (e.g. `ctrl+shift+m, ctrl+space`) with controllable timeout. +- Includes **high level API** (e.g. [record](#keyboard.record) and [play](#keyboard.play), [add_abbreviation](#keyboard.add_abbreviation)). +- Maps keys as they actually are in your layout, with **full internationalization support** (e.g. `Ctrl+ç`). +- Events automatically captured in separate thread, doesn't block main program. +- Tested and documented. +- Doesn't break accented dead keys (I'm looking at you, pyHook). +- Mouse support available via project [mouse](https://github.com/boppreh/mouse) (`pip install mouse`). + +## Usage + +Install the [PyPI package](https://pypi.python.org/pypi/keyboard/): + + pip install keyboard + +or clone the repository (no installation required, source files are sufficient): + + git clone https://github.com/boppreh/keyboard + +or [download and extract the zip](https://github.com/boppreh/keyboard/archive/master.zip) into your project folder. + +Then check the [API docs below](https://github.com/boppreh/keyboard#api) to see what features are available. + + +## Example + + +```py +import keyboard + +keyboard.press_and_release('shift+s, space') + +keyboard.write('The quick brown fox jumps over the lazy dog.') + +keyboard.add_hotkey('ctrl+shift+a', print, args=('triggered', 'hotkey')) + +# Press PAGE UP then PAGE DOWN to type "foobar". +keyboard.add_hotkey('page up, page down', lambda: keyboard.write('foobar')) + +# Blocks until you press esc. +keyboard.wait('esc') + +# Record events until 'esc' is pressed. +recorded = keyboard.record(until='esc') +# Then replay back at three times the speed. +keyboard.play(recorded, speed_factor=3) + +# Type @@ then press space to replace with abbreviation. +keyboard.add_abbreviation('@@', 'my.long.email@example.com') + +# Block forever, like `while True`. +keyboard.wait() +``` + +## Known limitations: + +- Events generated under Windows don't report device id (`event.device == None`). [#21](https://github.com/boppreh/keyboard/issues/21) +- Media keys on Linux may appear nameless (scan-code only) or not at all. [#20](https://github.com/boppreh/keyboard/issues/20) +- Key suppression/blocking only available on Windows. [#22](https://github.com/boppreh/keyboard/issues/22) +- To avoid depending on X, the Linux parts reads raw device files (`/dev/input/input*`) +but this requires root. +- Other applications, such as some games, may register hooks that swallow all +key events. In this case `keyboard` will be unable to report events. +- This program makes no attempt to hide itself, so don't use it for keyloggers or online gaming bots. Be responsible. + + diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/RECORD b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/RECORD new file mode 100644 index 0000000..b14a077 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/RECORD @@ -0,0 +1,39 @@ +keyboard-0.13.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +keyboard-0.13.5.dist-info/LICENSE.txt,sha256=K_FKUlVV0FqAHC0sKJAVBPt2q-58LX6_tM_HUI198Pc,1077 +keyboard-0.13.5.dist-info/METADATA,sha256=qdTVFmZpvjgDt65k7TGam77g3iiw3o1pgBrwWDRL-6w,3955 +keyboard-0.13.5.dist-info/RECORD,, +keyboard-0.13.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +keyboard-0.13.5.dist-info/WHEEL,sha256=v8slff5hmCpvciQ3G55d2d1CnOBupjDFJHDE2dUb1Ao,97 +keyboard-0.13.5.dist-info/top_level.txt,sha256=c5wzGrDqCQG1WTTAnxmIHqUWNvjPR9E1TLvrIfpzE-E,9 +keyboard/__init__.py,sha256=ZNeZFyglHAH2S8R5fQEKSYetMzgAr0-F-F9KUBH9r4E,43578 +keyboard/__main__.py,sha256=hT5QQiFEKZ7U9009Ox0JMONeON4vzhHwS7X-J5KU38M,378 +keyboard/__pycache__/__init__.cpython-312.pyc,, +keyboard/__pycache__/__main__.cpython-312.pyc,, +keyboard/__pycache__/_canonical_names.cpython-312.pyc,, +keyboard/__pycache__/_darwinkeyboard.cpython-312.pyc,, +keyboard/__pycache__/_darwinmouse.cpython-312.pyc,, +keyboard/__pycache__/_generic.cpython-312.pyc,, +keyboard/__pycache__/_keyboard_event.cpython-312.pyc,, +keyboard/__pycache__/_keyboard_tests.cpython-312.pyc,, +keyboard/__pycache__/_mouse_event.cpython-312.pyc,, +keyboard/__pycache__/_mouse_tests.cpython-312.pyc,, +keyboard/__pycache__/_nixcommon.cpython-312.pyc,, +keyboard/__pycache__/_nixkeyboard.cpython-312.pyc,, +keyboard/__pycache__/_nixmouse.cpython-312.pyc,, +keyboard/__pycache__/_winkeyboard.cpython-312.pyc,, +keyboard/__pycache__/_winmouse.cpython-312.pyc,, +keyboard/__pycache__/mouse.cpython-312.pyc,, +keyboard/_canonical_names.py,sha256=_V7K9lmF5z0eMbdMHr85KWoE_SC79zoeYfYB3n914pE,29474 +keyboard/_darwinkeyboard.py,sha256=nmDPlMPM2iE5ioZJpZf40GJgdFWta_xKnbwIv3efzAM,18124 +keyboard/_darwinmouse.py,sha256=YoD2RmGEnCoptlKn9Tbzg3k9pBVsosetxxQ5Fo3fb8E,6515 +keyboard/_generic.py,sha256=DMB0E7Sc4XvnGL_7B9mDbKioGgMSIUiwCkuGV1vDTrY,2176 +keyboard/_keyboard_event.py,sha256=Spsn28-Tbv50fGB8YBVVvzdaYP3Qd8DDJ_OHrMltskM,1630 +keyboard/_keyboard_tests.py,sha256=TKsNk_ZEGGe7RBb48SZp9QG6l9a0M_FeQ_vyrTQ4x9c,36830 +keyboard/_mouse_event.py,sha256=zRQGO6M6nbA-jvhI0yz4HzvQNcScF48PZ9iRegcTVjQ,422 +keyboard/_mouse_tests.py,sha256=jeXMAm8NCnM1xfoMacfj0Rqves8Zs7mehZHT8c0weaw,10014 +keyboard/_nixcommon.py,sha256=WLzMzpb7SB03Wpohzoh4BbLBZZMre_NHKfRrRdjhb_k,6053 +keyboard/_nixkeyboard.py,sha256=jBnwq-yVNb9j67P9OpeR7WBt1J6499VW_Uia3FDFRQo,5882 +keyboard/_nixmouse.py,sha256=rgcxW1Y0xljbk_Ljtqc08PLe9F9_jCki-oQUz-LvHcI,3518 +keyboard/_winkeyboard.py,sha256=13TcS23FQ9cLH6IUIuPG2tc8436DqjGfQo01_spDEaQ,20607 +keyboard/_winmouse.py,sha256=_8t4jDlnVRqeKr0HvtTbvnD8xwElmpGFtqOlZbIAbwM,5817 +keyboard/mouse.py,sha256=Eq50w6QnyYAGiJ_Y7ERmU-jQlYO7NT0aSFMkR-Fnwnc,7639 diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/REQUESTED b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/WHEEL b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/WHEEL new file mode 100644 index 0000000..d4fe38c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.33.6) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/top_level.txt b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/top_level.txt new file mode 100644 index 0000000..c253983 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard-0.13.5.dist-info/top_level.txt @@ -0,0 +1 @@ +keyboard diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__init__.py b/CLI/venv/lib/python3.12/site-packages/keyboard/__init__.py new file mode 100644 index 0000000..4a87715 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/__init__.py @@ -0,0 +1,1157 @@ +# -*- coding: utf-8 -*- +""" +keyboard +======== + +Take full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more. + +## Features + +- **Global event hook** on all keyboards (captures keys regardless of focus). +- **Listen** and **send** keyboard events. +- Works with **Windows** and **Linux** (requires sudo), with experimental **OS X** support (thanks @glitchassassin!). +- **Pure Python**, no C modules to be compiled. +- **Zero dependencies**. Trivial to install and deploy, just copy the files. +- **Python 2 and 3**. +- Complex hotkey support (e.g. `ctrl+shift+m, ctrl+space`) with controllable timeout. +- Includes **high level API** (e.g. [record](#keyboard.record) and [play](#keyboard.play), [add_abbreviation](#keyboard.add_abbreviation)). +- Maps keys as they actually are in your layout, with **full internationalization support** (e.g. `Ctrl+ç`). +- Events automatically captured in separate thread, doesn't block main program. +- Tested and documented. +- Doesn't break accented dead keys (I'm looking at you, pyHook). +- Mouse support available via project [mouse](https://github.com/boppreh/mouse) (`pip install mouse`). + +## Usage + +Install the [PyPI package](https://pypi.python.org/pypi/keyboard/): + + pip install keyboard + +or clone the repository (no installation required, source files are sufficient): + + git clone https://github.com/boppreh/keyboard + +or [download and extract the zip](https://github.com/boppreh/keyboard/archive/master.zip) into your project folder. + +Then check the [API docs below](https://github.com/boppreh/keyboard#api) to see what features are available. + + +## Example + + +```py +import keyboard + +keyboard.press_and_release('shift+s, space') + +keyboard.write('The quick brown fox jumps over the lazy dog.') + +keyboard.add_hotkey('ctrl+shift+a', print, args=('triggered', 'hotkey')) + +# Press PAGE UP then PAGE DOWN to type "foobar". +keyboard.add_hotkey('page up, page down', lambda: keyboard.write('foobar')) + +# Blocks until you press esc. +keyboard.wait('esc') + +# Record events until 'esc' is pressed. +recorded = keyboard.record(until='esc') +# Then replay back at three times the speed. +keyboard.play(recorded, speed_factor=3) + +# Type @@ then press space to replace with abbreviation. +keyboard.add_abbreviation('@@', 'my.long.email@example.com') + +# Block forever, like `while True`. +keyboard.wait() +``` + +## Known limitations: + +- Events generated under Windows don't report device id (`event.device == None`). [#21](https://github.com/boppreh/keyboard/issues/21) +- Media keys on Linux may appear nameless (scan-code only) or not at all. [#20](https://github.com/boppreh/keyboard/issues/20) +- Key suppression/blocking only available on Windows. [#22](https://github.com/boppreh/keyboard/issues/22) +- To avoid depending on X, the Linux parts reads raw device files (`/dev/input/input*`) +but this requires root. +- Other applications, such as some games, may register hooks that swallow all +key events. In this case `keyboard` will be unable to report events. +- This program makes no attempt to hide itself, so don't use it for keyloggers or online gaming bots. Be responsible. +""" +from __future__ import print_function as _print_function + +version = '0.13.5' + +import re as _re +import itertools as _itertools +import collections as _collections +from threading import Thread as _Thread, Lock as _Lock +import time as _time +# Python2... Buggy on time changes and leap seconds, but no other good option (https://stackoverflow.com/questions/1205722/how-do-i-get-monotonic-time-durations-in-python). +_time.monotonic = getattr(_time, 'monotonic', None) or _time.time + +try: + # Python2 + long, basestring + _is_str = lambda x: isinstance(x, basestring) + _is_number = lambda x: isinstance(x, (int, long)) + import Queue as _queue + # threading.Event is a function in Python2 wrappin _Event (?!). + from threading import _Event as _UninterruptibleEvent +except NameError: + # Python3 + _is_str = lambda x: isinstance(x, str) + _is_number = lambda x: isinstance(x, int) + import queue as _queue + from threading import Event as _UninterruptibleEvent +_is_list = lambda x: isinstance(x, (list, tuple)) + +# Just a dynamic object to store attributes for the closures. +class _State(object): pass + +# The "Event" class from `threading` ignores signals when waiting and is +# impossible to interrupt with Ctrl+C. So we rewrite `wait` to wait in small, +# interruptible intervals. +class _Event(_UninterruptibleEvent): + def wait(self): + while True: + if _UninterruptibleEvent.wait(self, 0.5): + break + +import platform as _platform +if _platform.system() == 'Windows': + from. import _winkeyboard as _os_keyboard +elif _platform.system() == 'Linux': + from. import _nixkeyboard as _os_keyboard +elif _platform.system() == 'Darwin': + from. import _darwinkeyboard as _os_keyboard +else: + raise OSError("Unsupported platform '{}'".format(_platform.system())) + +from ._keyboard_event import KEY_DOWN, KEY_UP, KeyboardEvent +from ._generic import GenericListener as _GenericListener +from ._canonical_names import all_modifiers, sided_modifiers, normalize_name + +_modifier_scan_codes = set() +def is_modifier(key): + """ + Returns True if `key` is a scan code or name of a modifier key. + """ + if _is_str(key): + return key in all_modifiers + else: + if not _modifier_scan_codes: + scan_codes = (key_to_scan_codes(name, False) for name in all_modifiers) + _modifier_scan_codes.update(*scan_codes) + return key in _modifier_scan_codes + +_pressed_events_lock = _Lock() +_pressed_events = {} +_physically_pressed_keys = _pressed_events +_logically_pressed_keys = {} +class _KeyboardListener(_GenericListener): + transition_table = { + #Current state of the modifier, per `modifier_states`. + #| + #| Type of event that triggered this modifier update. + #| | + #| | Type of key that triggered this modiier update. + #| | | + #| | | Should we send a fake key press? + #| | | | + #| | | => | Accept the event? + #| | | | | + #| | | | | Next state. + #v v v v v v + ('free', KEY_UP, 'modifier'): (False, True, 'free'), + ('free', KEY_DOWN, 'modifier'): (False, False, 'pending'), + ('pending', KEY_UP, 'modifier'): (True, True, 'free'), + ('pending', KEY_DOWN, 'modifier'): (False, True, 'allowed'), + ('suppressed', KEY_UP, 'modifier'): (False, False, 'free'), + ('suppressed', KEY_DOWN, 'modifier'): (False, False, 'suppressed'), + ('allowed', KEY_UP, 'modifier'): (False, True, 'free'), + ('allowed', KEY_DOWN, 'modifier'): (False, True, 'allowed'), + + ('free', KEY_UP, 'hotkey'): (False, None, 'free'), + ('free', KEY_DOWN, 'hotkey'): (False, None, 'free'), + ('pending', KEY_UP, 'hotkey'): (False, None, 'suppressed'), + ('pending', KEY_DOWN, 'hotkey'): (False, None, 'suppressed'), + ('suppressed', KEY_UP, 'hotkey'): (False, None, 'suppressed'), + ('suppressed', KEY_DOWN, 'hotkey'): (False, None, 'suppressed'), + ('allowed', KEY_UP, 'hotkey'): (False, None, 'allowed'), + ('allowed', KEY_DOWN, 'hotkey'): (False, None, 'allowed'), + + ('free', KEY_UP, 'other'): (False, True, 'free'), + ('free', KEY_DOWN, 'other'): (False, True, 'free'), + ('pending', KEY_UP, 'other'): (True, True, 'allowed'), + ('pending', KEY_DOWN, 'other'): (True, True, 'allowed'), + # Necessary when hotkeys are removed after beign triggered, such as + # TestKeyboard.test_add_hotkey_multistep_suppress_modifier. + ('suppressed', KEY_UP, 'other'): (False, False, 'allowed'), + ('suppressed', KEY_DOWN, 'other'): (True, True, 'allowed'), + ('allowed', KEY_UP, 'other'): (False, True, 'allowed'), + ('allowed', KEY_DOWN, 'other'): (False, True, 'allowed'), + } + + def init(self): + _os_keyboard.init() + + self.active_modifiers = set() + self.blocking_hooks = [] + self.blocking_keys = _collections.defaultdict(list) + self.nonblocking_keys = _collections.defaultdict(list) + self.blocking_hotkeys = _collections.defaultdict(list) + self.nonblocking_hotkeys = _collections.defaultdict(list) + self.filtered_modifiers = _collections.Counter() + self.is_replaying = False + + # Supporting hotkey suppression is harder than it looks. See + # https://github.com/boppreh/keyboard/issues/22 + self.modifier_states = {} # "alt" -> "allowed" + + def pre_process_event(self, event): + for key_hook in self.nonblocking_keys[event.scan_code]: + key_hook(event) + + with _pressed_events_lock: + hotkey = tuple(sorted(_pressed_events)) + for callback in self.nonblocking_hotkeys[hotkey]: + callback(event) + + return event.scan_code or (event.name and event.name != 'unknown') + + def direct_callback(self, event): + """ + This function is called for every OS keyboard event and decides if the + event should be blocked or not, and passes a copy of the event to + other, non-blocking, listeners. + + There are two ways to block events: remapped keys, which translate + events by suppressing and re-emitting; and blocked hotkeys, which + suppress specific hotkeys. + """ + # Pass through all fake key events, don't even report to other handlers. + if self.is_replaying: + return True + + if not all(hook(event) for hook in self.blocking_hooks): + return False + + event_type = event.event_type + scan_code = event.scan_code + + # Update tables of currently pressed keys and modifiers. + with _pressed_events_lock: + if event_type == KEY_DOWN: + if is_modifier(scan_code): self.active_modifiers.add(scan_code) + _pressed_events[scan_code] = event + hotkey = tuple(sorted(_pressed_events)) + if event_type == KEY_UP: + self.active_modifiers.discard(scan_code) + if scan_code in _pressed_events: del _pressed_events[scan_code] + + # Mappings based on individual keys instead of hotkeys. + for key_hook in self.blocking_keys[scan_code]: + if not key_hook(event): + return False + + # Default accept. + accept = True + + if self.blocking_hotkeys: + if self.filtered_modifiers[scan_code]: + origin = 'modifier' + modifiers_to_update = set([scan_code]) + else: + modifiers_to_update = self.active_modifiers + if is_modifier(scan_code): + modifiers_to_update = modifiers_to_update | {scan_code} + callback_results = [callback(event) for callback in self.blocking_hotkeys[hotkey]] + if callback_results: + accept = all(callback_results) + origin = 'hotkey' + else: + origin = 'other' + + for key in sorted(modifiers_to_update): + transition_tuple = (self.modifier_states.get(key, 'free'), event_type, origin) + should_press, new_accept, new_state = self.transition_table[transition_tuple] + if should_press: press(key) + if new_accept is not None: accept = new_accept + self.modifier_states[key] = new_state + + if accept: + if event_type == KEY_DOWN: + _logically_pressed_keys[scan_code] = event + elif event_type == KEY_UP and scan_code in _logically_pressed_keys: + del _logically_pressed_keys[scan_code] + + # Queue for handlers that won't block the event. + self.queue.put(event) + + return accept + + def listen(self): + _os_keyboard.listen(self.direct_callback) + +_listener = _KeyboardListener() + +def key_to_scan_codes(key, error_if_missing=True): + """ + Returns a list of scan codes associated with this key (name or scan code). + """ + if _is_number(key): + return (key,) + elif _is_list(key): + return sum((key_to_scan_codes(i) for i in key), ()) + elif not _is_str(key): + raise ValueError('Unexpected key type ' + str(type(key)) + ', value (' + repr(key) + ')') + + normalized = normalize_name(key) + if normalized in sided_modifiers: + left_scan_codes = key_to_scan_codes('left ' + normalized, False) + right_scan_codes = key_to_scan_codes('right ' + normalized, False) + return left_scan_codes + tuple(c for c in right_scan_codes if c not in left_scan_codes) + + try: + # Put items in ordered dict to remove duplicates. + t = tuple(_collections.OrderedDict((scan_code, True) for scan_code, modifier in _os_keyboard.map_name(normalized))) + e = None + except (KeyError, ValueError) as exception: + t = () + e = exception + + if not t and error_if_missing: + raise ValueError('Key {} is not mapped to any known key.'.format(repr(key)), e) + else: + return t + +def parse_hotkey(hotkey): + """ + Parses a user-provided hotkey into nested tuples representing the + parsed structure, with the bottom values being lists of scan codes. + Also accepts raw scan codes, which are then wrapped in the required + number of nestings. + + Example: + + parse_hotkey("alt+shift+a, alt+b, c") + # Keys: ^~^ ^~~~^ ^ ^~^ ^ ^ + # Steps: ^~~~~~~~~~^ ^~~~^ ^ + + # ((alt_codes, shift_codes, a_codes), (alt_codes, b_codes), (c_codes,)) + """ + if _is_number(hotkey) or len(hotkey) == 1: + scan_codes = key_to_scan_codes(hotkey) + step = (scan_codes,) + steps = (step,) + return steps + elif _is_list(hotkey): + if not any(map(_is_list, hotkey)): + step = tuple(key_to_scan_codes(k) for k in hotkey) + steps = (step,) + return steps + return hotkey + + steps = [] + for step in _re.split(r',\s?', hotkey): + keys = _re.split(r'\s?\+\s?', step) + steps.append(tuple(key_to_scan_codes(key) for key in keys)) + return tuple(steps) + +def send(hotkey, do_press=True, do_release=True): + """ + Sends OS events that perform the given *hotkey* hotkey. + + - `hotkey` can be either a scan code (e.g. 57 for space), single key + (e.g. 'space') or multi-key, multi-step hotkey (e.g. 'alt+F4, enter'). + - `do_press` if true then press events are sent. Defaults to True. + - `do_release` if true then release events are sent. Defaults to True. + + send(57) + send('ctrl+alt+del') + send('alt+F4, enter') + send('shift+s') + + Note: keys are released in the opposite order they were pressed. + """ + _listener.is_replaying = True + + parsed = parse_hotkey(hotkey) + for step in parsed: + if do_press: + for scan_codes in step: + _os_keyboard.press(scan_codes[0]) + + if do_release: + for scan_codes in reversed(step): + _os_keyboard.release(scan_codes[0]) + + _listener.is_replaying = False + +# Alias. +press_and_release = send + +def press(hotkey): + """ Presses and holds down a hotkey (see `send`). """ + send(hotkey, True, False) + +def release(hotkey): + """ Releases a hotkey (see `send`). """ + send(hotkey, False, True) + +def is_pressed(hotkey): + """ + Returns True if the key is pressed. + + is_pressed(57) #-> True + is_pressed('space') #-> True + is_pressed('ctrl+space') #-> True + """ + _listener.start_if_necessary() + + if _is_number(hotkey): + # Shortcut. + with _pressed_events_lock: + return hotkey in _pressed_events + + steps = parse_hotkey(hotkey) + if len(steps) > 1: + raise ValueError("Impossible to check if multi-step hotkeys are pressed (`a+b` is ok, `a, b` isn't).") + + # Convert _pressed_events into a set + with _pressed_events_lock: + pressed_scan_codes = set(_pressed_events) + for scan_codes in steps[0]: + if not any(scan_code in pressed_scan_codes for scan_code in scan_codes): + return False + return True + +def call_later(fn, args=(), delay=0.001): + """ + Calls the provided function in a new thread after waiting some time. + Useful for giving the system some time to process an event, without blocking + the current execution flow. + """ + thread = _Thread(target=lambda: (_time.sleep(delay), fn(*args))) + thread.start() + +_hooks = {} +def hook(callback, suppress=False, on_remove=lambda: None): + """ + Installs a global listener on all available keyboards, invoking `callback` + each time a key is pressed or released. + + The event passed to the callback is of type `keyboard.KeyboardEvent`, + with the following attributes: + + - `name`: an Unicode representation of the character (e.g. "&") or + description (e.g. "space"). The name is always lower-case. + - `scan_code`: number representing the physical key, e.g. 55. + - `time`: timestamp of the time the event occurred, with as much precision + as given by the OS. + + Returns the given callback for easier development. + """ + if suppress: + _listener.start_if_necessary() + append, remove = _listener.blocking_hooks.append, _listener.blocking_hooks.remove + else: + append, remove = _listener.add_handler, _listener.remove_handler + + append(callback) + def remove_(): + del _hooks[callback] + del _hooks[remove_] + remove(callback) + on_remove() + _hooks[callback] = _hooks[remove_] = remove_ + return remove_ + +def on_press(callback, suppress=False): + """ + Invokes `callback` for every KEY_DOWN event. For details see `hook`. + """ + return hook(lambda e: e.event_type == KEY_UP or callback(e), suppress=suppress) + +def on_release(callback, suppress=False): + """ + Invokes `callback` for every KEY_UP event. For details see `hook`. + """ + return hook(lambda e: e.event_type == KEY_DOWN or callback(e), suppress=suppress) + +def hook_key(key, callback, suppress=False): + """ + Hooks key up and key down events for a single key. Returns the event handler + created. To remove a hooked key use `unhook_key(key)` or + `unhook_key(handler)`. + + Note: this function shares state with hotkeys, so `clear_all_hotkeys` + affects it as well. + """ + _listener.start_if_necessary() + store = _listener.blocking_keys if suppress else _listener.nonblocking_keys + scan_codes = key_to_scan_codes(key) + for scan_code in scan_codes: + store[scan_code].append(callback) + + def remove_(): + del _hooks[callback] + del _hooks[key] + del _hooks[remove_] + for scan_code in scan_codes: + store[scan_code].remove(callback) + _hooks[callback] = _hooks[key] = _hooks[remove_] = remove_ + return remove_ + +def on_press_key(key, callback, suppress=False): + """ + Invokes `callback` for KEY_DOWN event related to the given key. For details see `hook`. + """ + return hook_key(key, lambda e: e.event_type == KEY_UP or callback(e), suppress=suppress) + +def on_release_key(key, callback, suppress=False): + """ + Invokes `callback` for KEY_UP event related to the given key. For details see `hook`. + """ + return hook_key(key, lambda e: e.event_type == KEY_DOWN or callback(e), suppress=suppress) + +def unhook(remove): + """ + Removes a previously added hook, either by callback or by the return value + of `hook`. + """ + _hooks[remove]() +unhook_key = unhook + +def unhook_all(): + """ + Removes all keyboard hooks in use, including hotkeys, abbreviations, word + listeners, `record`ers and `wait`s. + """ + _listener.start_if_necessary() + _listener.blocking_keys.clear() + _listener.nonblocking_keys.clear() + del _listener.blocking_hooks[:] + del _listener.handlers[:] + unhook_all_hotkeys() + +def block_key(key): + """ + Suppresses all key events of the given key, regardless of modifiers. + """ + return hook_key(key, lambda e: False, suppress=True) +unblock_key = unhook_key + +def remap_key(src, dst): + """ + Whenever the key `src` is pressed or released, regardless of modifiers, + press or release the hotkey `dst` instead. + """ + def handler(event): + if event.event_type == KEY_DOWN: + press(dst) + else: + release(dst) + return False + return hook_key(src, handler, suppress=True) +unremap_key = unhook_key + +def parse_hotkey_combinations(hotkey): + """ + Parses a user-provided hotkey. Differently from `parse_hotkey`, + instead of each step being a list of the different scan codes for each key, + each step is a list of all possible combinations of those scan codes. + """ + def combine_step(step): + # A single step may be composed of many keys, and each key can have + # multiple scan codes. To speed up hotkey matching and avoid introducing + # event delays, we list all possible combinations of scan codes for these + # keys. Hotkeys are usually small, and there are not many combinations, so + # this is not as insane as it sounds. + return (tuple(sorted(scan_codes)) for scan_codes in _itertools.product(*step)) + + return tuple(tuple(combine_step(step)) for step in parse_hotkey(hotkey)) + +def _add_hotkey_step(handler, combinations, suppress): + """ + Hooks a single-step hotkey (e.g. 'shift+a'). + """ + container = _listener.blocking_hotkeys if suppress else _listener.nonblocking_hotkeys + + # Register the scan codes of every possible combination of + # modfiier + main key. Modifiers have to be registered in + # filtered_modifiers too, so suppression and replaying can work. + for scan_codes in combinations: + for scan_code in scan_codes: + if is_modifier(scan_code): + _listener.filtered_modifiers[scan_code] += 1 + container[scan_codes].append(handler) + + def remove(): + for scan_codes in combinations: + for scan_code in scan_codes: + if is_modifier(scan_code): + _listener.filtered_modifiers[scan_code] -= 1 + container[scan_codes].remove(handler) + return remove + +_hotkeys = {} +def add_hotkey(hotkey, callback, args=(), suppress=False, timeout=1, trigger_on_release=False): + """ + Invokes a callback every time a hotkey is pressed. The hotkey must + be in the format `ctrl+shift+a, s`. This would trigger when the user holds + ctrl, shift and "a" at once, releases, and then presses "s". To represent + literal commas, pluses, and spaces, use their names ('comma', 'plus', + 'space'). + + - `args` is an optional list of arguments to passed to the callback during + each invocation. + - `suppress` defines if successful triggers should block the keys from being + sent to other programs. + - `timeout` is the amount of seconds allowed to pass between key presses. + - `trigger_on_release` if true, the callback is invoked on key release instead + of key press. + + The event handler function is returned. To remove a hotkey call + `remove_hotkey(hotkey)` or `remove_hotkey(handler)`. + before the hotkey state is reset. + + Note: hotkeys are activated when the last key is *pressed*, not released. + Note: the callback is executed in a separate thread, asynchronously. For an + example of how to use a callback synchronously, see `wait`. + + Examples: + + # Different but equivalent ways to listen for a spacebar key press. + add_hotkey(' ', print, args=['space was pressed']) + add_hotkey('space', print, args=['space was pressed']) + add_hotkey('Space', print, args=['space was pressed']) + # Here 57 represents the keyboard code for spacebar; so you will be + # pressing 'spacebar', not '57' to activate the print function. + add_hotkey(57, print, args=['space was pressed']) + + add_hotkey('ctrl+q', quit) + add_hotkey('ctrl+alt+enter, space', some_callback) + """ + if args: + callback = lambda callback=callback: callback(*args) + + _listener.start_if_necessary() + + steps = parse_hotkey_combinations(hotkey) + + event_type = KEY_UP if trigger_on_release else KEY_DOWN + if len(steps) == 1: + # Deciding when to allow a KEY_UP event is far harder than I thought, + # and any mistake will make that key "sticky". Therefore just let all + # KEY_UP events go through as long as that's not what we are listening + # for. + handler = lambda e: (event_type == KEY_DOWN and e.event_type == KEY_UP and e.scan_code in _logically_pressed_keys) or (event_type == e.event_type and callback()) + remove_step = _add_hotkey_step(handler, steps[0], suppress) + def remove_(): + remove_step() + del _hotkeys[hotkey] + del _hotkeys[remove_] + del _hotkeys[callback] + # TODO: allow multiple callbacks for each hotkey without overwriting the + # remover. + _hotkeys[hotkey] = _hotkeys[remove_] = _hotkeys[callback] = remove_ + return remove_ + + state = _State() + state.remove_catch_misses = None + state.remove_last_step = None + state.suppressed_events = [] + state.last_update = float('-inf') + + def catch_misses(event, force_fail=False): + if ( + event.event_type == event_type + and state.index + and event.scan_code not in allowed_keys_by_step[state.index] + ) or ( + timeout + and _time.monotonic() - state.last_update >= timeout + ) or force_fail: # Weird formatting to ensure short-circuit. + + state.remove_last_step() + + for event in state.suppressed_events: + if event.event_type == KEY_DOWN: + press(event.scan_code) + else: + release(event.scan_code) + del state.suppressed_events[:] + + index = 0 + set_index(0) + return True + + def set_index(new_index): + state.index = new_index + + if new_index == 0: + # This is done for performance reasons, avoiding a global key hook + # that is always on. + state.remove_catch_misses = lambda: None + elif new_index == 1: + state.remove_catch_misses() + # Must be `suppress=True` to ensure `send` has priority. + state.remove_catch_misses = hook(catch_misses, suppress=True) + + if new_index == len(steps) - 1: + def handler(event): + if event.event_type == KEY_UP: + remove() + set_index(0) + accept = event.event_type == event_type and callback() + if accept: + return catch_misses(event, force_fail=True) + else: + state.suppressed_events[:] = [event] + return False + remove = _add_hotkey_step(handler, steps[state.index], suppress) + else: + # Fix value of next_index. + def handler(event, new_index=state.index+1): + if event.event_type == KEY_UP: + remove() + set_index(new_index) + state.suppressed_events.append(event) + return False + remove = _add_hotkey_step(handler, steps[state.index], suppress) + state.remove_last_step = remove + state.last_update = _time.monotonic() + return False + set_index(0) + + allowed_keys_by_step = [ + set().union(*step) + for step in steps + ] + + def remove_(): + state.remove_catch_misses() + state.remove_last_step() + del _hotkeys[hotkey] + del _hotkeys[remove_] + del _hotkeys[callback] + # TODO: allow multiple callbacks for each hotkey without overwriting the + # remover. + _hotkeys[hotkey] = _hotkeys[remove_] = _hotkeys[callback] = remove_ + return remove_ +register_hotkey = add_hotkey + +def remove_hotkey(hotkey_or_callback): + """ + Removes a previously hooked hotkey. Must be called with the value returned + by `add_hotkey`. + """ + _hotkeys[hotkey_or_callback]() +unregister_hotkey = clear_hotkey = remove_hotkey + +def unhook_all_hotkeys(): + """ + Removes all keyboard hotkeys in use, including abbreviations, word listeners, + `record`ers and `wait`s. + """ + # Because of "alises" some hooks may have more than one entry, all of which + # are removed together. + _listener.blocking_hotkeys.clear() + _listener.nonblocking_hotkeys.clear() +unregister_all_hotkeys = remove_all_hotkeys = clear_all_hotkeys = unhook_all_hotkeys + +def remap_hotkey(src, dst, suppress=True, trigger_on_release=False): + """ + Whenever the hotkey `src` is pressed, suppress it and send + `dst` instead. + + Example: + + remap('alt+w', 'ctrl+up') + """ + def handler(): + active_modifiers = sorted(modifier for modifier, state in _listener.modifier_states.items() if state == 'allowed') + for modifier in active_modifiers: + release(modifier) + send(dst) + for modifier in reversed(active_modifiers): + press(modifier) + return False + return add_hotkey(src, handler, suppress=suppress, trigger_on_release=trigger_on_release) +unremap_hotkey = remove_hotkey + +def stash_state(): + """ + Builds a list of all currently pressed scan codes, releases them and returns + the list. Pairs well with `restore_state` and `restore_modifiers`. + """ + # TODO: stash caps lock / numlock /scrollock state. + with _pressed_events_lock: + state = sorted(_pressed_events) + for scan_code in state: + _os_keyboard.release(scan_code) + return state + +def restore_state(scan_codes): + """ + Given a list of scan_codes ensures these keys, and only these keys, are + pressed. Pairs well with `stash_state`, alternative to `restore_modifiers`. + """ + _listener.is_replaying = True + + with _pressed_events_lock: + current = set(_pressed_events) + target = set(scan_codes) + for scan_code in current - target: + _os_keyboard.release(scan_code) + for scan_code in target - current: + _os_keyboard.press(scan_code) + + _listener.is_replaying = False + +def restore_modifiers(scan_codes): + """ + Like `restore_state`, but only restores modifier keys. + """ + restore_state((scan_code for scan_code in scan_codes if is_modifier(scan_code))) + +def write(text, delay=0, restore_state_after=True, exact=None): + """ + Sends artificial keyboard events to the OS, simulating the typing of a given + text. Characters not available on the keyboard are typed as explicit unicode + characters using OS-specific functionality, such as alt+codepoint. + + To ensure text integrity, all currently pressed keys are released before + the text is typed, and modifiers are restored afterwards. + + - `delay` is the number of seconds to wait between keypresses, defaults to + no delay. + - `restore_state_after` can be used to restore the state of pressed keys + after the text is typed, i.e. presses the keys that were released at the + beginning. Defaults to True. + - `exact` forces typing all characters as explicit unicode (e.g. + alt+codepoint or special events). If None, uses platform-specific suggested + value. + """ + if exact is None: + exact = _platform.system() == 'Windows' + + state = stash_state() + + # Window's typing of unicode characters is quite efficient and should be preferred. + if exact: + for letter in text: + if letter in '\n\b': + send(letter) + else: + _os_keyboard.type_unicode(letter) + if delay: _time.sleep(delay) + else: + for letter in text: + try: + entries = _os_keyboard.map_name(normalize_name(letter)) + scan_code, modifiers = next(iter(entries)) + except (KeyError, ValueError): + _os_keyboard.type_unicode(letter) + continue + + for modifier in modifiers: + press(modifier) + + _os_keyboard.press(scan_code) + _os_keyboard.release(scan_code) + + for modifier in modifiers: + release(modifier) + + if delay: + _time.sleep(delay) + + if restore_state_after: + restore_modifiers(state) + +def wait(hotkey=None, suppress=False, trigger_on_release=False): + """ + Blocks the program execution until the given hotkey is pressed or, + if given no parameters, blocks forever. + """ + if hotkey: + lock = _Event() + remove = add_hotkey(hotkey, lambda: lock.set(), suppress=suppress, trigger_on_release=trigger_on_release) + lock.wait() + remove_hotkey(remove) + else: + while True: + _time.sleep(1e6) + +def get_hotkey_name(names=None): + """ + Returns a string representation of hotkey from the given key names, or + the currently pressed keys if not given. This function: + + - normalizes names; + - removes "left" and "right" prefixes; + - replaces the "+" key name with "plus" to avoid ambiguity; + - puts modifier keys first, in a standardized order; + - sort remaining keys; + - finally, joins everything with "+". + + Example: + + get_hotkey_name(['+', 'left ctrl', 'shift']) + # "ctrl+shift+plus" + """ + if names is None: + _listener.start_if_necessary() + with _pressed_events_lock: + names = [e.name for e in _pressed_events.values()] + else: + names = [normalize_name(name) for name in names] + clean_names = set(e.replace('left ', '').replace('right ', '').replace('+', 'plus') for e in names) + # https://developer.apple.com/macos/human-interface-guidelines/input-and-output/keyboard/ + # > List modifier keys in the correct order. If you use more than one modifier key in a + # > hotkey, always list them in this order: Control, Option, Shift, Command. + modifiers = ['ctrl', 'alt', 'shift', 'windows'] + sorting_key = lambda k: (modifiers.index(k) if k in modifiers else 5, str(k)) + return '+'.join(sorted(clean_names, key=sorting_key)) + +def read_event(suppress=False): + """ + Blocks until a keyboard event happens, then returns that event. + """ + queue = _queue.Queue(maxsize=1) + hooked = hook(queue.put, suppress=suppress) + while True: + event = queue.get() + unhook(hooked) + return event + +def read_key(suppress=False): + """ + Blocks until a keyboard event happens, then returns that event's name or, + if missing, its scan code. + """ + event = read_event(suppress) + return event.name or event.scan_code + +def read_hotkey(suppress=True): + """ + Similar to `read_key()`, but blocks until the user presses and releases a + hotkey (or single key), then returns a string representing the hotkey + pressed. + + Example: + + read_hotkey() + # "ctrl+shift+p" + """ + queue = _queue.Queue() + fn = lambda e: queue.put(e) or e.event_type == KEY_DOWN + hooked = hook(fn, suppress=suppress) + while True: + event = queue.get() + if event.event_type == KEY_UP: + unhook(hooked) + with _pressed_events_lock: + names = [e.name for e in _pressed_events.values()] + [event.name] + return get_hotkey_name(names) + +def get_typed_strings(events, allow_backspace=True): + """ + Given a sequence of events, tries to deduce what strings were typed. + Strings are separated when a non-textual key is pressed (such as tab or + enter). Characters are converted to uppercase according to shift and + capslock status. If `allow_backspace` is True, backspaces remove the last + character typed. + + This function is a generator, so you can pass an infinite stream of events + and convert them to strings in real time. + + Note this functions is merely an heuristic. Windows for example keeps per- + process keyboard state such as keyboard layout, and this information is not + available for our hooks. + + get_type_strings(record()) #-> ['This is what', 'I recorded', ''] + """ + backspace_name = 'delete' if _platform.system() == 'Darwin' else 'backspace' + + shift_pressed = False + capslock_pressed = False + string = '' + for event in events: + name = event.name + + # Space is the only key that we _parse_hotkey to the spelled out name + # because of legibility. Now we have to undo that. + if event.name == 'space': + name = ' ' + + if 'shift' in event.name: + shift_pressed = event.event_type == 'down' + elif event.name == 'caps lock' and event.event_type == 'down': + capslock_pressed = not capslock_pressed + elif allow_backspace and event.name == backspace_name and event.event_type == 'down': + string = string[:-1] + elif event.event_type == 'down': + if len(name) == 1: + if shift_pressed ^ capslock_pressed: + name = name.upper() + string = string + name + else: + yield string + string = '' + yield string + +_recording = None +def start_recording(recorded_events_queue=None): + """ + Starts recording all keyboard events into a global variable, or the given + queue if any. Returns the queue of events and the hooked function. + + Use `stop_recording()` or `unhook(hooked_function)` to stop. + """ + recorded_events_queue = recorded_events_queue or _queue.Queue() + global _recording + _recording = (recorded_events_queue, hook(recorded_events_queue.put)) + return _recording + +def stop_recording(): + """ + Stops the global recording of events and returns a list of the events + captured. + """ + global _recording + if not _recording: + raise ValueError('Must call "start_recording" before.') + recorded_events_queue, hooked = _recording + unhook(hooked) + return list(recorded_events_queue.queue) + +def record(until='escape', suppress=False, trigger_on_release=False): + """ + Records all keyboard events from all keyboards until the user presses the + given hotkey. Then returns the list of events recorded, of type + `keyboard.KeyboardEvent`. Pairs well with + `play(events)`. + + Note: this is a blocking function. + Note: for more details on the keyboard hook and events see `hook`. + """ + start_recording() + wait(until, suppress=suppress, trigger_on_release=trigger_on_release) + return stop_recording() + +def play(events, speed_factor=1.0): + """ + Plays a sequence of recorded events, maintaining the relative time + intervals. If speed_factor is <= 0 then the actions are replayed as fast + as the OS allows. Pairs well with `record()`. + + Note: the current keyboard state is cleared at the beginning and restored at + the end of the function. + """ + state = stash_state() + + last_time = None + for event in events: + if speed_factor > 0 and last_time is not None: + _time.sleep((event.time - last_time) / speed_factor) + last_time = event.time + + key = event.scan_code or event.name + press(key) if event.event_type == KEY_DOWN else release(key) + + restore_modifiers(state) +replay = play + +_word_listeners = {} +def add_word_listener(word, callback, triggers=['space'], match_suffix=False, timeout=2): + """ + Invokes a callback every time a sequence of characters is typed (e.g. 'pet') + and followed by a trigger key (e.g. space). Modifiers (e.g. alt, ctrl, + shift) are ignored. + + - `word` the typed text to be matched. E.g. 'pet'. + - `callback` is an argument-less function to be invoked each time the word + is typed. + - `triggers` is the list of keys that will cause a match to be checked. If + the user presses some key that is not a character (len>1) and not in + triggers, the characters so far will be discarded. By default the trigger + is only `space`. + - `match_suffix` defines if endings of words should also be checked instead + of only whole words. E.g. if true, typing 'carpet'+space will trigger the + listener for 'pet'. Defaults to false, only whole words are checked. + - `timeout` is the maximum number of seconds between typed characters before + the current word is discarded. Defaults to 2 seconds. + + Returns the event handler created. To remove a word listener use + `remove_word_listener(word)` or `remove_word_listener(handler)`. + + Note: all actions are performed on key down. Key up events are ignored. + Note: word matches are **case sensitive**. + """ + state = _State() + state.current = '' + state.time = -1 + + def handler(event): + name = event.name + if event.event_type == KEY_UP or name in all_modifiers: return + + if timeout and event.time - state.time > timeout: + state.current = '' + state.time = event.time + + matched = state.current == word or (match_suffix and state.current.endswith(word)) + if name in triggers and matched: + callback() + state.current = '' + elif len(name) > 1: + state.current = '' + else: + state.current += name + + hooked = hook(handler) + def remove(): + hooked() + del _word_listeners[word] + del _word_listeners[handler] + del _word_listeners[remove] + _word_listeners[word] = _word_listeners[handler] = _word_listeners[remove] = remove + # TODO: allow multiple word listeners and removing them correctly. + return remove + +def remove_word_listener(word_or_handler): + """ + Removes a previously registered word listener. Accepts either the word used + during registration (exact string) or the event handler returned by the + `add_word_listener` or `add_abbreviation` functions. + """ + _word_listeners[word_or_handler]() + +def add_abbreviation(source_text, replacement_text, match_suffix=False, timeout=2): + """ + Registers a hotkey that replaces one typed text with another. For example + + add_abbreviation('tm', u'™') + + Replaces every "tm" followed by a space with a ™ symbol (and no space). The + replacement is done by sending backspace events. + + - `match_suffix` defines if endings of words should also be checked instead + of only whole words. E.g. if true, typing 'carpet'+space will trigger the + listener for 'pet'. Defaults to false, only whole words are checked. + - `timeout` is the maximum number of seconds between typed characters before + the current word is discarded. Defaults to 2 seconds. + + For more details see `add_word_listener`. + """ + replacement = '\b'*(len(source_text)+1) + replacement_text + callback = lambda: write(replacement) + return add_word_listener(source_text, callback, match_suffix=match_suffix, timeout=timeout) + +# Aliases. +register_word_listener = add_word_listener +register_abbreviation = add_abbreviation +remove_abbreviation = remove_word_listener \ No newline at end of file diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__main__.py b/CLI/venv/lib/python3.12/site-packages/keyboard/__main__.py new file mode 100644 index 0000000..3acc6f6 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/__main__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +import keyboard +import fileinput +import json +import sys + +def print_event_json(event): + print(event.to_json(ensure_ascii=sys.stdout.encoding != 'utf-8')) + sys.stdout.flush() +keyboard.hook(print_event_json) + +parse_event_json = lambda line: keyboard.KeyboardEvent(**json.loads(line)) +keyboard.play(parse_event_json(line) for line in fileinput.input()) \ No newline at end of file diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..3480b53 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/__main__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000..effa3e2 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/__main__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_canonical_names.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_canonical_names.cpython-312.pyc new file mode 100644 index 0000000..7970af7 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_canonical_names.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_darwinkeyboard.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_darwinkeyboard.cpython-312.pyc new file mode 100644 index 0000000..ed543d3 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_darwinkeyboard.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_darwinmouse.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_darwinmouse.cpython-312.pyc new file mode 100644 index 0000000..f641a42 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_darwinmouse.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_generic.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_generic.cpython-312.pyc new file mode 100644 index 0000000..0157cec Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_generic.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_keyboard_event.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_keyboard_event.cpython-312.pyc new file mode 100644 index 0000000..82f6c27 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_keyboard_event.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_keyboard_tests.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_keyboard_tests.cpython-312.pyc new file mode 100644 index 0000000..9992cda Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_keyboard_tests.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_mouse_event.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_mouse_event.cpython-312.pyc new file mode 100644 index 0000000..8a017d2 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_mouse_event.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_mouse_tests.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_mouse_tests.cpython-312.pyc new file mode 100644 index 0000000..31d9ce6 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_mouse_tests.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixcommon.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixcommon.cpython-312.pyc new file mode 100644 index 0000000..bbaf07d Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixcommon.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixkeyboard.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixkeyboard.cpython-312.pyc new file mode 100644 index 0000000..add07b0 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixkeyboard.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixmouse.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixmouse.cpython-312.pyc new file mode 100644 index 0000000..b67e02e Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_nixmouse.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_winkeyboard.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_winkeyboard.cpython-312.pyc new file mode 100644 index 0000000..d26b51b Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_winkeyboard.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_winmouse.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_winmouse.cpython-312.pyc new file mode 100644 index 0000000..0d29bbf Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/_winmouse.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/mouse.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/mouse.cpython-312.pyc new file mode 100644 index 0000000..6249c0a Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/keyboard/__pycache__/mouse.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_canonical_names.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_canonical_names.py new file mode 100644 index 0000000..003fd3b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_canonical_names.py @@ -0,0 +1,1246 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +try: + basestring +except NameError: + basestring = str + +import platform + +# Defaults to Windows canonical names (platform-specific overrides below) +canonical_names = { + 'escape': 'esc', + 'return': 'enter', + 'del': 'delete', + 'control': 'ctrl', + + 'left arrow': 'left', + 'up arrow': 'up', + 'down arrow': 'down', + 'right arrow': 'right', + + ' ': 'space', # Prefer to spell out keys that would be hard to read. + '\x1b': 'esc', + '\x08': 'backspace', + '\n': 'enter', + '\t': 'tab', + '\r': 'enter', + + 'scrlk': 'scroll lock', + 'prtscn': 'print screen', + 'prnt scrn': 'print screen', + 'snapshot': 'print screen', + 'ins': 'insert', + 'pause break': 'pause', + 'ctrll lock': 'caps lock', + 'capslock': 'caps lock', + 'number lock': 'num lock', + 'numlock': 'num lock', + 'space bar': 'space', + 'spacebar': 'space', + 'linefeed': 'enter', + 'win': 'windows', + + # Mac keys + 'command': 'windows', + 'cmd': 'windows', + 'control': 'ctrl', + 'option': 'alt', + + 'app': 'menu', + 'apps': 'menu', + 'application': 'menu', + 'applications': 'menu', + + 'pagedown': 'page down', + 'pageup': 'page up', + 'pgdown': 'page down', + 'pgup': 'page up', + + 'play/pause': 'play/pause media', + + 'num multiply': '*', + 'num divide': '/', + 'num add': '+', + 'num plus': '+', + 'num minus': '-', + 'num sub': '-', + 'num enter': 'enter', + 'num 0': '0', + 'num 1': '1', + 'num 2': '2', + 'num 3': '3', + 'num 4': '4', + 'num 5': '5', + 'num 6': '6', + 'num 7': '7', + 'num 8': '8', + 'num 9': '9', + + 'left win': 'left windows', + 'right win': 'right windows', + 'left control': 'left ctrl', + 'right control': 'right ctrl', + 'left menu': 'left alt', # Windows... + 'altgr': 'alt gr', + + # https://www.x.org/releases/X11R7.6/doc/libX11/Compose/en_US.UTF-8.html + # https://svn.apache.org/repos/asf/xmlgraphics/commons/tags/commons-1_0/src/java/org/apache/xmlgraphics/fonts/Glyphs.java + # Note this list has plenty of uppercase letters that are not being used + # at the moment, as normalization forces names to be lowercase. + "Aacute": "Á", + "aacute": "á", + "Aacutesmall": "", + "abovedot": "˙", + "Abreve": "Ă", + "abreve": "ă", + "Abreveacute": "Ắ", + "abreveacute": "ắ", + "Abrevebelowdot": "Ặ", + "abrevebelowdot": "ặ", + "Abrevegrave": "Ằ", + "abrevegrave": "ằ", + "Abrevehook": "Ẳ", + "abrevehook": "ẳ", + "Abrevetilde": "Ẵ", + "abrevetilde": "ẵ", + "Acircumflex": "Â", + "acircumflex": "â", + "Acircumflexacute": "Ấ", + "acircumflexacute": "ấ", + "Acircumflexbelowdot": "Ậ", + "acircumflexbelowdot": "ậ", + "Acircumflexgrave": "Ầ", + "acircumflexgrave": "ầ", + "Acircumflexhook": "Ẩ", + "acircumflexhook": "ẩ", + "Acircumflexsmall": "", + "Acircumflextilde": "Ẫ", + "acircumflextilde": "ẫ", + "acute": "´", + "Acute": "", + "acutecomb": "́", + "Acutesmall": "", + "add": "+", + "Adiaeresis": "Ä", + "adiaeresis": "ä", + "Adieresis": "Ä", + "adieresis": "ä", + "Adieresissmall": "", + "ae": "æ", + "AE": "Æ", + "AEacute": "Ǽ", + "aeacute": "ǽ", + "AEsmall": "", + "afii00208": "―", + "afii10017": "А", + "afii10018": "Б", + "afii10019": "В", + "afii10020": "Г", + "afii10021": "Д", + "afii10022": "Е", + "afii10023": "Ё", + "afii10024": "Ж", + "afii10025": "З", + "afii10026": "И", + "afii10027": "Й", + "afii10028": "К", + "afii10029": "Л", + "afii10030": "М", + "afii10031": "Н", + "afii10032": "О", + "afii10033": "П", + "afii10034": "Р", + "afii10035": "С", + "afii10036": "Т", + "afii10037": "У", + "afii10038": "Ф", + "afii10039": "Х", + "afii10040": "Ц", + "afii10041": "Ч", + "afii10042": "Ш", + "afii10043": "Щ", + "afii10044": "Ъ", + "afii10045": "Ы", + "afii10046": "Ь", + "afii10047": "Э", + "afii10048": "Ю", + "afii10049": "Я", + "afii10050": "Ґ", + "afii10051": "Ђ", + "afii10052": "Ѓ", + "afii10053": "Є", + "afii10054": "Ѕ", + "afii10055": "І", + "afii10056": "Ї", + "afii10057": "Ј", + "afii10058": "Љ", + "afii10059": "Њ", + "afii10060": "Ћ", + "afii10061": "Ќ", + "afii10062": "Ў", + "afii10063": "", + "afii10064": "", + "afii10065": "а", + "afii10066": "б", + "afii10067": "в", + "afii10068": "г", + "afii10069": "д", + "afii10070": "е", + "afii10071": "ё", + "afii10072": "ж", + "afii10073": "з", + "afii10074": "и", + "afii10075": "й", + "afii10076": "к", + "afii10077": "л", + "afii10078": "м", + "afii10079": "н", + "afii10080": "о", + "afii10081": "п", + "afii10082": "р", + "afii10083": "с", + "afii10084": "т", + "afii10085": "у", + "afii10086": "ф", + "afii10087": "х", + "afii10088": "ц", + "afii10089": "ч", + "afii10090": "ш", + "afii10091": "щ", + "afii10092": "ъ", + "afii10093": "ы", + "afii10094": "ь", + "afii10095": "э", + "afii10096": "ю", + "afii10097": "я", + "afii10098": "ґ", + "afii10099": "ђ", + "afii10100": "ѓ", + "afii10101": "є", + "afii10102": "ѕ", + "afii10103": "і", + "afii10104": "ї", + "afii10105": "ј", + "afii10106": "љ", + "afii10107": "њ", + "afii10108": "ћ", + "afii10109": "ќ", + "afii10110": "ў", + "afii10145": "Џ", + "afii10146": "Ѣ", + "afii10147": "Ѳ", + "afii10148": "Ѵ", + "afii10192": "", + "afii10193": "џ", + "afii10194": "ѣ", + "afii10195": "ѳ", + "afii10196": "ѵ", + "afii10831": "", + "afii10832": "", + "afii10846": "ә", + "afii299": "‎", + "afii300": "‏", + "afii301": "‍", + "afii57381": "٪", + "afii57388": "،", + "afii57392": "٠", + "afii57393": "١", + "afii57394": "٢", + "afii57395": "٣", + "afii57396": "٤", + "afii57397": "٥", + "afii57398": "٦", + "afii57399": "٧", + "afii57400": "٨", + "afii57401": "٩", + "afii57403": "؛", + "afii57407": "؟", + "afii57409": "ء", + "afii57410": "آ", + "afii57411": "أ", + "afii57412": "ؤ", + "afii57413": "إ", + "afii57414": "ئ", + "afii57415": "ا", + "afii57416": "ب", + "afii57417": "ة", + "afii57418": "ت", + "afii57419": "ث", + "afii57420": "ج", + "afii57421": "ح", + "afii57422": "خ", + "afii57423": "د", + "afii57424": "ذ", + "afii57425": "ر", + "afii57426": "ز", + "afii57427": "س", + "afii57428": "ش", + "afii57429": "ص", + "afii57430": "ض", + "afii57431": "ط", + "afii57432": "ظ", + "afii57433": "ع", + "afii57434": "غ", + "afii57440": "ـ", + "afii57441": "ف", + "afii57442": "ق", + "afii57443": "ك", + "afii57444": "ل", + "afii57445": "م", + "afii57446": "ن", + "afii57448": "و", + "afii57449": "ى", + "afii57450": "ي", + "afii57451": "ً", + "afii57452": "ٌ", + "afii57453": "ٍ", + "afii57454": "َ", + "afii57455": "ُ", + "afii57456": "ِ", + "afii57457": "ّ", + "afii57458": "ْ", + "afii57470": "ه", + "afii57505": "ڤ", + "afii57506": "پ", + "afii57507": "چ", + "afii57508": "ژ", + "afii57509": "گ", + "afii57511": "ٹ", + "afii57512": "ڈ", + "afii57513": "ڑ", + "afii57514": "ں", + "afii57519": "ے", + "afii57534": "ە", + "afii57636": "₪", + "afii57645": "־", + "afii57658": "׃", + "afii57664": "א", + "afii57665": "ב", + "afii57666": "ג", + "afii57667": "ד", + "afii57668": "ה", + "afii57669": "ו", + "afii57670": "ז", + "afii57671": "ח", + "afii57672": "ט", + "afii57673": "י", + "afii57674": "ך", + "afii57675": "כ", + "afii57676": "ל", + "afii57677": "ם", + "afii57678": "מ", + "afii57679": "ן", + "afii57680": "נ", + "afii57681": "ס", + "afii57682": "ע", + "afii57683": "ף", + "afii57684": "פ", + "afii57685": "ץ", + "afii57686": "צ", + "afii57687": "ק", + "afii57688": "ר", + "afii57689": "ש", + "afii57690": "ת", + "afii57694": "שׁ", + "afii57695": "שׂ", + "afii57700": "וֹ", + "afii57705": "ײַ", + "afii57716": "װ", + "afii57717": "ױ", + "afii57718": "ײ", + "afii57723": "וּ", + "afii57793": "ִ", + "afii57794": "ֵ", + "afii57795": "ֶ", + "afii57796": "ֻ", + "afii57797": "ָ", + "afii57798": "ַ", + "afii57799": "ְ", + "afii57800": "ֲ", + "afii57801": "ֱ", + "afii57802": "ֳ", + "afii57803": "ׂ", + "afii57804": "ׁ", + "afii57806": "ֹ", + "afii57807": "ּ", + "afii57839": "ֽ", + "afii57841": "ֿ", + "afii57842": "׀", + "afii57929": "ʼ", + "afii61248": "℅", + "afii61289": "ℓ", + "afii61352": "№", + "afii61573": "‬", + "afii61574": "‭", + "afii61575": "‮", + "afii61664": "‌", + "afii63167": "٭", + "afii64937": "ʽ", + "Agrave": "À", + "agrave": "à", + "Agravesmall": "", + "agudo": "´", + "aleph": "ℵ", + "Alpha": "Α", + "alpha": "α", + "Alphatonos": "Ά", + "alphatonos": "ά", + "Amacron": "Ā", + "amacron": "ā", + "ampersand": "&", + "ampersandsmall": "", + "angle": "∠", + "angleleft": "〈", + "angleright": "〉", + "anoteleia": "·", + "Aogonek": "Ą", + "aogonek": "ą", + "apostrophe": "'", + "approxequal": "≈", + "Aring": "Å", + "aring": "å", + "Aringacute": "Ǻ", + "aringacute": "ǻ", + "Aringsmall": "", + "arrowboth": "↔", + "arrowdblboth": "⇔", + "arrowdbldown": "⇓", + "arrowdblleft": "⇐", + "arrowdblright": "⇒", + "arrowdblup": "⇑", + "arrowdown": "↓", + "arrowhorizex": "", + "arrowleft": "←", + "arrowright": "→", + "arrowup": "↑", + "arrowupdn": "↕", + "arrowupdnbse": "↨", + "arrowvertex": "", + "asciicircum": "^", + "asciitilde": "~", + "Asmall": "", + "asterisk": "*", + "asteriskmath": "∗", + "asuperior": "", + "at": "@", + "Atilde": "Ã", + "atilde": "ã", + "Atildesmall": "", + "backslash": "\\", + "bar": "|", + "Beta": "Β", + "beta": "β", + "block": "█", + "braceex": "", + "braceleft": "{", + "braceleftbt": "", + "braceleftmid": "", + "bracelefttp": "", + "braceright": "}", + "bracerightbt": "", + "bracerightmid": "", + "bracerighttp": "", + "bracketleft": "[", + "bracketleftbt": "", + "bracketleftex": "", + "bracketlefttp": "", + "bracketright": "]", + "bracketrightbt": "", + "bracketrightex": "", + "bracketrighttp": "", + "breve": "˘", + "Brevesmall": "", + "brokenbar": "¦", + "Bsmall": "", + "bsuperior": "", + "bullet": "•", + "Cacute": "Ć", + "cacute": "ć", + "caron": "ˇ", + "Caron": "", + "Caronsmall": "", + "carriagereturn": "↵", + "Ccaron": "Č", + "ccaron": "č", + "Ccedilla": "Ç", + "ccedilla": "ç", + "Ccedillasmall": "", + "Ccircumflex": "Ĉ", + "ccircumflex": "ĉ", + "Cdotaccent": "Ċ", + "cdotaccent": "ċ", + "cedilla": "¸", + "Cedillasmall": "", + "cent": "¢", + "centinferior": "", + "centoldstyle": "", + "centsuperior": "", + "Chi": "Χ", + "chi": "χ", + "circle": "○", + "circlemultiply": "⊗", + "circleplus": "⊕", + "circumflex": "^", + "circumflex": "ˆ", + "Circumflexsmall": "", + "club": "♣", + "colon": ":", + "colonmonetary": "₡", + "ColonSign": "₡", + "comma": ",", + "commaaccent": "", + "commainferior": "", + "commasuperior": "", + "congruent": "≅", + "copyright": "©", + "copyrightsans": "", + "copyrightserif": "", + "CruzeiroSign": "₢", + "Csmall": "", + "currency": "¤", + "cyrBreve": "", + "cyrbreve": "", + "cyrFlex": "", + "cyrflex": "", + "dagger": "†", + "daggerdbl": "‡", + "dblGrave": "", + "dblgrave": "", + "Dcaron": "Ď", + "dcaron": "ď", + "Dcroat": "Đ", + "dcroat": "đ", + "degree": "°", + "Delta": "Δ", + "delta": "δ", + "diaeresis": "¨", + "diamond": "♦", + "dieresis": "¨", + "Dieresis": "", + "DieresisAcute": "", + "dieresisacute": "", + "DieresisGrave": "", + "dieresisgrave": "", + "Dieresissmall": "", + "dieresistonos": "΅", + "divide": "/", + "divide": "÷", + "division": "÷", + "dkshade": "▓", + "dnblock": "▄", + "dollar": "$", + "dollarinferior": "", + "dollaroldstyle": "", + "dollarsuperior": "", + "dong": "₫", + "DongSign": "₫", + "dot": ".", + "dotaccent": "˙", + "Dotaccentsmall": "", + "dotbelowcomb": "̣", + "dotlessi": "ı", + "dotlessj": "", + "dotmath": "⋅", + "Dsmall": "", + "dstroke": "đ", + "Dstroke": "Đ", + "dsuperior": "", + "Eacute": "É", + "eacute": "é", + "Eacutesmall": "", + "Ebreve": "Ĕ", + "ebreve": "ĕ", + "Ecaron": "Ě", + "ecaron": "ě", + "Ecircumflex": "Ê", + "ecircumflex": "ê", + "Ecircumflexacute": "Ế", + "ecircumflexacute": "ế", + "Ecircumflexbelowdot": "Ệ", + "ecircumflexbelowdot": "ệ", + "Ecircumflexgrave": "Ề", + "ecircumflexgrave": "ề", + "Ecircumflexhook": "Ể", + "ecircumflexhook": "ể", + "Ecircumflexsmall": "", + "Ecircumflextilde": "Ễ", + "ecircumflextilde": "ễ", + "EcuSign": "₠", + "Ediaeresis": "Ë", + "ediaeresis": "ë", + "Edieresis": "Ë", + "edieresis": "ë", + "Edieresissmall": "", + "Edotaccent": "Ė", + "edotaccent": "ė", + "Egrave": "È", + "egrave": "è", + "Egravesmall": "", + "eight": "8", + "eightinferior": "₈", + "eightoldstyle": "", + "eightsubscript": "₈", + "eightsuperior": "⁸", + "element": "∈", + "ellipsis": "…", + "Emacron": "Ē", + "emacron": "ē", + "emdash": "—", + "emptyset": "∅", + "endash": "–", + "enfilledcircbullet": "•", + "Eng": "Ŋ", + "eng": "ŋ", + "Eogonek": "Ę", + "eogonek": "ę", + "Epsilon": "Ε", + "epsilon": "ε", + "Epsilontonos": "Έ", + "epsilontonos": "έ", + "equal": "=", + "equivalence": "≡", + "Esmall": "", + "estimated": "℮", + "esuperior": "", + "Eta": "Η", + "eta": "η", + "Etatonos": "Ή", + "etatonos": "ή", + "ETH": "Ð", + "eth": "ð", + "Eth": "Ð", + "Ethsmall": "", + "euro": "€", + "Euro": "€", + "EuroSign": "€", + "exclam": "!", + "exclamdbl": "‼", + "exclamdown": "¡", + "exclamdownsmall": "", + "exclamsmall": "", + "existential": "∃", + "female": "♀", + "ff": "ff", + "ffi": "ffi", + "ffl": "ffl", + "FFrancSign": "₣", + "fi": "fi", + "figuredash": "‒", + "filledbox": "■", + "filledrect": "▬", + "five": "5", + "fiveeighths": "⅝", + "fiveinferior": "₅", + "fiveoldstyle": "", + "fivesubscript": "₅", + "fivesuperior": "⁵", + "fl": "fl", + "florin": "ƒ", + "four": "4", + "fourinferior": "₄", + "fouroldstyle": "", + "foursubscript": "₄", + "foursuperior": "⁴", + "fraction": "∕", + "franc": "₣", + "Fsmall": "", + "function": "ƒ", + "Gamma": "Γ", + "gamma": "γ", + "Gbreve": "Ğ", + "gbreve": "ğ", + "Gcaron": "Ǧ", + "gcaron": "ǧ", + "Gcircumflex": "Ĝ", + "gcircumflex": "ĝ", + "Gcommaaccent": "Ģ", + "gcommaaccent": "ģ", + "Gdotaccent": "Ġ", + "gdotaccent": "ġ", + "germandbls": "ß", + "gradient": "∇", + "grave": "`", + "Grave": "", + "gravecomb": "̀", + "Gravesmall": "", + "greater": ">", + "greaterequal": "≥", + "Gsmall": "", + "guillemotleft": "«", + "guillemotright": "»", + "guilsinglleft": "‹", + "guilsinglright": "›", + "H18533": "●", + "H18543": "▪", + "H18551": "▫", + "H22073": "□", + "hash": "#", + "hashtag": "#", + "Hbar": "Ħ", + "hbar": "ħ", + "Hcircumflex": "Ĥ", + "hcircumflex": "ĥ", + "heart": "♥", + "hookabovecomb": "̉", + "house": "⌂", + "Hsmall": "", + "hungarumlaut": "˝", + "Hungarumlaut": "", + "Hungarumlautsmall": "", + "hyphen": "­", + "hypheninferior": "", + "hyphensuperior": "", + "Iacute": "Í", + "iacute": "í", + "Iacutesmall": "", + "Ibreve": "Ĭ", + "ibreve": "ĭ", + "Icircumflex": "Î", + "icircumflex": "î", + "Icircumflexsmall": "", + "Idiaeresis": "Ï", + "idiaeresis": "ï", + "Idieresis": "Ï", + "idieresis": "ï", + "Idieresissmall": "", + "Idotaccent": "İ", + "Ifraktur": "ℑ", + "Igrave": "Ì", + "igrave": "ì", + "Igravesmall": "", + "IJ": "IJ", + "ij": "ij", + "Imacron": "Ī", + "imacron": "ī", + "infinity": "∞", + "integral": "∫", + "integralbt": "⌡", + "integralex": "", + "integraltp": "⌠", + "intersection": "∩", + "invbullet": "◘", + "invcircle": "◙", + "invsmileface": "☻", + "Iogonek": "Į", + "iogonek": "į", + "Iota": "Ι", + "iota": "ι", + "Iotadieresis": "Ϊ", + "iotadieresis": "ϊ", + "iotadieresistonos": "ΐ", + "Iotatonos": "Ί", + "iotatonos": "ί", + "Ismall": "", + "isuperior": "", + "Itilde": "Ĩ", + "itilde": "ĩ", + "Jcircumflex": "Ĵ", + "jcircumflex": "ĵ", + "Jsmall": "", + "Kappa": "Κ", + "kappa": "κ", + "Kcommaaccent": "Ķ", + "kcommaaccent": "ķ", + "kgreenlandic": "ĸ", + "Ksmall": "", + "Lacute": "Ĺ", + "lacute": "ĺ", + "Lambda": "Λ", + "lambda": "λ", + "Lcaron": "Ľ", + "lcaron": "ľ", + "Lcommaaccent": "Ļ", + "lcommaaccent": "ļ", + "Ldot": "Ŀ", + "ldot": "ŀ", + "less": "<", + "lessequal": "≤", + "lfblock": "▌", + "lira": "₤", + "LiraSign": "₤", + "LL": "", + "ll": "", + "logicaland": "∧", + "logicalnot": "¬", + "logicalor": "∨", + "longs": "ſ", + "lozenge": "◊", + "Lslash": "Ł", + "lslash": "ł", + "Lslashsmall": "", + "Lsmall": "", + "lsuperior": "", + "ltshade": "░", + "macron": "¯", + "macron": "ˉ", + "Macron": "", + "Macronsmall": "", + "male": "♂", + "masculine": "º", + "MillSign": "₥", + "minplus": "+", + "minus": "-", + "minus": "−", + "minute": "′", + "Msmall": "", + "msuperior": "", + "mu": "µ", + "Mu": "Μ", + "mu": "μ", + "multiply": "*", + "multiply": "×", + "musicalnote": "♪", + "musicalnotedbl": "♫", + "Nacute": "Ń", + "nacute": "ń", + "NairaSign": "₦", + "napostrophe": "ʼn", + "Ncaron": "Ň", + "ncaron": "ň", + "Ncommaaccent": "Ņ", + "ncommaaccent": "ņ", + "NewSheqelSign": "₪", + "nine": "9", + "nineinferior": "₉", + "nineoldstyle": "", + "ninesubscript": "₉", + "ninesuperior": "⁹", + "nobreakspace": " ", + "notelement": "∉", + "notequal": "≠", + "notsign": "¬", + "notsubset": "⊄", + "Nsmall": "", + "nsuperior": "ⁿ", + "Ntilde": "Ñ", + "ntilde": "ñ", + "Ntildesmall": "", + "Nu": "Ν", + "nu": "ν", + "numbersign": "#", + "numerosign": "№", + "Oacute": "Ó", + "oacute": "ó", + "Oacutesmall": "", + "Obreve": "Ŏ", + "obreve": "ŏ", + "Ocircumflex": "Ô", + "ocircumflex": "ô", + "Ocircumflexacute": "Ố", + "ocircumflexacute": "ố", + "Ocircumflexbelowdot": "Ộ", + "ocircumflexbelowdot": "ộ", + "Ocircumflexgrave": "Ồ", + "ocircumflexgrave": "ồ", + "Ocircumflexhook": "Ổ", + "ocircumflexhook": "ổ", + "Ocircumflexsmall": "", + "Ocircumflextilde": "Ỗ", + "ocircumflextilde": "ỗ", + "Odiaeresis": "Ö", + "odiaeresis": "ö", + "Odieresis": "Ö", + "odieresis": "ö", + "Odieresissmall": "", + "oe": "œ", + "OE": "Œ", + "OEsmall": "", + "ogonek": "˛", + "Ogoneksmall": "", + "Ograve": "Ò", + "ograve": "ò", + "Ogravesmall": "", + "Ohorn": "Ơ", + "ohorn": "ơ", + "Ohornacute": "Ớ", + "ohornacute": "ớ", + "Ohornbelowdot": "Ợ", + "ohornbelowdot": "ợ", + "Ohorngrave": "Ờ", + "ohorngrave": "ờ", + "Ohornhook": "Ở", + "ohornhook": "ở", + "Ohorntilde": "Ỡ", + "ohorntilde": "ỡ", + "Ohungarumlaut": "Ő", + "ohungarumlaut": "ő", + "Omacron": "Ō", + "omacron": "ō", + "Omega": "Ω", + "omega": "ω", + "omega1": "ϖ", + "Omegatonos": "Ώ", + "omegatonos": "ώ", + "Omicron": "Ο", + "omicron": "ο", + "Omicrontonos": "Ό", + "omicrontonos": "ό", + "one": "1", + "onedotenleader": "․", + "oneeighth": "⅛", + "onefitted": "", + "onehalf": "½", + "oneinferior": "₁", + "oneoldstyle": "", + "onequarter": "¼", + "onesubscript": "₁", + "onesuperior": "¹", + "onethird": "⅓", + "openbullet": "◦", + "ordfeminine": "ª", + "ordmasculine": "º", + "orthogonal": "∟", + "Oslash": "Ø", + "oslash": "ø", + "Oslashacute": "Ǿ", + "oslashacute": "ǿ", + "Oslashsmall": "", + "Osmall": "", + "osuperior": "", + "Otilde": "Õ", + "otilde": "õ", + "Otildesmall": "", + "paragraph": "¶", + "parenleft": "(", + "parenleftbt": "", + "parenleftex": "", + "parenleftinferior": "₍", + "parenleftsuperior": "⁽", + "parenlefttp": "", + "parenright": ")", + "parenrightbt": "", + "parenrightex": "", + "parenrightinferior": "₎", + "parenrightsuperior": "⁾", + "parenrighttp": "", + "partialdiff": "∂", + "percent": "%", + "period": ".", + "periodcentered": "·", + "periodcentered": "∙", + "periodinferior": "", + "periodsuperior": "", + "perpendicular": "⊥", + "perthousand": "‰", + "peseta": "₧", + "PesetaSign": "₧", + "Phi": "Φ", + "phi": "φ", + "phi1": "ϕ", + "Pi": "Π", + "pi": "π", + "plus": "+", + "plusminus": "±", + "pound": "£", + "prescription": "℞", + "product": "∏", + "propersubset": "⊂", + "propersuperset": "⊃", + "proportional": "∝", + "Psi": "Ψ", + "psi": "ψ", + "Psmall": "", + "Qsmall": "", + "question": "?", + "questiondown": "¿", + "questiondownsmall": "", + "questionsmall": "", + "quotedbl": "\"", + "quotedblbase": "„", + "quotedblleft": "“", + "quotedblright": "”", + "quoteleft": "‘", + "quotereversed": "‛", + "quoteright": "’", + "quotesinglbase": "‚", + "quotesingle": "'", + "Racute": "Ŕ", + "racute": "ŕ", + "radical": "√", + "radicalex": "", + "Rcaron": "Ř", + "rcaron": "ř", + "Rcommaaccent": "Ŗ", + "rcommaaccent": "ŗ", + "reflexsubset": "⊆", + "reflexsuperset": "⊇", + "registered": "®", + "registersans": "", + "registerserif": "", + "revlogicalnot": "⌐", + "Rfraktur": "ℜ", + "Rho": "Ρ", + "rho": "ρ", + "ring": "˚", + "Ringsmall": "", + "Rsmall": "", + "rsuperior": "", + "rtblock": "▐", + "RupeeSign": "₨", + "rupiah": "", + "Sacute": "Ś", + "sacute": "ś", + "Scaron": "Š", + "scaron": "š", + "Scaronsmall": "", + "Scedilla": "", + "scedilla": "", + "Scircumflex": "Ŝ", + "scircumflex": "ŝ", + "Scommaaccent": "Ș", + "scommaaccent": "ș", + "second": "″", + "section": "§", + "semicolon": ";", + "seven": "7", + "seveneighths": "⅞", + "seveninferior": "₇", + "sevenoldstyle": "", + "sevensubscript": "₇", + "sevensuperior": "⁷", + "SF010000": "┌", + "SF020000": "└", + "SF030000": "┐", + "SF040000": "┘", + "SF050000": "┼", + "SF060000": "┬", + "SF070000": "┴", + "SF080000": "├", + "SF090000": "┤", + "SF100000": "─", + "SF110000": "│", + "SF190000": "╡", + "SF200000": "╢", + "SF210000": "╖", + "SF220000": "╕", + "SF230000": "╣", + "SF240000": "║", + "SF250000": "╗", + "SF260000": "╝", + "SF270000": "╜", + "SF280000": "╛", + "SF360000": "╞", + "SF370000": "╟", + "SF380000": "╚", + "SF390000": "╔", + "SF400000": "╩", + "SF410000": "╦", + "SF420000": "╠", + "SF430000": "═", + "SF440000": "╬", + "SF450000": "╧", + "SF460000": "╨", + "SF470000": "╤", + "SF480000": "╥", + "SF490000": "╙", + "SF500000": "╘", + "SF510000": "╒", + "SF520000": "╓", + "SF530000": "╫", + "SF540000": "╪", + "shade": "▒", + "Sigma": "Σ", + "sigma": "σ", + "sigma1": "ς", + "similar": "∼", + "similarequal": "≃", + "six": "6", + "sixinferior": "₆", + "sixoldstyle": "", + "sixsubscript": "₆", + "sixsuperior": "⁶", + "slash": "/", + "smileface": "☺", + "spade": "♠", + "ssharp": "§", + "ssharp": "ß", + "Ssharp": "ẞ", + "Ssmall": "", + "ssuperior": "", + "sterling": "£", + "subtract": "-", + "suchthat": "∋", + "summation": "∑", + "sun": "☼", + "Tau": "Τ", + "tau": "τ", + "Tbar": "Ŧ", + "tbar": "ŧ", + "Tcaron": "Ť", + "tcaron": "ť", + "Tcommaaccent": "Ț", + "tcommaaccent": "ț", + "Thai_baht": "฿", + "therefore": "∴", + "Theta": "Θ", + "theta": "θ", + "theta1": "ϑ", + "THORN": "Þ", + "thorn": "þ", + "Thorn": "Þ", + "Thornsmall": "", + "three": "3", + "threeeighths": "⅜", + "threeinferior": "₃", + "threeoldstyle": "", + "threequarters": "¾", + "threequartersemdash": "", + "threesubscript": "₃", + "threesuperior": "³", + "til": "~", + "tilde": "~", + "tilde": "˜", + "tildecomb": "̃", + "Tildesmall": "", + "tonos": "΄", + "trademark": "™", + "trademarksans": "", + "trademarkserif": "", + "triagdn": "▼", + "triaglf": "◄", + "triagrt": "►", + "triagup": "▲", + "Tsmall": "", + "tsuperior": "", + "two": "2", + "twodotenleader": "‥", + "twoinferior": "₂", + "twooldstyle": "", + "twosubscript": "₂", + "twosuperior": "²", + "twothirds": "⅔", + "Uacute": "Ú", + "uacute": "ú", + "Uacutesmall": "", + "Ubreve": "Ŭ", + "ubreve": "ŭ", + "Ucircumflex": "Û", + "ucircumflex": "û", + "Ucircumflexsmall": "", + "Udiaeresis": "Ü", + "udiaeresis": "ü", + "Udieresis": "Ü", + "udieresis": "ü", + "Udieresissmall": "", + "Ugrave": "Ù", + "ugrave": "ù", + "Ugravesmall": "", + "Uhorn": "Ư", + "uhorn": "ư", + "Uhornacute": "Ứ", + "uhornacute": "ứ", + "Uhornbelowdot": "Ự", + "uhornbelowdot": "ự", + "Uhorngrave": "Ừ", + "uhorngrave": "ừ", + "Uhornhook": "Ử", + "uhornhook": "ử", + "Uhorntilde": "Ữ", + "uhorntilde": "ữ", + "Uhungarumlaut": "Ű", + "uhungarumlaut": "ű", + "Umacron": "Ū", + "umacron": "ū", + "underscore": "_", + "underscoredbl": "‗", + "union": "∪", + "universal": "∀", + "Uogonek": "Ų", + "uogonek": "ų", + "upblock": "▀", + "Upsilon": "Υ", + "upsilon": "υ", + "Upsilon1": "ϒ", + "Upsilondieresis": "Ϋ", + "upsilondieresis": "ϋ", + "upsilondieresistonos": "ΰ", + "Upsilontonos": "Ύ", + "upsilontonos": "ύ", + "Uring": "Ů", + "uring": "ů", + "Usmall": "", + "Utilde": "Ũ", + "utilde": "ũ", + "Vsmall": "", + "Wacute": "Ẃ", + "wacute": "ẃ", + "Wcircumflex": "Ŵ", + "wcircumflex": "ŵ", + "Wdieresis": "Ẅ", + "wdieresis": "ẅ", + "weierstrass": "℘", + "Wgrave": "Ẁ", + "wgrave": "ẁ", + "WonSign": "₩", + "Wsmall": "", + "Xi": "Ξ", + "xi": "ξ", + "Xsmall": "", + "Yacute": "Ý", + "yacute": "ý", + "Yacutesmall": "", + "Ycircumflex": "Ŷ", + "ycircumflex": "ŷ", + "ydiaeresis": "ÿ", + "Ydieresis": "Ÿ", + "ydieresis": "ÿ", + "Ydieresissmall": "", + "yen": "¥", + "Ygrave": "Ỳ", + "ygrave": "ỳ", + "Ysmall": "", + "Zacute": "Ź", + "zacute": "ź", + "Zcaron": "Ž", + "zcaron": "ž", + "Zcaronsmall": "", + "Zdotaccent": "Ż", + "zdotaccent": "ż", + "zero": "0", + "zeroinferior": "₀", + "zerooldstyle": "", + "zerosubscript": "₀", + "zerosuperior": "⁰", + "zeta": "ζ", + "Zeta": "Ζ", + "Zsmall": "", +} +sided_modifiers = {'ctrl', 'alt', 'shift', 'windows'} +all_modifiers = {'alt', 'alt gr', 'ctrl', 'shift', 'windows'} | set('left ' + n for n in sided_modifiers) | set('right ' + n for n in sided_modifiers) + +# Platform-specific canonical overrides + +if platform.system() == 'Darwin': + canonical_names.update({ + "command": "command", + "windows": "command", + "cmd": "command", + "win": "command", + "backspace": "delete", + 'alt gr': 'alt' # Issue #117 + }) + all_modifiers = {'alt', 'ctrl', 'shift', 'windows'} +if platform.system() == 'Linux': + canonical_names.update({ + "select": "end", + "find": "home", + 'next': 'page down', + 'prior': 'page up', + }) + +def normalize_name(name): + """ + Given a key name (e.g. "LEFT CONTROL"), clean up the string and convert to + the canonical representation (e.g. "left ctrl") if one is known. + """ + if not name or not isinstance(name, basestring): + raise ValueError('Can only normalize non-empty string names. Unexpected '+ repr(name)) + + if len(name) > 1: + name = name.lower() + if name != '_' and '_' in name: + name = name.replace('_', ' ') + + return canonical_names.get(name, name) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_darwinkeyboard.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_darwinkeyboard.py new file mode 100644 index 0000000..85670ee --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_darwinkeyboard.py @@ -0,0 +1,442 @@ +import ctypes +import ctypes.util +import Quartz +import time +import os +import threading +from AppKit import NSEvent +from ._keyboard_event import KeyboardEvent, KEY_DOWN, KEY_UP +from ._canonical_names import normalize_name + +try: # Python 2/3 compatibility + unichr +except NameError: + unichr = chr + +Carbon = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Carbon')) + +class KeyMap(object): + non_layout_keys = dict((vk, normalize_name(name)) for vk, name in { + # Layout specific keys from https://stackoverflow.com/a/16125341/252218 + # Unfortunately no source for layout-independent keys was found. + 0x24: 'return', + 0x30: 'tab', + 0x31: 'space', + 0x33: 'delete', + 0x35: 'escape', + 0x37: 'command', + 0x38: 'shift', + 0x39: 'capslock', + 0x3a: 'option', + 0x3b: 'control', + 0x3c: 'right shift', + 0x3d: 'right option', + 0x3e: 'right control', + 0x3f: 'function', + 0x40: 'f17', + 0x48: 'volume up', + 0x49: 'volume down', + 0x4a: 'mute', + 0x4f: 'f18', + 0x50: 'f19', + 0x5a: 'f20', + 0x60: 'f5', + 0x61: 'f6', + 0x62: 'f7', + 0x63: 'f3', + 0x64: 'f8', + 0x65: 'f9', + 0x67: 'f11', + 0x69: 'f13', + 0x6a: 'f16', + 0x6b: 'f14', + 0x6d: 'f10', + 0x6f: 'f12', + 0x71: 'f15', + 0x72: 'help', + 0x73: 'home', + 0x74: 'page up', + 0x75: 'forward delete', + 0x76: 'f4', + 0x77: 'end', + 0x78: 'f2', + 0x79: 'page down', + 0x7a: 'f1', + 0x7b: 'left', + 0x7c: 'right', + 0x7d: 'down', + 0x7e: 'up', + }.items()) + layout_specific_keys = {} + def __init__(self): + # Virtual key codes are usually the same for any given key, unless you have a different + # keyboard layout. The only way I've found to determine the layout relies on (supposedly + # deprecated) Carbon APIs. If there's a more modern way to do this, please update this + # section. + + # Set up data types and exported values: + + CFTypeRef = ctypes.c_void_p + CFDataRef = ctypes.c_void_p + CFIndex = ctypes.c_uint64 + OptionBits = ctypes.c_uint32 + UniCharCount = ctypes.c_uint8 + UniChar = ctypes.c_uint16 + UniChar4 = UniChar * 4 + + class CFRange(ctypes.Structure): + _fields_ = [('loc', CFIndex), + ('len', CFIndex)] + + kTISPropertyUnicodeKeyLayoutData = ctypes.c_void_p.in_dll(Carbon, 'kTISPropertyUnicodeKeyLayoutData') + shiftKey = 0x0200 + alphaKey = 0x0400 + optionKey = 0x0800 + controlKey = 0x1000 + kUCKeyActionDisplay = 3 + kUCKeyTranslateNoDeadKeysBit = 0 + + # Set up function calls: + Carbon.CFDataGetBytes.argtypes = [CFDataRef] #, CFRange, UInt8 + Carbon.CFDataGetBytes.restype = None + Carbon.CFDataGetLength.argtypes = [CFDataRef] + Carbon.CFDataGetLength.restype = CFIndex + Carbon.CFRelease.argtypes = [CFTypeRef] + Carbon.CFRelease.restype = None + Carbon.LMGetKbdType.argtypes = [] + Carbon.LMGetKbdType.restype = ctypes.c_uint32 + Carbon.TISCopyCurrentKeyboardInputSource.argtypes = [] + Carbon.TISCopyCurrentKeyboardInputSource.restype = ctypes.c_void_p + Carbon.TISCopyCurrentASCIICapableKeyboardLayoutInputSource.argtypes = [] + Carbon.TISCopyCurrentASCIICapableKeyboardLayoutInputSource.restype = ctypes.c_void_p + Carbon.TISGetInputSourceProperty.argtypes = [ctypes.c_void_p, ctypes.c_void_p] + Carbon.TISGetInputSourceProperty.restype = ctypes.c_void_p + Carbon.UCKeyTranslate.argtypes = [ctypes.c_void_p, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint32, + ctypes.c_uint32, + OptionBits, # keyTranslateOptions + ctypes.POINTER(ctypes.c_uint32), # deadKeyState + UniCharCount, # maxStringLength + ctypes.POINTER(UniCharCount), # actualStringLength + UniChar4] + Carbon.UCKeyTranslate.restype = ctypes.c_uint32 + + # Get keyboard layout + klis = Carbon.TISCopyCurrentKeyboardInputSource() + k_layout = Carbon.TISGetInputSourceProperty(klis, kTISPropertyUnicodeKeyLayoutData) + if k_layout is None: + klis = Carbon.TISCopyCurrentASCIICapableKeyboardLayoutInputSource() + k_layout = Carbon.TISGetInputSourceProperty(klis, kTISPropertyUnicodeKeyLayoutData) + k_layout_size = Carbon.CFDataGetLength(k_layout) + k_layout_buffer = ctypes.create_string_buffer(k_layout_size) # TODO - Verify this works instead of initializing with empty string + Carbon.CFDataGetBytes(k_layout, CFRange(0, k_layout_size), ctypes.byref(k_layout_buffer)) + + # Generate character representations of key codes + for key_code in range(0, 128): + # TODO - Possibly add alt modifier to key map + non_shifted_char = UniChar4() + shifted_char = UniChar4() + keys_down = ctypes.c_uint32() + char_count = UniCharCount() + + retval = Carbon.UCKeyTranslate(k_layout_buffer, + key_code, + kUCKeyActionDisplay, + 0, # No modifier + Carbon.LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + ctypes.byref(keys_down), + 4, + ctypes.byref(char_count), + non_shifted_char) + + non_shifted_key = u''.join(unichr(non_shifted_char[i]) for i in range(char_count.value)) + + retval = Carbon.UCKeyTranslate(k_layout_buffer, + key_code, + kUCKeyActionDisplay, + shiftKey >> 8, # Shift + Carbon.LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + ctypes.byref(keys_down), + 4, + ctypes.byref(char_count), + shifted_char) + + shifted_key = u''.join(unichr(shifted_char[i]) for i in range(char_count.value)) + + self.layout_specific_keys[key_code] = (non_shifted_key, shifted_key) + # Cleanup + Carbon.CFRelease(klis) + + def character_to_vk(self, character): + """ Returns a tuple of (scan_code, modifiers) where ``scan_code`` is a numeric scan code + and ``modifiers`` is an array of string modifier names (like 'shift') """ + for vk in self.non_layout_keys: + if self.non_layout_keys[vk] == character.lower(): + return (vk, []) + for vk in self.layout_specific_keys: + if self.layout_specific_keys[vk][0] == character: + return (vk, []) + elif self.layout_specific_keys[vk][1] == character: + return (vk, ['shift']) + raise ValueError("Unrecognized character: {}".format(character)) + + def vk_to_character(self, vk, modifiers=[]): + """ Returns a character corresponding to the specified scan code (with given + modifiers applied) """ + if vk in self.non_layout_keys: + # Not a character + return self.non_layout_keys[vk] + elif vk in self.layout_specific_keys: + if 'shift' in modifiers: + return self.layout_specific_keys[vk][1] + return self.layout_specific_keys[vk][0] + else: + # Invalid vk + raise ValueError("Invalid scan code: {}".format(vk)) + + +class KeyController(object): + def __init__(self): + self.key_map = KeyMap() + self.current_modifiers = { + "shift": False, + "caps": False, + "alt": False, + "ctrl": False, + "cmd": False, + } + self.media_keys = { + 'KEYTYPE_SOUND_UP': 0, + 'KEYTYPE_SOUND_DOWN': 1, + 'KEYTYPE_BRIGHTNESS_UP': 2, + 'KEYTYPE_BRIGHTNESS_DOWN': 3, + 'KEYTYPE_CAPS_LOCK': 4, + 'KEYTYPE_HELP': 5, + 'POWER_KEY': 6, + 'KEYTYPE_MUTE': 7, + 'UP_ARROW_KEY': 8, + 'DOWN_ARROW_KEY': 9, + 'KEYTYPE_NUM_LOCK': 10, + 'KEYTYPE_CONTRAST_UP': 11, + 'KEYTYPE_CONTRAST_DOWN': 12, + 'KEYTYPE_LAUNCH_PANEL': 13, + 'KEYTYPE_EJECT': 14, + 'KEYTYPE_VIDMIRROR': 15, + 'KEYTYPE_PLAY': 16, + 'KEYTYPE_NEXT': 17, + 'KEYTYPE_PREVIOUS': 18, + 'KEYTYPE_FAST': 19, + 'KEYTYPE_REWIND': 20, + 'KEYTYPE_ILLUMINATION_UP': 21, + 'KEYTYPE_ILLUMINATION_DOWN': 22, + 'KEYTYPE_ILLUMINATION_TOGGLE': 23 + } + + def press(self, key_code): + """ Sends a 'down' event for the specified scan code """ + if key_code >= 128: + # Media key + ev = NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_( + 14, # type + (0, 0), # location + 0xa00, # flags + 0, # timestamp + 0, # window + 0, # ctx + 8, # subtype + ((key_code-128) << 16) | (0xa << 8), # data1 + -1 # data2 + ) + Quartz.CGEventPost(0, ev.CGEvent()) + else: + # Regular key + # Apply modifiers if necessary + event_flags = 0 + if self.current_modifiers["shift"]: + event_flags += Quartz.kCGEventFlagMaskShift + if self.current_modifiers["caps"]: + event_flags += Quartz.kCGEventFlagMaskAlphaShift + if self.current_modifiers["alt"]: + event_flags += Quartz.kCGEventFlagMaskAlternate + if self.current_modifiers["ctrl"]: + event_flags += Quartz.kCGEventFlagMaskControl + if self.current_modifiers["cmd"]: + event_flags += Quartz.kCGEventFlagMaskCommand + + # Update modifiers if necessary + if key_code == 0x37: # cmd + self.current_modifiers["cmd"] = True + elif key_code == 0x38 or key_code == 0x3C: # shift or right shift + self.current_modifiers["shift"] = True + elif key_code == 0x39: # caps lock + self.current_modifiers["caps"] = True + elif key_code == 0x3A: # alt + self.current_modifiers["alt"] = True + elif key_code == 0x3B: # ctrl + self.current_modifiers["ctrl"] = True + event = Quartz.CGEventCreateKeyboardEvent(None, key_code, True) + Quartz.CGEventSetFlags(event, event_flags) + Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) + time.sleep(0.01) + + def release(self, key_code): + """ Sends an 'up' event for the specified scan code """ + if key_code >= 128: + # Media key + ev = NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_( + 14, # type + (0, 0), # location + 0xb00, # flags + 0, # timestamp + 0, # window + 0, # ctx + 8, # subtype + ((key_code-128) << 16) | (0xb << 8), # data1 + -1 # data2 + ) + Quartz.CGEventPost(0, ev.CGEvent()) + else: + # Regular key + # Update modifiers if necessary + if key_code == 0x37: # cmd + self.current_modifiers["cmd"] = False + elif key_code == 0x38 or key_code == 0x3C: # shift or right shift + self.current_modifiers["shift"] = False + elif key_code == 0x39: # caps lock + self.current_modifiers["caps"] = False + elif key_code == 0x3A: # alt + self.current_modifiers["alt"] = False + elif key_code == 0x3B: # ctrl + self.current_modifiers["ctrl"] = False + + # Apply modifiers if necessary + event_flags = 0 + if self.current_modifiers["shift"]: + event_flags += Quartz.kCGEventFlagMaskShift + if self.current_modifiers["caps"]: + event_flags += Quartz.kCGEventFlagMaskAlphaShift + if self.current_modifiers["alt"]: + event_flags += Quartz.kCGEventFlagMaskAlternate + if self.current_modifiers["ctrl"]: + event_flags += Quartz.kCGEventFlagMaskControl + if self.current_modifiers["cmd"]: + event_flags += Quartz.kCGEventFlagMaskCommand + event = Quartz.CGEventCreateKeyboardEvent(None, key_code, False) + Quartz.CGEventSetFlags(event, event_flags) + Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) + time.sleep(0.01) + + def map_char(self, character): + if character in self.media_keys: + return (128+self.media_keys[character],[]) + else: + return self.key_map.character_to_vk(character) + def map_scan_code(self, scan_code): + if scan_code >= 128: + character = [k for k, v in enumerate(self.media_keys) if v == scan_code-128] + if len(character): + return character[0] + return None + else: + return self.key_map.vk_to_character(scan_code) + +class KeyEventListener(object): + def __init__(self, callback, blocking=False): + self.blocking = blocking + self.callback = callback + self.listening = True + self.tap = None + + def run(self): + """ Creates a listener and loops while waiting for an event. Intended to run as + a background thread. """ + self.tap = Quartz.CGEventTapCreate( + Quartz.kCGSessionEventTap, + Quartz.kCGHeadInsertEventTap, + Quartz.kCGEventTapOptionDefault, + Quartz.CGEventMaskBit(Quartz.kCGEventKeyDown) | + Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp) | + Quartz.CGEventMaskBit(Quartz.kCGEventFlagsChanged), + self.handler, + None) + loopsource = Quartz.CFMachPortCreateRunLoopSource(None, self.tap, 0) + loop = Quartz.CFRunLoopGetCurrent() + Quartz.CFRunLoopAddSource(loop, loopsource, Quartz.kCFRunLoopDefaultMode) + Quartz.CGEventTapEnable(self.tap, True) + + while self.listening: + Quartz.CFRunLoopRunInMode(Quartz.kCFRunLoopDefaultMode, 5, False) + + def handler(self, proxy, e_type, event, refcon): + scan_code = Quartz.CGEventGetIntegerValueField(event, Quartz.kCGKeyboardEventKeycode) + key_name = name_from_scancode(scan_code) + flags = Quartz.CGEventGetFlags(event) + event_type = "" + is_keypad = (flags & Quartz.kCGEventFlagMaskNumericPad) + if e_type == Quartz.kCGEventKeyDown: + event_type = "down" + elif e_type == Quartz.kCGEventKeyUp: + event_type = "up" + elif e_type == Quartz.kCGEventFlagsChanged: + if key_name.endswith("shift") and (flags & Quartz.kCGEventFlagMaskShift): + event_type = "down" + elif key_name == "caps lock" and (flags & Quartz.kCGEventFlagMaskAlphaShift): + event_type = "down" + elif (key_name.endswith("option") or key_name.endswith("alt")) and (flags & Quartz.kCGEventFlagMaskAlternate): + event_type = "down" + elif key_name == "ctrl" and (flags & Quartz.kCGEventFlagMaskControl): + event_type = "down" + elif key_name == "command" and (flags & Quartz.kCGEventFlagMaskCommand): + event_type = "down" + else: + event_type = "up" + + if self.blocking: + return None + + self.callback(KeyboardEvent(event_type, scan_code, name=key_name, is_keypad=is_keypad)) + return event + +key_controller = KeyController() + +""" Exported functions below """ + +def init(): + key_controller = KeyController() + +def press(scan_code): + """ Sends a 'down' event for the specified scan code """ + key_controller.press(scan_code) + +def release(scan_code): + """ Sends an 'up' event for the specified scan code """ + key_controller.release(scan_code) + +def map_name(name): + """ Returns a tuple of (scan_code, modifiers) where ``scan_code`` is a numeric scan code + and ``modifiers`` is an array of string modifier names (like 'shift') """ + yield key_controller.map_char(name) + +def name_from_scancode(scan_code): + """ Returns the name or character associated with the specified key code """ + return key_controller.map_scan_code(scan_code) + +def listen(callback): + if not os.geteuid() == 0: + raise OSError("Error 13 - Must be run as administrator") + KeyEventListener(callback).run() + +def type_unicode(character): + OUTPUT_SOURCE = Quartz.CGEventSourceCreate(Quartz.kCGEventSourceStateHIDSystemState) + # Key down + event = Quartz.CGEventCreateKeyboardEvent(OUTPUT_SOURCE, 0, True) + Quartz.CGEventKeyboardSetUnicodeString(event, len(character.encode('utf-16-le')) // 2, character) + Quartz.CGEventPost(Quartz.kCGSessionEventTap, event) + # Key up + event = Quartz.CGEventCreateKeyboardEvent(OUTPUT_SOURCE, 0, False) + Quartz.CGEventKeyboardSetUnicodeString(event, len(character.encode('utf-16-le')) // 2, character) + Quartz.CGEventPost(Quartz.kCGSessionEventTap, event) \ No newline at end of file diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_darwinmouse.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_darwinmouse.py new file mode 100644 index 0000000..b112dc0 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_darwinmouse.py @@ -0,0 +1,173 @@ +import os +import datetime +import threading +import Quartz +from ._mouse_event import ButtonEvent, WheelEvent, MoveEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN + +_button_mapping = { + LEFT: (Quartz.kCGMouseButtonLeft, Quartz.kCGEventLeftMouseDown, Quartz.kCGEventLeftMouseUp, Quartz.kCGEventLeftMouseDragged), + RIGHT: (Quartz.kCGMouseButtonRight, Quartz.kCGEventRightMouseDown, Quartz.kCGEventRightMouseUp, Quartz.kCGEventRightMouseDragged), + MIDDLE: (Quartz.kCGMouseButtonCenter, Quartz.kCGEventOtherMouseDown, Quartz.kCGEventOtherMouseUp, Quartz.kCGEventOtherMouseDragged) +} +_button_state = { + LEFT: False, + RIGHT: False, + MIDDLE: False +} +_last_click = { + "time": None, + "button": None, + "position": None, + "click_count": 0 +} + +class MouseEventListener(object): + def __init__(self, callback, blocking=False): + self.blocking = blocking + self.callback = callback + self.listening = True + + def run(self): + """ Creates a listener and loops while waiting for an event. Intended to run as + a background thread. """ + self.tap = Quartz.CGEventTapCreate( + Quartz.kCGSessionEventTap, + Quartz.kCGHeadInsertEventTap, + Quartz.kCGEventTapOptionDefault, + Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDown) | + Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseUp) | + Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseDown) | + Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseUp) | + Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseDown) | + Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseUp) | + Quartz.CGEventMaskBit(Quartz.kCGEventMouseMoved) | + Quartz.CGEventMaskBit(Quartz.kCGEventScrollWheel), + self.handler, + None) + loopsource = Quartz.CFMachPortCreateRunLoopSource(None, self.tap, 0) + loop = Quartz.CFRunLoopGetCurrent() + Quartz.CFRunLoopAddSource(loop, loopsource, Quartz.kCFRunLoopDefaultMode) + Quartz.CGEventTapEnable(self.tap, True) + + while self.listening: + Quartz.CFRunLoopRunInMode(Quartz.kCFRunLoopDefaultMode, 5, False) + + def handler(self, proxy, e_type, event, refcon): + # TODO Separate event types by button/wheel/move + scan_code = Quartz.CGEventGetIntegerValueField(event, Quartz.kCGKeyboardEventKeycode) + key_name = name_from_scancode(scan_code) + flags = Quartz.CGEventGetFlags(event) + event_type = "" + is_keypad = (flags & Quartz.kCGEventFlagMaskNumericPad) + if e_type == Quartz.kCGEventKeyDown: + event_type = "down" + elif e_type == Quartz.kCGEventKeyUp: + event_type = "up" + + if self.blocking: + return None + + self.callback(KeyboardEvent(event_type, scan_code, name=key_name, is_keypad=is_keypad)) + return event + +# Exports + +def init(): + """ Initializes mouse state """ + pass + +def listen(queue): + """ Appends events to the queue (ButtonEvent, WheelEvent, and MoveEvent). """ + if not os.geteuid() == 0: + raise OSError("Error 13 - Must be run as administrator") + listener = MouseEventListener(lambda e: queue.put(e) or is_allowed(e.name, e.event_type == KEY_UP)) + t = threading.Thread(target=listener.run, args=()) + t.daemon = True + t.start() + +def press(button=LEFT): + """ Sends a down event for the specified button, using the provided constants """ + location = get_position() + button_code, button_down, _, _ = _button_mapping[button] + e = Quartz.CGEventCreateMouseEvent( + None, + button_down, + location, + button_code) + + # Check if this is a double-click (same location within the last 300ms) + if _last_click["time"] is not None and datetime.datetime.now() - _last_click["time"] < datetime.timedelta(seconds=0.3) and _last_click["button"] == button and _last_click["position"] == location: + # Repeated Click + _last_click["click_count"] = min(3, _last_click["click_count"]+1) + else: + # Not a double-click - Reset last click + _last_click["click_count"] = 1 + Quartz.CGEventSetIntegerValueField( + e, + Quartz.kCGMouseEventClickState, + _last_click["click_count"]) + Quartz.CGEventPost(Quartz.kCGHIDEventTap, e) + _button_state[button] = True + _last_click["time"] = datetime.datetime.now() + _last_click["button"] = button + _last_click["position"] = location + +def release(button=LEFT): + """ Sends an up event for the specified button, using the provided constants """ + location = get_position() + button_code, _, button_up, _ = _button_mapping[button] + e = Quartz.CGEventCreateMouseEvent( + None, + button_up, + location, + button_code) + + if _last_click["time"] is not None and _last_click["time"] > datetime.datetime.now() - datetime.timedelta(microseconds=300000) and _last_click["button"] == button and _last_click["position"] == location: + # Repeated Click + Quartz.CGEventSetIntegerValueField( + e, + Quartz.kCGMouseEventClickState, + _last_click["click_count"]) + Quartz.CGEventPost(Quartz.kCGHIDEventTap, e) + _button_state[button] = False + +def wheel(delta=1): + """ Sends a wheel event for the provided number of clicks. May be negative to reverse + direction. """ + location = get_position() + e = Quartz.CGEventCreateMouseEvent( + None, + Quartz.kCGEventScrollWheel, + location, + Quartz.kCGMouseButtonLeft) + e2 = Quartz.CGEventCreateScrollWheelEvent( + None, + Quartz.kCGScrollEventUnitLine, + 1, + delta) + Quartz.CGEventPost(Quartz.kCGHIDEventTap, e) + Quartz.CGEventPost(Quartz.kCGHIDEventTap, e2) + +def move_to(x, y): + """ Sets the mouse's location to the specified coordinates. """ + for b in _button_state: + if _button_state[b]: + e = Quartz.CGEventCreateMouseEvent( + None, + _button_mapping[b][3], # Drag Event + (x, y), + _button_mapping[b][0]) + break + else: + e = Quartz.CGEventCreateMouseEvent( + None, + Quartz.kCGEventMouseMoved, + (x, y), + Quartz.kCGMouseButtonLeft) + Quartz.CGEventPost(Quartz.kCGHIDEventTap, e) + +def get_position(): + """ Returns the mouse's location as a tuple of (x, y). """ + e = Quartz.CGEventCreate(None) + point = Quartz.CGEventGetLocation(e) + return (point.x, point.y) \ No newline at end of file diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_generic.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_generic.py new file mode 100644 index 0000000..bac559f --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_generic.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +from threading import Thread, Lock +import traceback +import functools + +try: + from queue import Queue +except ImportError: + from Queue import Queue + +class GenericListener(object): + lock = Lock() + + def __init__(self): + self.handlers = [] + self.listening = False + self.queue = Queue() + + def invoke_handlers(self, event): + for handler in self.handlers: + try: + if handler(event): + # Stop processing this hotkey. + return 1 + except Exception as e: + traceback.print_exc() + + def start_if_necessary(self): + """ + Starts the listening thread if it wasn't already. + """ + self.lock.acquire() + try: + if not self.listening: + self.init() + + self.listening = True + self.listening_thread = Thread(target=self.listen) + self.listening_thread.daemon = True + self.listening_thread.start() + + self.processing_thread = Thread(target=self.process) + self.processing_thread.daemon = True + self.processing_thread.start() + finally: + self.lock.release() + + def pre_process_event(self, event): + raise NotImplementedError('This method should be implemented in the child class.') + + def process(self): + """ + Loops over the underlying queue of events and processes them in order. + """ + assert self.queue is not None + while True: + event = self.queue.get() + if self.pre_process_event(event): + self.invoke_handlers(event) + self.queue.task_done() + + def add_handler(self, handler): + """ + Adds a function to receive each event captured, starting the capturing + process if necessary. + """ + self.start_if_necessary() + self.handlers.append(handler) + + def remove_handler(self, handler): + """ Removes a previously added event handler. """ + while handler in self.handlers: + self.handlers.remove(handler) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_keyboard_event.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_keyboard_event.py new file mode 100644 index 0000000..6d9f279 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_keyboard_event.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- + +from time import time as now +import json +from ._canonical_names import canonical_names, normalize_name + +try: + basestring +except NameError: + basestring = str + +KEY_DOWN = 'down' +KEY_UP = 'up' + +class KeyboardEvent(object): + event_type = None + scan_code = None + name = None + time = None + device = None + modifiers = None + is_keypad = None + + def __init__(self, event_type, scan_code, name=None, time=None, device=None, modifiers=None, is_keypad=None): + self.event_type = event_type + self.scan_code = scan_code + self.time = now() if time is None else time + self.device = device + self.is_keypad = is_keypad + self.modifiers = modifiers + if name: + self.name = normalize_name(name) + + def to_json(self, ensure_ascii=False): + attrs = dict( + (attr, getattr(self, attr)) for attr in ['event_type', 'scan_code', 'name', 'time', 'device', 'is_keypad'] + if not attr.startswith('_') and getattr(self, attr) is not None + ) + return json.dumps(attrs, ensure_ascii=ensure_ascii) + + def __repr__(self): + return 'KeyboardEvent({} {})'.format(self.name or 'Unknown {}'.format(self.scan_code), self.event_type) + + def __eq__(self, other): + return ( + isinstance(other, KeyboardEvent) + and self.event_type == other.event_type + and ( + not self.scan_code or not other.scan_code or self.scan_code == other.scan_code + ) and ( + not self.name or not other.name or self.name == other.name + ) + ) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_keyboard_tests.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_keyboard_tests.py new file mode 100644 index 0000000..f0e1432 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_keyboard_tests.py @@ -0,0 +1,827 @@ +# -*- coding: utf-8 -*- +""" +Side effects are avoided using two techniques: + +- Low level OS requests (keyboard._os_keyboard) are mocked out by rewriting +the functions at that namespace. This includes a list of dummy keys. +- Events are pumped manually by the main test class, and accepted events +are tested against expected values. + +Fake user events are appended to `input_events`, passed through +keyboard,_listener.direct_callback, then, if accepted, appended to +`output_events`. Fake OS events (keyboard.press) are processed +and added to `output_events` immediately, mimicking real functionality. +""" +from __future__ import print_function + +import unittest +import time + +import keyboard +from ._keyboard_event import KeyboardEvent, KEY_DOWN, KEY_UP + +dummy_keys = { + 'space': [(0, [])], + + 'a': [(1, [])], + 'b': [(2, [])], + 'c': [(3, [])], + 'A': [(1, ['shift']), (-1, [])], + 'B': [(2, ['shift']), (-2, [])], + 'C': [(3, ['shift']), (-3, [])], + + 'alt': [(4, [])], + 'left alt': [(4, [])], + + 'left shift': [(5, [])], + 'right shift': [(6, [])], + + 'left ctrl': [(7, [])], + + 'backspace': [(8, [])], + 'caps lock': [(9, [])], + + '+': [(10, [])], + ',': [(11, [])], + '_': [(12, [])], + + 'none': [], + 'duplicated': [(20, []), (20, [])], +} + +def make_event(event_type, name, scan_code=None, time=0): + return KeyboardEvent(event_type=event_type, scan_code=scan_code or dummy_keys[name][0][0], name=name, time=time) + +# Used when manually pumping events. +input_events = [] +output_events = [] + +def send_instant_event(event): + if keyboard._listener.direct_callback(event): + output_events.append(event) + +# Mock out side effects. +keyboard._os_keyboard.init = lambda: None +keyboard._os_keyboard.listen = lambda callback: None +keyboard._os_keyboard.map_name = dummy_keys.__getitem__ +keyboard._os_keyboard.press = lambda scan_code: send_instant_event(make_event(KEY_DOWN, None, scan_code)) +keyboard._os_keyboard.release = lambda scan_code: send_instant_event(make_event(KEY_UP, None, scan_code)) +keyboard._os_keyboard.type_unicode = lambda char: output_events.append(KeyboardEvent(event_type=KEY_DOWN, scan_code=999, name=char)) + +# Shortcuts for defining test inputs and expected outputs. +# Usage: d_shift + d_a + u_a + u_shift +d_a = [make_event(KEY_DOWN, 'a')] +u_a = [make_event(KEY_UP, 'a')] +du_a = d_a+u_a +d_b = [make_event(KEY_DOWN, 'b')] +u_b = [make_event(KEY_UP, 'b')] +du_b = d_b+u_b +d_c = [make_event(KEY_DOWN, 'c')] +u_c = [make_event(KEY_UP, 'c')] +du_c = d_c+u_c +d_ctrl = [make_event(KEY_DOWN, 'left ctrl')] +u_ctrl = [make_event(KEY_UP, 'left ctrl')] +du_ctrl = d_ctrl+u_ctrl +d_shift = [make_event(KEY_DOWN, 'left shift')] +u_shift = [make_event(KEY_UP, 'left shift')] +du_shift = d_shift+u_shift +d_alt = [make_event(KEY_DOWN, 'alt')] +u_alt = [make_event(KEY_UP, 'alt')] +du_alt = d_alt+u_alt +du_backspace = [make_event(KEY_DOWN, 'backspace'), make_event(KEY_UP, 'backspace')] +du_capslock = [make_event(KEY_DOWN, 'caps lock'), make_event(KEY_UP, 'caps lock')] +d_space = [make_event(KEY_DOWN, 'space')] +u_space = [make_event(KEY_UP, 'space')] +du_space = [make_event(KEY_DOWN, 'space'), make_event(KEY_UP, 'space')] + +trigger = lambda e=None: keyboard.press(999) +triggered_event = [KeyboardEvent(KEY_DOWN, scan_code=999)] + +class TestKeyboard(unittest.TestCase): + def tearDown(self): + keyboard.unhook_all() + #self.assertEquals(keyboard._hooks, {}) + #self.assertEquals(keyboard._hotkeys, {}) + + def setUp(self): + #keyboard._hooks.clear() + #keyboard._hotkeys.clear() + del input_events[:] + del output_events[:] + keyboard._recording = None + keyboard._pressed_events.clear() + keyboard._physically_pressed_keys.clear() + keyboard._logically_pressed_keys.clear() + keyboard._hotkeys.clear() + keyboard._listener.init() + keyboard._word_listeners = {} + + def do(self, manual_events, expected=None): + input_events.extend(manual_events) + while input_events: + event = input_events.pop(0) + if keyboard._listener.direct_callback(event): + output_events.append(event) + if expected is not None: + to_names = lambda es: '+'.join(('d' if e.event_type == KEY_DOWN else 'u') + '_' + str(e.scan_code) for e in es) + self.assertEqual(to_names(output_events), to_names(expected)) + del output_events[:] + + keyboard._listener.queue.join() + + def test_event_json(self): + event = make_event(KEY_DOWN, u'á \'"', 999) + import json + self.assertEqual(event, KeyboardEvent(**json.loads(event.to_json()))) + + def test_is_modifier_name(self): + for name in keyboard.all_modifiers: + self.assertTrue(keyboard.is_modifier(name)) + def test_is_modifier_scan_code(self): + for i in range(10): + self.assertEqual(keyboard.is_modifier(i), i in [4, 5, 6, 7]) + + def test_key_to_scan_codes_brute(self): + for name, entries in dummy_keys.items(): + if name in ['none', 'duplicated']: continue + expected = tuple(scan_code for scan_code, modifiers in entries) + self.assertEqual(keyboard.key_to_scan_codes(name), expected) + def test_key_to_scan_code_from_scan_code(self): + for i in range(10): + self.assertEqual(keyboard.key_to_scan_codes(i), (i,)) + def test_key_to_scan_code_from_letter(self): + self.assertEqual(keyboard.key_to_scan_codes('a'), (1,)) + self.assertEqual(keyboard.key_to_scan_codes('A'), (1,-1)) + def test_key_to_scan_code_from_normalized(self): + self.assertEqual(keyboard.key_to_scan_codes('shift'), (5,6)) + self.assertEqual(keyboard.key_to_scan_codes('SHIFT'), (5,6)) + self.assertEqual(keyboard.key_to_scan_codes('ctrl'), keyboard.key_to_scan_codes('CONTROL')) + def test_key_to_scan_code_from_sided_modifier(self): + self.assertEqual(keyboard.key_to_scan_codes('left shift'), (5,)) + self.assertEqual(keyboard.key_to_scan_codes('right shift'), (6,)) + def test_key_to_scan_code_underscores(self): + self.assertEqual(keyboard.key_to_scan_codes('_'), (12,)) + self.assertEqual(keyboard.key_to_scan_codes('right_shift'), (6,)) + def test_key_to_scan_code_error_none(self): + with self.assertRaises(ValueError): + keyboard.key_to_scan_codes(None) + def test_key_to_scan_code_error_empty(self): + with self.assertRaises(ValueError): + keyboard.key_to_scan_codes('') + def test_key_to_scan_code_error_other(self): + with self.assertRaises(ValueError): + keyboard.key_to_scan_codes({}) + def test_key_to_scan_code_list(self): + self.assertEqual(keyboard.key_to_scan_codes([10, 5, 'a']), (10, 5, 1)) + def test_key_to_scan_code_empty(self): + with self.assertRaises(ValueError): + keyboard.key_to_scan_codes('none') + def test_key_to_scan_code_duplicated(self): + self.assertEqual(keyboard.key_to_scan_codes('duplicated'), (20,)) + + def test_parse_hotkey_simple(self): + self.assertEqual(keyboard.parse_hotkey('a'), (((1,),),)) + self.assertEqual(keyboard.parse_hotkey('A'), (((1,-1),),)) + def test_parse_hotkey_separators(self): + self.assertEqual(keyboard.parse_hotkey('+'), keyboard.parse_hotkey('plus')) + self.assertEqual(keyboard.parse_hotkey(','), keyboard.parse_hotkey('comma')) + def test_parse_hotkey_keys(self): + self.assertEqual(keyboard.parse_hotkey('left shift + a'), (((5,), (1,),),)) + self.assertEqual(keyboard.parse_hotkey('left shift+a'), (((5,), (1,),),)) + def test_parse_hotkey_simple_steps(self): + self.assertEqual(keyboard.parse_hotkey('a,b'), (((1,),),((2,),))) + self.assertEqual(keyboard.parse_hotkey('a, b'), (((1,),),((2,),))) + def test_parse_hotkey_steps(self): + self.assertEqual(keyboard.parse_hotkey('a+b, b+c'), (((1,),(2,)),((2,),(3,)))) + def test_parse_hotkey_example(self): + alt_codes = keyboard.key_to_scan_codes('alt') + shift_codes = keyboard.key_to_scan_codes('shift') + a_codes = keyboard.key_to_scan_codes('a') + b_codes = keyboard.key_to_scan_codes('b') + c_codes = keyboard.key_to_scan_codes('c') + self.assertEqual(keyboard.parse_hotkey("alt+shift+a, alt+b, c"), ((alt_codes, shift_codes, a_codes), (alt_codes, b_codes), (c_codes,))) + def test_parse_hotkey_list_scan_codes(self): + self.assertEqual(keyboard.parse_hotkey([1, 2, 3]), (((1,), (2,), (3,)),)) + def test_parse_hotkey_deep_list_scan_codes(self): + result = keyboard.parse_hotkey('a') + self.assertEqual(keyboard.parse_hotkey(result), (((1,),),)) + def test_parse_hotkey_list_names(self): + self.assertEqual(keyboard.parse_hotkey(['a', 'b', 'c']), (((1,), (2,), (3,)),)) + + def test_is_pressed_none(self): + self.assertFalse(keyboard.is_pressed('a')) + def test_is_pressed_true(self): + self.do(d_a) + self.assertTrue(keyboard.is_pressed('a')) + def test_is_pressed_true_scan_code_true(self): + self.do(d_a) + self.assertTrue(keyboard.is_pressed(1)) + def test_is_pressed_true_scan_code_false(self): + self.do(d_a) + self.assertFalse(keyboard.is_pressed(2)) + def test_is_pressed_true_scan_code_invalid(self): + self.do(d_a) + self.assertFalse(keyboard.is_pressed(-1)) + def test_is_pressed_false(self): + self.do(d_a+u_a+d_b) + self.assertFalse(keyboard.is_pressed('a')) + self.assertTrue(keyboard.is_pressed('b')) + def test_is_pressed_hotkey_true(self): + self.do(d_shift+d_a) + self.assertTrue(keyboard.is_pressed('shift+a')) + def test_is_pressed_hotkey_false(self): + self.do(d_shift+d_a+u_a) + self.assertFalse(keyboard.is_pressed('shift+a')) + def test_is_pressed_multi_step_fail(self): + self.do(u_a+d_a) + with self.assertRaises(ValueError): + keyboard.is_pressed('a, b') + + def test_send_single_press_release(self): + keyboard.send('a', do_press=True, do_release=True) + self.do([], d_a+u_a) + def test_send_single_press(self): + keyboard.send('a', do_press=True, do_release=False) + self.do([], d_a) + def test_send_single_release(self): + keyboard.send('a', do_press=False, do_release=True) + self.do([], u_a) + def test_send_single_none(self): + keyboard.send('a', do_press=False, do_release=False) + self.do([], []) + def test_press(self): + keyboard.press('a') + self.do([], d_a) + def test_release(self): + keyboard.release('a') + self.do([], u_a) + def test_press_and_release(self): + keyboard.press_and_release('a') + self.do([], d_a+u_a) + + def test_send_modifier_press_release(self): + keyboard.send('ctrl+a', do_press=True, do_release=True) + self.do([], d_ctrl+d_a+u_a+u_ctrl) + def test_send_modifiers_release(self): + keyboard.send('ctrl+shift+a', do_press=False, do_release=True) + self.do([], u_a+u_shift+u_ctrl) + + def test_call_later(self): + triggered = [] + def fn(arg1, arg2): + assert arg1 == 1 and arg2 == 2 + triggered.append(True) + keyboard.call_later(fn, (1, 2), 0.01) + self.assertFalse(triggered) + time.sleep(0.05) + self.assertTrue(triggered) + + def test_hook_nonblocking(self): + self.i = 0 + def count(e): + self.assertEqual(e.name, 'a') + self.i += 1 + hook = keyboard.hook(count, suppress=False) + self.do(d_a+u_a, d_a+u_a) + self.assertEqual(self.i, 2) + keyboard.unhook(hook) + self.do(d_a+u_a, d_a+u_a) + self.assertEqual(self.i, 2) + keyboard.hook(count, suppress=False) + self.do(d_a+u_a, d_a+u_a) + self.assertEqual(self.i, 4) + keyboard.unhook_all() + self.do(d_a+u_a, d_a+u_a) + self.assertEqual(self.i, 4) + def test_hook_blocking(self): + self.i = 0 + def count(e): + self.assertIn(e.name, ['a', 'b']) + self.i += 1 + return e.name == 'b' + hook = keyboard.hook(count, suppress=True) + self.do(d_a+d_b, d_b) + self.assertEqual(self.i, 2) + keyboard.unhook(hook) + self.do(d_a+d_b, d_a+d_b) + self.assertEqual(self.i, 2) + keyboard.hook(count, suppress=True) + self.do(d_a+d_b, d_b) + self.assertEqual(self.i, 4) + keyboard.unhook_all() + self.do(d_a+d_b, d_a+d_b) + self.assertEqual(self.i, 4) + def test_on_press_nonblocking(self): + keyboard.on_press(lambda e: self.assertEqual(e.name, 'a') and self.assertEqual(e.event_type, KEY_DOWN)) + self.do(d_a+u_a) + def test_on_press_blocking(self): + keyboard.on_press(lambda e: e.scan_code == 1, suppress=True) + self.do([make_event(KEY_DOWN, 'A', -1)] + d_a, d_a) + def test_on_release(self): + keyboard.on_release(lambda e: self.assertEqual(e.name, 'a') and self.assertEqual(e.event_type, KEY_UP)) + self.do(d_a+u_a) + + def test_hook_key_invalid(self): + with self.assertRaises(ValueError): + keyboard.hook_key('invalid', lambda e: None) + def test_hook_key_nonblocking(self): + self.i = 0 + def count(event): + self.i += 1 + hook = keyboard.hook_key('A', count) + self.do(d_a) + self.assertEqual(self.i, 1) + self.do(u_a+d_b) + self.assertEqual(self.i, 2) + self.do([make_event(KEY_DOWN, 'A', -1)]) + self.assertEqual(self.i, 3) + keyboard.unhook_key(hook) + self.do(d_a) + self.assertEqual(self.i, 3) + def test_hook_key_blocking(self): + self.i = 0 + def count(event): + self.i += 1 + return event.scan_code == 1 + hook = keyboard.hook_key('A', count, suppress=True) + self.do(d_a, d_a) + self.assertEqual(self.i, 1) + self.do(u_a+d_b, u_a+d_b) + self.assertEqual(self.i, 2) + self.do([make_event(KEY_DOWN, 'A', -1)], []) + self.assertEqual(self.i, 3) + keyboard.unhook_key(hook) + self.do([make_event(KEY_DOWN, 'A', -1)], [make_event(KEY_DOWN, 'A', -1)]) + self.assertEqual(self.i, 3) + def test_on_press_key_nonblocking(self): + keyboard.on_press_key('A', lambda e: self.assertEqual(e.name, 'a') and self.assertEqual(e.event_type, KEY_DOWN)) + self.do(d_a+u_a+d_b+u_b) + def test_on_press_key_blocking(self): + keyboard.on_press_key('A', lambda e: e.scan_code == 1, suppress=True) + self.do([make_event(KEY_DOWN, 'A', -1)] + d_a, d_a) + def test_on_release_key(self): + keyboard.on_release_key('a', lambda e: self.assertEqual(e.name, 'a') and self.assertEqual(e.event_type, KEY_UP)) + self.do(d_a+u_a) + + def test_block_key(self): + blocked = keyboard.block_key('a') + self.do(d_a+d_b, d_b) + self.do([make_event(KEY_DOWN, 'A', -1)], [make_event(KEY_DOWN, 'A', -1)]) + keyboard.unblock_key(blocked) + self.do(d_a+d_b, d_a+d_b) + def test_block_key_ambiguous(self): + keyboard.block_key('A') + self.do(d_a+d_b, d_b) + self.do([make_event(KEY_DOWN, 'A', -1)], []) + + def test_remap_key_simple(self): + mapped = keyboard.remap_key('a', 'b') + self.do(d_a+d_c+u_a, d_b+d_c+u_b) + keyboard.unremap_key(mapped) + self.do(d_a+d_c+u_a, d_a+d_c+u_a) + def test_remap_key_ambiguous(self): + keyboard.remap_key('A', 'b') + self.do(d_a+d_b, d_b+d_b) + self.do([make_event(KEY_DOWN, 'A', -1)], d_b) + def test_remap_key_multiple(self): + mapped = keyboard.remap_key('a', 'shift+b') + self.do(d_a+d_c+u_a, d_shift+d_b+d_c+u_b+u_shift) + keyboard.unremap_key(mapped) + self.do(d_a+d_c+u_a, d_a+d_c+u_a) + + def test_stash_state(self): + self.do(d_a+d_shift) + self.assertEqual(sorted(keyboard.stash_state()), [1, 5]) + self.do([], u_a+u_shift) + def test_restore_state(self): + self.do(d_b) + keyboard.restore_state([1, 5]) + self.do([], u_b+d_a+d_shift) + def test_restore_modifieres(self): + self.do(d_b) + keyboard.restore_modifiers([1, 5]) + self.do([], u_b+d_shift) + + def test_write_simple(self): + keyboard.write('a', exact=False) + self.do([], d_a+u_a) + def test_write_multiple(self): + keyboard.write('ab', exact=False) + self.do([], d_a+u_a+d_b+u_b) + def test_write_modifiers(self): + keyboard.write('Ab', exact=False) + self.do([], d_shift+d_a+u_a+u_shift+d_b+u_b) + # restore_state_after has been removed after the introduction of `restore_modifiers`. + #def test_write_stash_not_restore(self): + # self.do(d_shift) + # keyboard.write('a', restore_state_after=False, exact=False) + # self.do([], u_shift+d_a+u_a) + def test_write_stash_restore(self): + self.do(d_shift) + keyboard.write('a', exact=False) + self.do([], u_shift+d_a+u_a+d_shift) + def test_write_multiple(self): + last_time = time.time() + keyboard.write('ab', delay=0.01, exact=False) + self.do([], d_a+u_a+d_b+u_b) + self.assertGreater(time.time() - last_time, 0.015) + def test_write_unicode_explicit(self): + keyboard.write('ab', exact=True) + self.do([], [KeyboardEvent(event_type=KEY_DOWN, scan_code=999, name='a'), KeyboardEvent(event_type=KEY_DOWN, scan_code=999, name='b')]) + def test_write_unicode_fallback(self): + keyboard.write(u'áb', exact=False) + self.do([], [KeyboardEvent(event_type=KEY_DOWN, scan_code=999, name=u'á')]+d_b+u_b) + + def test_start_stop_recording(self): + keyboard.start_recording() + self.do(d_a+u_a) + self.assertEqual(keyboard.stop_recording(), d_a+u_a) + def test_stop_recording_error(self): + with self.assertRaises(ValueError): + keyboard.stop_recording() + + def test_record(self): + queue = keyboard._queue.Queue() + def process(): + queue.put(keyboard.record('space', suppress=True)) + from threading import Thread + t = Thread(target=process) + t.daemon = True + t.start() + # 0.01s sleep failed once already. Better solutions? + time.sleep(0.01) + self.do(du_a+du_b+du_space, du_a+du_b) + self.assertEqual(queue.get(timeout=0.5), du_a+du_b+du_space) + + def test_play_nodelay(self): + keyboard.play(d_a+u_a, 0) + self.do([], d_a+u_a) + def test_play_stash(self): + self.do(d_ctrl) + keyboard.play(d_a+u_a, 0) + self.do([], u_ctrl+d_a+u_a+d_ctrl) + def test_play_delay(self): + last_time = time.time() + events = [make_event(KEY_DOWN, 'a', 1, 100), make_event(KEY_UP, 'a', 1, 100.01)] + keyboard.play(events, 1) + self.do([], d_a+u_a) + self.assertGreater(time.time() - last_time, 0.005) + + def test_get_typed_strings_simple(self): + events = du_a+du_b+du_backspace+d_shift+du_a+u_shift+du_space+du_ctrl+du_a + self.assertEqual(list(keyboard.get_typed_strings(events)), ['aA ', 'a']) + def test_get_typed_strings_backspace(self): + events = du_a+du_b+du_backspace + self.assertEqual(list(keyboard.get_typed_strings(events)), ['a']) + events = du_backspace+du_a+du_b + self.assertEqual(list(keyboard.get_typed_strings(events)), ['ab']) + def test_get_typed_strings_shift(self): + events = d_shift+du_a+du_b+u_shift+du_space+du_ctrl+du_a + self.assertEqual(list(keyboard.get_typed_strings(events)), ['AB ', 'a']) + def test_get_typed_strings_all(self): + events = du_a+du_b+du_backspace+d_shift+du_a+du_capslock+du_b+u_shift+du_space+du_ctrl+du_a + self.assertEqual(list(keyboard.get_typed_strings(events)), ['aAb ', 'A']) + + def test_get_hotkey_name_simple(self): + self.assertEqual(keyboard.get_hotkey_name(['a']), 'a') + def test_get_hotkey_name_modifiers(self): + self.assertEqual(keyboard.get_hotkey_name(['a', 'shift', 'ctrl']), 'ctrl+shift+a') + def test_get_hotkey_name_normalize(self): + self.assertEqual(keyboard.get_hotkey_name(['SHIFT', 'left ctrl']), 'ctrl+shift') + def test_get_hotkey_name_plus(self): + self.assertEqual(keyboard.get_hotkey_name(['+']), 'plus') + def test_get_hotkey_name_duplicated(self): + self.assertEqual(keyboard.get_hotkey_name(['+', 'plus']), 'plus') + def test_get_hotkey_name_full(self): + self.assertEqual(keyboard.get_hotkey_name(['+', 'left ctrl', 'shift', 'WIN', 'right alt']), 'ctrl+alt+shift+windows+plus') + def test_get_hotkey_name_multiple(self): + self.assertEqual(keyboard.get_hotkey_name(['ctrl', 'b', '!', 'a']), 'ctrl+!+a+b') + def test_get_hotkey_name_from_pressed(self): + self.do(du_c+d_ctrl+d_a+d_b) + self.assertEqual(keyboard.get_hotkey_name(), 'ctrl+a+b') + + def test_read_hotkey(self): + queue = keyboard._queue.Queue() + def process(): + queue.put(keyboard.read_hotkey()) + from threading import Thread + t = Thread(target=process) + t.daemon = True + t.start() + time.sleep(0.01) + self.do(d_ctrl+d_a+d_b+u_ctrl) + self.assertEqual(queue.get(timeout=0.5), 'ctrl+a+b') + + def test_read_event(self): + queue = keyboard._queue.Queue() + def process(): + queue.put(keyboard.read_event(suppress=True)) + from threading import Thread + t = Thread(target=process) + t.daemon = True + t.start() + time.sleep(0.01) + self.do(d_a, []) + self.assertEqual(queue.get(timeout=0.5), d_a[0]) + + def test_read_key(self): + queue = keyboard._queue.Queue() + def process(): + queue.put(keyboard.read_key(suppress=True)) + from threading import Thread + t = Thread(target=process) + t.daemon = True + t.start() + time.sleep(0.01) + self.do(d_a, []) + self.assertEqual(queue.get(timeout=0.5), 'a') + + def test_wait_infinite(self): + self.triggered = False + def process(): + keyboard.wait() + self.triggered = True + from threading import Thread + t = Thread(target=process) + t.daemon = True # Yep, we are letting this thread loose. + t.start() + time.sleep(0.01) + self.assertFalse(self.triggered) + + def test_wait_until_success(self): + queue = keyboard._queue.Queue() + def process(): + queue.put(keyboard.wait(queue.get(timeout=0.5), suppress=True) or True) + from threading import Thread + t = Thread(target=process) + t.daemon = True + t.start() + queue.put('a') + time.sleep(0.01) + self.do(d_a, []) + self.assertTrue(queue.get(timeout=0.5)) + def test_wait_until_fail(self): + def process(): + keyboard.wait('a', suppress=True) + self.fail() + from threading import Thread + t = Thread(target=process) + t.daemon = True # Yep, we are letting this thread loose. + t.start() + time.sleep(0.01) + self.do(d_b) + + def test_add_hotkey_single_step_suppress_allow(self): + keyboard.add_hotkey('a', lambda: trigger() or True, suppress=True) + self.do(d_a, triggered_event+d_a) + def test_add_hotkey_single_step_suppress_args_allow(self): + arg = object() + keyboard.add_hotkey('a', lambda a: self.assertIs(a, arg) or trigger() or True, args=(arg,), suppress=True) + self.do(d_a, triggered_event+d_a) + def test_add_hotkey_single_step_suppress_single(self): + keyboard.add_hotkey('a', trigger, suppress=True) + self.do(d_a, triggered_event) + def test_add_hotkey_single_step_suppress_removed(self): + keyboard.remove_hotkey(keyboard.add_hotkey('a', trigger, suppress=True)) + self.do(d_a, d_a) + def test_add_hotkey_single_step_suppress_removed(self): + keyboard.remove_hotkey(keyboard.add_hotkey('ctrl+a', trigger, suppress=True)) + self.do(d_ctrl+d_a, d_ctrl+d_a) + self.assertEqual(keyboard._listener.filtered_modifiers[dummy_keys['left ctrl'][0][0]], 0) + def test_remove_hotkey_internal(self): + remove = keyboard.add_hotkey('shift+a', trigger, suppress=True) + self.assertTrue(all(keyboard._listener.blocking_hotkeys.values())) + self.assertTrue(all(keyboard._listener.filtered_modifiers.values())) + self.assertNotEqual(keyboard._hotkeys, {}) + remove() + self.assertTrue(not any(keyboard._listener.filtered_modifiers.values())) + self.assertTrue(not any(keyboard._listener.blocking_hotkeys.values())) + self.assertEqual(keyboard._hotkeys, {}) + def test_remove_hotkey_internal_multistep_start(self): + remove = keyboard.add_hotkey('shift+a, b', trigger, suppress=True) + self.assertTrue(all(keyboard._listener.blocking_hotkeys.values())) + self.assertTrue(all(keyboard._listener.filtered_modifiers.values())) + self.assertNotEqual(keyboard._hotkeys, {}) + remove() + self.assertTrue(not any(keyboard._listener.filtered_modifiers.values())) + self.assertTrue(not any(keyboard._listener.blocking_hotkeys.values())) + self.assertEqual(keyboard._hotkeys, {}) + def test_remove_hotkey_internal_multistep_end(self): + remove = keyboard.add_hotkey('shift+a, b', trigger, suppress=True) + self.do(d_shift+du_a+u_shift) + self.assertTrue(any(keyboard._listener.blocking_hotkeys.values())) + self.assertTrue(not any(keyboard._listener.filtered_modifiers.values())) + self.assertNotEqual(keyboard._hotkeys, {}) + remove() + self.assertTrue(not any(keyboard._listener.filtered_modifiers.values())) + self.assertTrue(not any(keyboard._listener.blocking_hotkeys.values())) + self.assertEqual(keyboard._hotkeys, {}) + def test_add_hotkey_single_step_suppress_with_modifiers(self): + keyboard.add_hotkey('ctrl+shift+a', trigger, suppress=True) + self.do(d_ctrl+d_shift+d_a, triggered_event) + def test_add_hotkey_single_step_suppress_with_modifiers_fail_unrelated_modifier(self): + keyboard.add_hotkey('ctrl+shift+a', trigger, suppress=True) + self.do(d_ctrl+d_shift+u_shift+d_a, d_shift+u_shift+d_ctrl+d_a) + def test_add_hotkey_single_step_suppress_with_modifiers_fail_unrelated_key(self): + keyboard.add_hotkey('ctrl+shift+a', trigger, suppress=True) + self.do(d_ctrl+d_shift+du_b, d_shift+d_ctrl+du_b) + def test_add_hotkey_single_step_suppress_with_modifiers_unrelated_key(self): + keyboard.add_hotkey('ctrl+shift+a', trigger, suppress=True) + self.do(d_ctrl+d_shift+du_b+d_a, d_shift+d_ctrl+du_b+triggered_event) + def test_add_hotkey_single_step_suppress_with_modifiers_release(self): + keyboard.add_hotkey('ctrl+shift+a', trigger, suppress=True) + self.do(d_ctrl+d_shift+du_b+d_a+u_ctrl+u_shift, d_shift+d_ctrl+du_b+triggered_event+u_ctrl+u_shift) + def test_add_hotkey_single_step_suppress_with_modifiers_out_of_order(self): + keyboard.add_hotkey('ctrl+shift+a', trigger, suppress=True) + self.do(d_shift+d_ctrl+d_a, triggered_event) + def test_add_hotkey_single_step_suppress_with_modifiers_repeated(self): + keyboard.add_hotkey('ctrl+a', trigger, suppress=True) + self.do(d_ctrl+du_a+du_b+du_a, triggered_event+d_ctrl+du_b+triggered_event) + def test_add_hotkey_single_step_suppress_with_modifiers_release(self): + keyboard.add_hotkey('ctrl+a', trigger, suppress=True, trigger_on_release=True) + self.do(d_ctrl+du_a+du_b+du_a, triggered_event+d_ctrl+du_b+triggered_event) + def test_add_hotkey_single_step_suppress_with_modifier_superset_release(self): + keyboard.add_hotkey('ctrl+a', trigger, suppress=True, trigger_on_release=True) + self.do(d_ctrl+d_shift+du_a+u_shift+u_ctrl, d_ctrl+d_shift+du_a+u_shift+u_ctrl) + def test_add_hotkey_single_step_suppress_with_modifier_superset(self): + keyboard.add_hotkey('ctrl+a', trigger, suppress=True) + self.do(d_ctrl+d_shift+du_a+u_shift+u_ctrl, d_ctrl+d_shift+du_a+u_shift+u_ctrl) + def test_add_hotkey_single_step_timeout(self): + keyboard.add_hotkey('a', trigger, timeout=1, suppress=True) + self.do(du_a, triggered_event) + def test_add_hotkey_multi_step_first_timeout(self): + keyboard.add_hotkey('a, b', trigger, timeout=0.01, suppress=True) + time.sleep(0.03) + self.do(du_a+du_b, triggered_event) + def test_add_hotkey_multi_step_last_timeout(self): + keyboard.add_hotkey('a, b', trigger, timeout=0.01, suppress=True) + self.do(du_a, []) + time.sleep(0.05) + self.do(du_b, du_a+du_b) + def test_add_hotkey_multi_step_success_timeout(self): + keyboard.add_hotkey('a, b', trigger, timeout=0.05, suppress=True) + self.do(du_a, []) + time.sleep(0.01) + self.do(du_b, triggered_event) + def test_add_hotkey_multi_step_suffix_timeout(self): + keyboard.add_hotkey('a, b, a', trigger, timeout=0.01, suppress=True) + self.do(du_a+du_b, []) + time.sleep(0.05) + self.do(du_a, du_a+du_b) + self.do(du_b+du_a, triggered_event) + def test_add_hotkey_multi_step_allow(self): + keyboard.add_hotkey('a, b', lambda: trigger() or True, suppress=True) + self.do(du_a+du_b, triggered_event+du_a+du_b) + + def test_add_hotkey_single_step_nonsuppress(self): + queue = keyboard._queue.Queue() + keyboard.add_hotkey('ctrl+shift+a+b', lambda: queue.put(True), suppress=False) + self.do(d_shift+d_ctrl+d_a+d_b) + self.assertTrue(queue.get(timeout=0.5)) + def test_add_hotkey_single_step_nonsuppress_repeated(self): + queue = keyboard._queue.Queue() + keyboard.add_hotkey('ctrl+shift+a+b', lambda: queue.put(True), suppress=False) + self.do(d_shift+d_ctrl+d_a+d_b) + self.do(d_shift+d_ctrl+d_a+d_b) + self.assertTrue(queue.get(timeout=0.5)) + self.assertTrue(queue.get(timeout=0.5)) + def test_add_hotkey_single_step_nosuppress_with_modifiers_out_of_order(self): + queue = keyboard._queue.Queue() + keyboard.add_hotkey('ctrl+shift+a', lambda: queue.put(True), suppress=False) + self.do(d_shift+d_ctrl+d_a) + self.assertTrue(queue.get(timeout=0.5)) + def test_add_hotkey_single_step_suppress_regression_1(self): + keyboard.add_hotkey('a', trigger, suppress=True) + self.do(d_c+d_a+u_c+u_a, d_c+d_a+u_c+u_a) + + def test_remap_hotkey_single(self): + keyboard.remap_hotkey('a', 'b') + self.do(d_a+u_a, d_b+u_b) + def test_remap_hotkey_complex_dst(self): + keyboard.remap_hotkey('a', 'ctrl+b, c') + self.do(d_a+u_a, d_ctrl+du_b+u_ctrl+du_c) + def test_remap_hotkey_modifiers(self): + keyboard.remap_hotkey('ctrl+shift+a', 'b') + self.do(d_ctrl+d_shift+d_a+u_a, du_b) + def test_remap_hotkey_modifiers_repeat(self): + keyboard.remap_hotkey('ctrl+shift+a', 'b') + self.do(d_ctrl+d_shift+du_a+du_a, du_b+du_b) + def test_remap_hotkey_modifiers_state(self): + keyboard.remap_hotkey('ctrl+shift+a', 'b') + self.do(d_ctrl+d_shift+du_c+du_a+du_a, d_shift+d_ctrl+du_c+u_shift+u_ctrl+du_b+d_ctrl+d_shift+u_shift+u_ctrl+du_b+d_ctrl+d_shift) + def test_remap_hotkey_release_incomplete(self): + keyboard.remap_hotkey('a', 'b', trigger_on_release=True) + self.do(d_a, []) + def test_remap_hotkey_release_complete(self): + keyboard.remap_hotkey('a', 'b', trigger_on_release=True) + self.do(du_a, du_b) + + def test_parse_hotkey_combinations_scan_code(self): + self.assertEqual(keyboard.parse_hotkey_combinations(30), (((30,),),)) + def test_parse_hotkey_combinations_single(self): + self.assertEqual(keyboard.parse_hotkey_combinations('a'), (((1,),),)) + def test_parse_hotkey_combinations_single_modifier(self): + self.assertEqual(keyboard.parse_hotkey_combinations('shift+a'), (((1, 5), (1, 6)),)) + def test_parse_hotkey_combinations_single_modifiers(self): + self.assertEqual(keyboard.parse_hotkey_combinations('shift+ctrl+a'), (((1, 5, 7), (1, 6, 7)),)) + def test_parse_hotkey_combinations_multi(self): + self.assertEqual(keyboard.parse_hotkey_combinations('a, b'), (((1,),), ((2,),))) + def test_parse_hotkey_combinations_multi_modifier(self): + self.assertEqual(keyboard.parse_hotkey_combinations('shift+a, b'), (((1, 5), (1, 6)), ((2,),))) + def test_parse_hotkey_combinations_list_list(self): + self.assertEqual(keyboard.parse_hotkey_combinations(keyboard.parse_hotkey_combinations('a, b')), keyboard.parse_hotkey_combinations('a, b')) + def test_parse_hotkey_combinations_fail_empty(self): + with self.assertRaises(ValueError): + keyboard.parse_hotkey_combinations('') + + + def test_add_hotkey_multistep_suppress_incomplete(self): + keyboard.add_hotkey('a, b', trigger, suppress=True) + self.do(du_a, []) + self.assertEqual(keyboard._listener.blocking_hotkeys[(1,)], []) + self.assertEqual(len(keyboard._listener.blocking_hotkeys[(2,)]), 1) + def test_add_hotkey_multistep_suppress_incomplete(self): + keyboard.add_hotkey('a, b', trigger, suppress=True) + self.do(du_a+du_b, triggered_event) + def test_add_hotkey_multistep_suppress_modifier(self): + keyboard.add_hotkey('shift+a, b', trigger, suppress=True) + self.do(d_shift+du_a+u_shift+du_b, triggered_event) + def test_add_hotkey_multistep_suppress_fail(self): + keyboard.add_hotkey('a, b', trigger, suppress=True) + self.do(du_a+du_c, du_a+du_c) + def test_add_hotkey_multistep_suppress_three_steps(self): + keyboard.add_hotkey('a, b, c', trigger, suppress=True) + self.do(du_a+du_b+du_c, triggered_event) + def test_add_hotkey_multistep_suppress_repeated_prefix(self): + keyboard.add_hotkey('a, a, c', trigger, suppress=True, trigger_on_release=True) + self.do(du_a+du_a+du_c, triggered_event) + def test_add_hotkey_multistep_suppress_repeated_key(self): + keyboard.add_hotkey('a, b', trigger, suppress=True) + self.do(du_a+du_a+du_b, du_a+triggered_event) + self.assertEqual(keyboard._listener.blocking_hotkeys[(2,)], []) + self.assertEqual(len(keyboard._listener.blocking_hotkeys[(1,)]), 1) + def test_add_hotkey_multi_step_suppress_regression_1(self): + keyboard.add_hotkey('a, b', trigger, suppress=True) + self.do(d_c+d_a+u_c+u_a+du_c, d_c+d_a+u_c+u_a+du_c) + def test_add_hotkey_multi_step_suppress_replays(self): + keyboard.add_hotkey('a, b, c', trigger, suppress=True) + self.do(du_a+du_b+du_a+du_b+du_space, du_a+du_b+du_a+du_b+du_space) + + def test_add_word_listener_success(self): + queue = keyboard._queue.Queue() + def free(): + queue.put(1) + keyboard.add_word_listener('abc', free) + self.do(du_a+du_b+du_c+du_space) + self.assertTrue(queue.get(timeout=0.5)) + def test_add_word_listener_no_trigger_fail(self): + queue = keyboard._queue.Queue() + def free(): + queue.put(1) + keyboard.add_word_listener('abc', free) + self.do(du_a+du_b+du_c) + with self.assertRaises(keyboard._queue.Empty): + queue.get(timeout=0.01) + def test_add_word_listener_timeout_fail(self): + queue = keyboard._queue.Queue() + def free(): + queue.put(1) + keyboard.add_word_listener('abc', free, timeout=1) + self.do(du_a+du_b+du_c+[make_event(KEY_DOWN, name='space', time=2)]) + with self.assertRaises(keyboard._queue.Empty): + queue.get(timeout=0.01) + def test_duplicated_word_listener(self): + keyboard.add_word_listener('abc', trigger) + keyboard.add_word_listener('abc', trigger) + def test_add_word_listener_remove(self): + queue = keyboard._queue.Queue() + def free(): + queue.put(1) + keyboard.add_word_listener('abc', free) + keyboard.remove_word_listener('abc') + self.do(du_a+du_b+du_c+du_space) + with self.assertRaises(keyboard._queue.Empty): + queue.get(timeout=0.01) + def test_add_word_listener_suffix_success(self): + queue = keyboard._queue.Queue() + def free(): + queue.put(1) + keyboard.add_word_listener('abc', free, match_suffix=True) + self.do(du_a+du_a+du_b+du_c+du_space) + self.assertTrue(queue.get(timeout=0.5)) + def test_add_word_listener_suffix_fail(self): + queue = keyboard._queue.Queue() + def free(): + queue.put(1) + keyboard.add_word_listener('abc', free) + self.do(du_a+du_a+du_b+du_c) + with self.assertRaises(keyboard._queue.Empty): + queue.get(timeout=0.01) + + #def test_add_abbreviation(self): + # keyboard.add_abbreviation('abc', 'aaa') + # self.do(du_a+du_b+du_c+du_space, []) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_mouse_event.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_mouse_event.py new file mode 100644 index 0000000..38b8961 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_mouse_event.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from collections import namedtuple + +LEFT = 'left' +RIGHT = 'right' +MIDDLE = 'middle' +WHEEL = 'wheel' +X = 'x' +X2 = 'x2' + +UP = 'up' +DOWN = 'down' +DOUBLE = 'double' +VERTICAL = 'vertical' +HORIZONTAL = 'horizontal' + + +ButtonEvent = namedtuple('ButtonEvent', ['event_type', 'button', 'time']) +WheelEvent = namedtuple('WheelEvent', ['delta', 'time']) +MoveEvent = namedtuple('MoveEvent', ['x', 'y', 'time']) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_mouse_tests.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_mouse_tests.py new file mode 100644 index 0000000..6a2b2e4 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_mouse_tests.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +import unittest +import time + +from ._mouse_event import MoveEvent, ButtonEvent, WheelEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN, DOUBLE +from keyboard import mouse + +class FakeOsMouse(object): + def __init__(self): + self.append = None + self.position = (0, 0) + self.queue = None + self.init = lambda: None + + def listen(self, queue): + self.listening = True + self.queue = queue + + def press(self, button): + self.append((DOWN, button)) + + def release(self, button): + self.append((UP, button)) + + def get_position(self): + return self.position + + def move_to(self, x, y): + self.append(('move', (x, y))) + self.position = (x, y) + + def wheel(self, delta): + self.append(('wheel', delta)) + + def move_relative(self, x, y): + self.position = (self.position[0] + x, self.position[1] + y) + +class TestMouse(unittest.TestCase): + @staticmethod + def setUpClass(): + mouse._os_mouse= FakeOsMouse() + mouse._listener.start_if_necessary() + assert mouse._os_mouse.listening + + def setUp(self): + self.events = [] + mouse._pressed_events.clear() + mouse._os_mouse.append = self.events.append + + def tearDown(self): + mouse.unhook_all() + # Make sure there's no spill over between tests. + self.wait_for_events_queue() + + def wait_for_events_queue(self): + mouse._listener.queue.join() + + def flush_events(self): + self.wait_for_events_queue() + events = list(self.events) + # Ugly, but requried to work in Python2. Python3 has list.clear + del self.events[:] + return events + + def press(self, button=LEFT): + mouse._os_mouse.queue.put(ButtonEvent(DOWN, button, time.time())) + self.wait_for_events_queue() + + def release(self, button=LEFT): + mouse._os_mouse.queue.put(ButtonEvent(UP, button, time.time())) + self.wait_for_events_queue() + + def double_click(self, button=LEFT): + mouse._os_mouse.queue.put(ButtonEvent(DOUBLE, button, time.time())) + self.wait_for_events_queue() + + def click(self, button=LEFT): + self.press(button) + self.release(button) + + def wheel(self, delta=1): + mouse._os_mouse.queue.put(WheelEvent(delta, time.time())) + self.wait_for_events_queue() + + def move(self, x=0, y=0): + mouse._os_mouse.queue.put(MoveEvent(x, y, time.time())) + self.wait_for_events_queue() + + def test_hook(self): + events = [] + self.press() + mouse.hook(events.append) + self.press() + mouse.unhook(events.append) + self.press() + self.assertEqual(len(events), 1) + + def test_is_pressed(self): + self.assertFalse(mouse.is_pressed()) + self.press() + self.assertTrue(mouse.is_pressed()) + self.release() + self.press(X2) + self.assertFalse(mouse.is_pressed()) + + self.assertTrue(mouse.is_pressed(X2)) + self.press(X2) + self.assertTrue(mouse.is_pressed(X2)) + self.release(X2) + self.release(X2) + self.assertFalse(mouse.is_pressed(X2)) + + def test_buttons(self): + mouse.press() + self.assertEqual(self.flush_events(), [(DOWN, LEFT)]) + mouse.release() + self.assertEqual(self.flush_events(), [(UP, LEFT)]) + mouse.click() + self.assertEqual(self.flush_events(), [(DOWN, LEFT), (UP, LEFT)]) + mouse.double_click() + self.assertEqual(self.flush_events(), [(DOWN, LEFT), (UP, LEFT), (DOWN, LEFT), (UP, LEFT)]) + mouse.right_click() + self.assertEqual(self.flush_events(), [(DOWN, RIGHT), (UP, RIGHT)]) + mouse.click(RIGHT) + self.assertEqual(self.flush_events(), [(DOWN, RIGHT), (UP, RIGHT)]) + mouse.press(X2) + self.assertEqual(self.flush_events(), [(DOWN, X2)]) + + def test_position(self): + self.assertEqual(mouse.get_position(), mouse._os_mouse.get_position()) + + def test_move(self): + mouse.move(0, 0) + self.assertEqual(mouse._os_mouse.get_position(), (0, 0)) + mouse.move(100, 500) + self.assertEqual(mouse._os_mouse.get_position(), (100, 500)) + mouse.move(1, 2, False) + self.assertEqual(mouse._os_mouse.get_position(), (101, 502)) + + mouse.move(0, 0) + mouse.move(100, 499, True, duration=0.01) + self.assertEqual(mouse._os_mouse.get_position(), (100, 499)) + mouse.move(100, 1, False, duration=0.01) + self.assertEqual(mouse._os_mouse.get_position(), (200, 500)) + mouse.move(0, 0, False, duration=0.01) + self.assertEqual(mouse._os_mouse.get_position(), (200, 500)) + + def triggers(self, fn, events, **kwargs): + self.triggered = False + def callback(): + self.triggered = True + handler = fn(callback, **kwargs) + + for event_type, arg in events: + if event_type == DOWN: + self.press(arg) + elif event_type == UP: + self.release(arg) + elif event_type == DOUBLE: + self.double_click(arg) + elif event_type == 'WHEEL': + self.wheel() + + mouse._listener.remove_handler(handler) + return self.triggered + + def test_on_button(self): + self.assertTrue(self.triggers(mouse.on_button, [(DOWN, LEFT)])) + self.assertTrue(self.triggers(mouse.on_button, [(DOWN, RIGHT)])) + self.assertTrue(self.triggers(mouse.on_button, [(DOWN, X)])) + + self.assertFalse(self.triggers(mouse.on_button, [('WHEEL', '')])) + + self.assertFalse(self.triggers(mouse.on_button, [(DOWN, X)], buttons=MIDDLE)) + self.assertTrue(self.triggers(mouse.on_button, [(DOWN, MIDDLE)], buttons=MIDDLE)) + self.assertTrue(self.triggers(mouse.on_button, [(DOWN, MIDDLE)], buttons=MIDDLE)) + self.assertFalse(self.triggers(mouse.on_button, [(DOWN, MIDDLE)], buttons=MIDDLE, types=UP)) + self.assertTrue(self.triggers(mouse.on_button, [(UP, MIDDLE)], buttons=MIDDLE, types=UP)) + + self.assertTrue(self.triggers(mouse.on_button, [(UP, MIDDLE)], buttons=[MIDDLE, LEFT], types=[UP, DOWN])) + self.assertTrue(self.triggers(mouse.on_button, [(DOWN, LEFT)], buttons=[MIDDLE, LEFT], types=[UP, DOWN])) + self.assertFalse(self.triggers(mouse.on_button, [(UP, X)], buttons=[MIDDLE, LEFT], types=[UP, DOWN])) + + def test_ons(self): + self.assertTrue(self.triggers(mouse.on_click, [(UP, LEFT)])) + self.assertFalse(self.triggers(mouse.on_click, [(UP, RIGHT)])) + self.assertFalse(self.triggers(mouse.on_click, [(DOWN, LEFT)])) + self.assertFalse(self.triggers(mouse.on_click, [(DOWN, RIGHT)])) + + self.assertTrue(self.triggers(mouse.on_double_click, [(DOUBLE, LEFT)])) + self.assertFalse(self.triggers(mouse.on_double_click, [(DOUBLE, RIGHT)])) + self.assertFalse(self.triggers(mouse.on_double_click, [(DOWN, RIGHT)])) + + self.assertTrue(self.triggers(mouse.on_right_click, [(UP, RIGHT)])) + self.assertTrue(self.triggers(mouse.on_middle_click, [(UP, MIDDLE)])) + + def test_wait(self): + # If this fails it blocks. Unfortunately, but I see no other way of testing. + from threading import Thread, Lock + lock = Lock() + lock.acquire() + def t(): + mouse.wait() + lock.release() + Thread(target=t).start() + self.press() + lock.acquire() + + def test_record_play(self): + from threading import Thread, Lock + lock = Lock() + lock.acquire() + def t(): + self.recorded = mouse.record(RIGHT) + lock.release() + Thread(target=t).start() + self.click() + self.wheel(5) + self.move(100, 50) + self.press(RIGHT) + lock.acquire() + + self.assertEqual(len(self.recorded), 5) + self.assertEqual(self.recorded[0]._replace(time=None), ButtonEvent(DOWN, LEFT, None)) + self.assertEqual(self.recorded[1]._replace(time=None), ButtonEvent(UP, LEFT, None)) + self.assertEqual(self.recorded[2]._replace(time=None), WheelEvent(5, None)) + self.assertEqual(self.recorded[3]._replace(time=None), MoveEvent(100, 50, None)) + self.assertEqual(self.recorded[4]._replace(time=None), ButtonEvent(DOWN, RIGHT, None)) + + mouse.play(self.recorded, speed_factor=0) + events = self.flush_events() + self.assertEqual(len(events), 5) + self.assertEqual(events[0], (DOWN, LEFT)) + self.assertEqual(events[1], (UP, LEFT)) + self.assertEqual(events[2], ('wheel', 5)) + self.assertEqual(events[3], ('move', (100, 50))) + self.assertEqual(events[4], (DOWN, RIGHT)) + + mouse.play(self.recorded) + events = self.flush_events() + self.assertEqual(len(events), 5) + self.assertEqual(events[0], (DOWN, LEFT)) + self.assertEqual(events[1], (UP, LEFT)) + self.assertEqual(events[2], ('wheel', 5)) + self.assertEqual(events[3], ('move', (100, 50))) + self.assertEqual(events[4], (DOWN, RIGHT)) + + mouse.play(self.recorded, include_clicks=False) + events = self.flush_events() + self.assertEqual(len(events), 2) + self.assertEqual(events[0], ('wheel', 5)) + self.assertEqual(events[1], ('move', (100, 50))) + + mouse.play(self.recorded, include_moves=False) + events = self.flush_events() + self.assertEqual(len(events), 4) + self.assertEqual(events[0], (DOWN, LEFT)) + self.assertEqual(events[1], (UP, LEFT)) + self.assertEqual(events[2], ('wheel', 5)) + self.assertEqual(events[3], (DOWN, RIGHT)) + + mouse.play(self.recorded, include_wheel=False) + events = self.flush_events() + self.assertEqual(len(events), 4) + self.assertEqual(events[0], (DOWN, LEFT)) + self.assertEqual(events[1], (UP, LEFT)) + self.assertEqual(events[2], ('move', (100, 50))) + self.assertEqual(events[3], (DOWN, RIGHT)) + +if __name__ == '__main__': + unittest.main() diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_nixcommon.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_nixcommon.py new file mode 100644 index 0000000..a4d0d06 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_nixcommon.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +import struct +import os +import atexit +from time import time as now +from threading import Thread +from glob import glob +try: + from queue import Queue +except ImportError: + from Queue import Queue + +event_bin_format = 'llHHI' + +# Taken from include/linux/input.h +# https://www.kernel.org/doc/Documentation/input/event-codes.txt +EV_SYN = 0x00 +EV_KEY = 0x01 +EV_REL = 0x02 +EV_ABS = 0x03 +EV_MSC = 0x04 + +def make_uinput(): + if not os.path.exists('/dev/uinput'): + raise IOError('No uinput module found.') + + import fcntl, struct + + # Requires uinput driver, but it's usually available. + uinput = open("/dev/uinput", 'wb') + UI_SET_EVBIT = 0x40045564 + fcntl.ioctl(uinput, UI_SET_EVBIT, EV_KEY) + + UI_SET_KEYBIT = 0x40045565 + for i in range(256): + fcntl.ioctl(uinput, UI_SET_KEYBIT, i) + + BUS_USB = 0x03 + uinput_user_dev = "80sHHHHi64i64i64i64i" + axis = [0] * 64 * 4 + uinput.write(struct.pack(uinput_user_dev, b"Virtual Keyboard", BUS_USB, 1, 1, 1, 0, *axis)) + uinput.flush() # Without this you may get Errno 22: Invalid argument. + + UI_DEV_CREATE = 0x5501 + fcntl.ioctl(uinput, UI_DEV_CREATE) + UI_DEV_DESTROY = 0x5502 + #fcntl.ioctl(uinput, UI_DEV_DESTROY) + + return uinput + +class EventDevice(object): + def __init__(self, path): + self.path = path + self._input_file = None + self._output_file = None + + @property + def input_file(self): + if self._input_file is None: + try: + self._input_file = open(self.path, 'rb') + except IOError as e: + if e.strerror == 'Permission denied': + print('Permission denied ({}). You must be sudo to access global events.'.format(self.path)) + exit() + + def try_close(): + try: + self._input_file.close + except: + pass + atexit.register(try_close) + return self._input_file + + @property + def output_file(self): + if self._output_file is None: + self._output_file = open(self.path, 'wb') + atexit.register(self._output_file.close) + return self._output_file + + def read_event(self): + data = self.input_file.read(struct.calcsize(event_bin_format)) + seconds, microseconds, type, code, value = struct.unpack(event_bin_format, data) + return seconds + microseconds / 1e6, type, code, value, self.path + + def write_event(self, type, code, value): + integer, fraction = divmod(now(), 1) + seconds = int(integer) + microseconds = int(fraction * 1e6) + data_event = struct.pack(event_bin_format, seconds, microseconds, type, code, value) + + # Send a sync event to ensure other programs update. + sync_event = struct.pack(event_bin_format, seconds, microseconds, EV_SYN, 0, 0) + + self.output_file.write(data_event + sync_event) + self.output_file.flush() + +class AggregatedEventDevice(object): + def __init__(self, devices, output=None): + self.event_queue = Queue() + self.devices = devices + self.output = output or self.devices[0] + def start_reading(device): + while True: + self.event_queue.put(device.read_event()) + for device in self.devices: + thread = Thread(target=start_reading, args=[device]) + thread.setDaemon(True) + thread.start() + + def read_event(self): + return self.event_queue.get(block=True) + + def write_event(self, type, code, value): + self.output.write_event(type, code, value) + +import re +from collections import namedtuple +DeviceDescription = namedtuple('DeviceDescription', 'event_file is_mouse is_keyboard') +device_pattern = r"""N: Name="([^"]+?)".+?H: Handlers=([^\n]+)""" +def list_devices_from_proc(type_name): + try: + with open('/proc/bus/input/devices') as f: + description = f.read() + except FileNotFoundError: + return + + devices = {} + for name, handlers in re.findall(device_pattern, description, re.DOTALL): + path = '/dev/input/event' + re.search(r'event(\d+)', handlers).group(1) + if type_name in handlers: + yield EventDevice(path) + +def list_devices_from_by_id(name_suffix, by_id=True): + for path in glob('/dev/input/{}/*-event-{}'.format('by-id' if by_id else 'by-path', name_suffix)): + yield EventDevice(path) + +def aggregate_devices(type_name): + # Some systems have multiple keyboards with different range of allowed keys + # on each one, like a notebook with a "keyboard" device exclusive for the + # power button. Instead of figuring out which keyboard allows which key to + # send events, we create a fake device and send all events through there. + try: + uinput = make_uinput() + fake_device = EventDevice('uinput Fake Device') + fake_device._input_file = uinput + fake_device._output_file = uinput + except IOError as e: + import warnings + warnings.warn('Failed to create a device file using `uinput` module. Sending of events may be limited or unavailable depending on plugged-in devices.', stacklevel=2) + fake_device = None + + # We don't aggregate devices from different sources to avoid + # duplicates. + + devices_from_proc = list(list_devices_from_proc(type_name)) + if devices_from_proc: + return AggregatedEventDevice(devices_from_proc, output=fake_device) + + # breaks on mouse for virtualbox + # was getting /dev/input/by-id/usb-VirtualBox_USB_Tablet-event-mouse + devices_from_by_id = list(list_devices_from_by_id(type_name)) or list(list_devices_from_by_id(type_name, by_id=False)) + if devices_from_by_id: + return AggregatedEventDevice(devices_from_by_id, output=fake_device) + + # If no keyboards were found we can only use the fake device to send keys. + assert fake_device + return fake_device + + +def ensure_root(): + if os.geteuid() != 0: + raise ImportError('You must be root to use this library on linux.') diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_nixkeyboard.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_nixkeyboard.py new file mode 100644 index 0000000..d3950a1 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_nixkeyboard.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +import struct +import traceback +from time import time as now +from collections import namedtuple +from ._keyboard_event import KeyboardEvent, KEY_DOWN, KEY_UP +from ._canonical_names import all_modifiers, normalize_name +from ._nixcommon import EV_KEY, aggregate_devices, ensure_root + +# TODO: start by reading current keyboard state, as to not missing any already pressed keys. +# See: http://stackoverflow.com/questions/3649874/how-to-get-keyboard-state-in-linux + +def cleanup_key(name): + """ Formats a dumpkeys format to our standard. """ + name = name.lstrip('+') + is_keypad = name.startswith('KP_') + for mod in ('Meta_', 'Control_', 'dead_', 'KP_'): + if name.startswith(mod): + name = name[len(mod):] + + # Dumpkeys is weird like that. + if name == 'Remove': + name = 'Delete' + elif name == 'Delete': + name = 'Backspace' + + if name.endswith('_r'): + name = 'right ' + name[:-2] + if name.endswith('_l'): + name = 'left ' + name[:-2] + + + return normalize_name(name), is_keypad + +def cleanup_modifier(modifier): + modifier = normalize_name(modifier) + if modifier in all_modifiers: + return modifier + if modifier[:-1] in all_modifiers: + return modifier[:-1] + raise ValueError('Unknown modifier {}'.format(modifier)) + +""" +Use `dumpkeys --keys-only` to list all scan codes and their names. We +then parse the output and built a table. For each scan code and modifiers we +have a list of names and vice-versa. +""" +from subprocess import check_output +from collections import defaultdict +import re + +to_name = defaultdict(list) +from_name = defaultdict(list) +keypad_scan_codes = set() + +def register_key(key_and_modifiers, name): + if name not in to_name[key_and_modifiers]: + to_name[key_and_modifiers].append(name) + if key_and_modifiers not in from_name[name]: + from_name[name].append(key_and_modifiers) + +def build_tables(): + if to_name and from_name: return + ensure_root() + + modifiers_bits = { + 'shift': 1, + 'alt gr': 2, + 'ctrl': 4, + 'alt': 8, + } + keycode_template = r'^keycode\s+(\d+)\s+=(.*?)$' + dump = check_output(['dumpkeys', '--keys-only'], universal_newlines=True) + for str_scan_code, str_names in re.findall(keycode_template, dump, re.MULTILINE): + scan_code = int(str_scan_code) + for i, str_name in enumerate(str_names.strip().split()): + modifiers = tuple(sorted(modifier for modifier, bit in modifiers_bits.items() if i & bit)) + name, is_keypad = cleanup_key(str_name) + register_key((scan_code, modifiers), name) + if is_keypad: + keypad_scan_codes.add(scan_code) + register_key((scan_code, modifiers), 'keypad ' + name) + + # dumpkeys consistently misreports the Windows key, sometimes + # skipping it completely or reporting as 'alt. 125 = left win, + # 126 = right win. + if (125, ()) not in to_name or to_name[(125, ())] == 'alt': + register_key((125, ()), 'windows') + if (126, ()) not in to_name or to_name[(126, ())] == 'alt': + register_key((126, ()), 'windows') + + # The menu key is usually skipped altogether, so we also add it manually. + if (127, ()) not in to_name: + register_key((127, ()), 'menu') + + synonyms_template = r'^(\S+)\s+for (.+)$' + dump = check_output(['dumpkeys', '--long-info'], universal_newlines=True) + for synonym_str, original_str in re.findall(synonyms_template, dump, re.MULTILINE): + synonym, _ = cleanup_key(synonym_str) + original, _ = cleanup_key(original_str) + if synonym != original: + from_name[original].extend(from_name[synonym]) + from_name[synonym].extend(from_name[original]) + +device = None +def build_device(): + global device + if device: return + ensure_root() + device = aggregate_devices('kbd') + +def init(): + build_device() + build_tables() + +pressed_modifiers = set() + +def listen(callback): + build_device() + build_tables() + + while True: + time, type, code, value, device_id = device.read_event() + if type != EV_KEY: + continue + + scan_code = code + event_type = KEY_DOWN if value else KEY_UP # 0 = UP, 1 = DOWN, 2 = HOLD + + pressed_modifiers_tuple = tuple(sorted(pressed_modifiers)) + names = to_name[(scan_code, pressed_modifiers_tuple)] or to_name[(scan_code, ())] or ['unknown'] + name = names[0] + + if name in all_modifiers: + if event_type == KEY_DOWN: + pressed_modifiers.add(name) + else: + pressed_modifiers.discard(name) + + is_keypad = scan_code in keypad_scan_codes + callback(KeyboardEvent(event_type=event_type, scan_code=scan_code, name=name, time=time, device=device_id, is_keypad=is_keypad, modifiers=pressed_modifiers_tuple)) + +def write_event(scan_code, is_down): + build_device() + device.write_event(EV_KEY, scan_code, int(is_down)) + +def map_name(name): + build_tables() + for entry in from_name[name]: + yield entry + + parts = name.split(' ', 1) + if len(parts) > 1 and parts[0] in ('left', 'right'): + for entry in from_name[parts[1]]: + yield entry + +def press(scan_code): + write_event(scan_code, True) + +def release(scan_code): + write_event(scan_code, False) + +def type_unicode(character): + codepoint = ord(character) + hexadecimal = hex(codepoint)[len('0x'):] + + for key in ['ctrl', 'shift', 'u']: + scan_code, _ = next(map_name(key)) + press(scan_code) + + for key in hexadecimal: + scan_code, _ = next(map_name(key)) + press(scan_code) + release(scan_code) + + for key in ['ctrl', 'shift', 'u']: + scan_code, _ = next(map_name(key)) + release(scan_code) + +if __name__ == '__main__': + def p(e): + print(e) + listen(p) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_nixmouse.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_nixmouse.py new file mode 100644 index 0000000..6b02c57 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_nixmouse.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +import struct +from subprocess import check_output +import re +from ._nixcommon import EV_KEY, EV_REL, EV_MSC, EV_SYN, EV_ABS, aggregate_devices, ensure_root +from ._mouse_event import ButtonEvent, WheelEvent, MoveEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN + +import ctypes +import ctypes.util +from ctypes import c_uint32, c_uint, c_int, byref + +display = None +window = None +x11 = None +def build_display(): + global display, window, x11 + if display and window and x11: return + x11 = ctypes.cdll.LoadLibrary(ctypes.util.find_library('X11')) + # Required because we will have multiple threads calling x11, + # such as the listener thread and then main using "move_to". + x11.XInitThreads() + display = x11.XOpenDisplay(None) + # Known to cause segfault in Fedora 23 64bits, no known workarounds. + # http://stackoverflow.com/questions/35137007/get-mouse-position-on-linux-pure-python + window = x11.XDefaultRootWindow(display) + +def get_position(): + build_display() + root_id, child_id = c_uint32(), c_uint32() + root_x, root_y, win_x, win_y = c_int(), c_int(), c_int(), c_int() + mask = c_uint() + ret = x11.XQueryPointer(display, c_uint32(window), byref(root_id), byref(child_id), + byref(root_x), byref(root_y), + byref(win_x), byref(win_y), byref(mask)) + return root_x.value, root_y.value + +def move_to(x, y): + build_display() + x11.XWarpPointer(display, None, window, 0, 0, 0, 0, x, y) + x11.XFlush(display) + +REL_X = 0x00 +REL_Y = 0x01 +REL_Z = 0x02 +REL_HWHEEL = 0x06 +REL_WHEEL = 0x08 + +ABS_X = 0x00 +ABS_Y = 0x01 + +BTN_MOUSE = 0x110 +BTN_LEFT = 0x110 +BTN_RIGHT = 0x111 +BTN_MIDDLE = 0x112 +BTN_SIDE = 0x113 +BTN_EXTRA = 0x114 + +button_by_code = { + BTN_LEFT: LEFT, + BTN_RIGHT: RIGHT, + BTN_MIDDLE: MIDDLE, + BTN_SIDE: X, + BTN_EXTRA: X2, +} +code_by_button = {button: code for code, button in button_by_code.items()} + +device = None +def build_device(): + global device + if device: return + ensure_root() + device = aggregate_devices('mouse') +init = build_device + +def listen(queue): + build_device() + + while True: + time, type, code, value, device_id = device.read_event() + if type == EV_SYN or type == EV_MSC: + continue + + event = None + arg = None + + if type == EV_KEY: + event = ButtonEvent(DOWN if value else UP, button_by_code.get(code, '?'), time) + elif type == EV_REL: + value, = struct.unpack('i', struct.pack('I', value)) + + if code == REL_WHEEL: + event = WheelEvent(value, time) + elif code in (REL_X, REL_Y): + x, y = get_position() + event = MoveEvent(x, y, time) + + if event is None: + # Unknown event type. + continue + + queue.put(event) + +def press(button=LEFT): + build_device() + device.write_event(EV_KEY, code_by_button[button], 0x01) + +def release(button=LEFT): + build_device() + device.write_event(EV_KEY, code_by_button[button], 0x00) + +def move_relative(x, y): + build_device() + # Note relative events are not in terms of pixels, but millimeters. + if x < 0: + x += 2**32 + if y < 0: + y += 2**32 + device.write_event(EV_REL, REL_X, x) + device.write_event(EV_REL, REL_Y, y) + +def wheel(delta=1): + build_device() + if delta < 0: + delta += 2**32 + device.write_event(EV_REL, REL_WHEEL, delta) + + +if __name__ == '__main__': + #listen(print) + move_to(100, 200) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_winkeyboard.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_winkeyboard.py new file mode 100644 index 0000000..8e310a4 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_winkeyboard.py @@ -0,0 +1,620 @@ +# -*- coding: utf-8 -*- +""" +This is the Windows backend for keyboard events, and is implemented by +invoking the Win32 API through the ctypes module. This is error prone +and can introduce very unpythonic failure modes, such as segfaults and +low level memory leaks. But it is also dependency-free, very performant +well documented on Microsoft's website and scattered examples. + +# TODO: +- Keypad numbers still print as numbers even when numlock is off. +- No way to specify if user wants a keypad key or not in `map_char`. +""" +from __future__ import unicode_literals +import re +import atexit +import traceback +from threading import Lock +from collections import defaultdict + +from ._keyboard_event import KeyboardEvent, KEY_DOWN, KEY_UP +from ._canonical_names import normalize_name +try: + # Force Python2 to convert to unicode and not to str. + chr = unichr +except NameError: + pass + +# This part is just declaring Win32 API structures using ctypes. In C +# this would be simply #include "windows.h". + +import ctypes +from ctypes import c_short, c_char, c_uint8, c_int32, c_int, c_uint, c_uint32, c_long, Structure, CFUNCTYPE, POINTER +from ctypes.wintypes import WORD, DWORD, BOOL, HHOOK, MSG, LPWSTR, WCHAR, WPARAM, LPARAM, LONG, HMODULE, LPCWSTR, HINSTANCE, HWND +LPMSG = POINTER(MSG) +ULONG_PTR = POINTER(DWORD) + +kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) +GetModuleHandleW = kernel32.GetModuleHandleW +GetModuleHandleW.restype = HMODULE +GetModuleHandleW.argtypes = [LPCWSTR] + +#https://github.com/boppreh/mouse/issues/1 +#user32 = ctypes.windll.user32 +user32 = ctypes.WinDLL('user32', use_last_error = True) + +VK_PACKET = 0xE7 + +INPUT_MOUSE = 0 +INPUT_KEYBOARD = 1 +INPUT_HARDWARE = 2 + +KEYEVENTF_KEYUP = 0x02 +KEYEVENTF_UNICODE = 0x04 + +class KBDLLHOOKSTRUCT(Structure): + _fields_ = [("vk_code", DWORD), + ("scan_code", DWORD), + ("flags", DWORD), + ("time", c_int), + ("dwExtraInfo", ULONG_PTR)] + +# Included for completeness. +class MOUSEINPUT(ctypes.Structure): + _fields_ = (('dx', LONG), + ('dy', LONG), + ('mouseData', DWORD), + ('dwFlags', DWORD), + ('time', DWORD), + ('dwExtraInfo', ULONG_PTR)) + +class KEYBDINPUT(ctypes.Structure): + _fields_ = (('wVk', WORD), + ('wScan', WORD), + ('dwFlags', DWORD), + ('time', DWORD), + ('dwExtraInfo', ULONG_PTR)) + +class HARDWAREINPUT(ctypes.Structure): + _fields_ = (('uMsg', DWORD), + ('wParamL', WORD), + ('wParamH', WORD)) + +class _INPUTunion(ctypes.Union): + _fields_ = (('mi', MOUSEINPUT), + ('ki', KEYBDINPUT), + ('hi', HARDWAREINPUT)) + +class INPUT(ctypes.Structure): + _fields_ = (('type', DWORD), + ('union', _INPUTunion)) + +LowLevelKeyboardProc = CFUNCTYPE(c_int, WPARAM, LPARAM, POINTER(KBDLLHOOKSTRUCT)) + +SetWindowsHookEx = user32.SetWindowsHookExW +SetWindowsHookEx.argtypes = [c_int, LowLevelKeyboardProc, HINSTANCE , DWORD] +SetWindowsHookEx.restype = HHOOK + +CallNextHookEx = user32.CallNextHookEx +#CallNextHookEx.argtypes = [c_int , c_int, c_int, POINTER(KBDLLHOOKSTRUCT)] +CallNextHookEx.restype = c_int + +UnhookWindowsHookEx = user32.UnhookWindowsHookEx +UnhookWindowsHookEx.argtypes = [HHOOK] +UnhookWindowsHookEx.restype = BOOL + +GetMessage = user32.GetMessageW +GetMessage.argtypes = [LPMSG, HWND, c_uint, c_uint] +GetMessage.restype = BOOL + +TranslateMessage = user32.TranslateMessage +TranslateMessage.argtypes = [LPMSG] +TranslateMessage.restype = BOOL + +DispatchMessage = user32.DispatchMessageA +DispatchMessage.argtypes = [LPMSG] + + +keyboard_state_type = c_uint8 * 256 + +GetKeyboardState = user32.GetKeyboardState +GetKeyboardState.argtypes = [keyboard_state_type] +GetKeyboardState.restype = BOOL + +GetKeyNameText = user32.GetKeyNameTextW +GetKeyNameText.argtypes = [c_long, LPWSTR, c_int] +GetKeyNameText.restype = c_int + +MapVirtualKey = user32.MapVirtualKeyW +MapVirtualKey.argtypes = [c_uint, c_uint] +MapVirtualKey.restype = c_uint + +ToUnicode = user32.ToUnicode +ToUnicode.argtypes = [c_uint, c_uint, keyboard_state_type, LPWSTR, c_int, c_uint] +ToUnicode.restype = c_int + +SendInput = user32.SendInput +SendInput.argtypes = [c_uint, POINTER(INPUT), c_int] +SendInput.restype = c_uint + +# https://msdn.microsoft.com/en-us/library/windows/desktop/ms646307(v=vs.85).aspx +MAPVK_VK_TO_CHAR = 2 +MAPVK_VK_TO_VSC = 0 +MAPVK_VSC_TO_VK = 1 +MAPVK_VK_TO_VSC_EX = 4 +MAPVK_VSC_TO_VK_EX = 3 + +VkKeyScan = user32.VkKeyScanW +VkKeyScan.argtypes = [WCHAR] +VkKeyScan.restype = c_short + +LLKHF_INJECTED = 0x00000010 + +WM_KEYDOWN = 0x0100 +WM_KEYUP = 0x0101 +WM_SYSKEYDOWN = 0x104 # Used for ALT key +WM_SYSKEYUP = 0x105 + + +# This marks the end of Win32 API declarations. The rest is ours. + +keyboard_event_types = { + WM_KEYDOWN: KEY_DOWN, + WM_KEYUP: KEY_UP, + WM_SYSKEYDOWN: KEY_DOWN, + WM_SYSKEYUP: KEY_UP, +} + +# List taken from the official documentation, but stripped of the OEM-specific keys. +# Keys are virtual key codes, values are pairs (name, is_keypad). +official_virtual_keys = { + 0x03: ('control-break processing', False), + 0x08: ('backspace', False), + 0x09: ('tab', False), + 0x0c: ('clear', False), + 0x0d: ('enter', False), + 0x10: ('shift', False), + 0x11: ('ctrl', False), + 0x12: ('alt', False), + 0x13: ('pause', False), + 0x14: ('caps lock', False), + 0x15: ('ime kana mode', False), + 0x15: ('ime hanguel mode', False), + 0x15: ('ime hangul mode', False), + 0x17: ('ime junja mode', False), + 0x18: ('ime final mode', False), + 0x19: ('ime hanja mode', False), + 0x19: ('ime kanji mode', False), + 0x1b: ('esc', False), + 0x1c: ('ime convert', False), + 0x1d: ('ime nonconvert', False), + 0x1e: ('ime accept', False), + 0x1f: ('ime mode change request', False), + 0x20: ('spacebar', False), + 0x21: ('page up', False), + 0x22: ('page down', False), + 0x23: ('end', False), + 0x24: ('home', False), + 0x25: ('left', False), + 0x26: ('up', False), + 0x27: ('right', False), + 0x28: ('down', False), + 0x29: ('select', False), + 0x2a: ('print', False), + 0x2b: ('execute', False), + 0x2c: ('print screen', False), + 0x2d: ('insert', False), + 0x2e: ('delete', False), + 0x2f: ('help', False), + 0x30: ('0', False), + 0x31: ('1', False), + 0x32: ('2', False), + 0x33: ('3', False), + 0x34: ('4', False), + 0x35: ('5', False), + 0x36: ('6', False), + 0x37: ('7', False), + 0x38: ('8', False), + 0x39: ('9', False), + 0x41: ('a', False), + 0x42: ('b', False), + 0x43: ('c', False), + 0x44: ('d', False), + 0x45: ('e', False), + 0x46: ('f', False), + 0x47: ('g', False), + 0x48: ('h', False), + 0x49: ('i', False), + 0x4a: ('j', False), + 0x4b: ('k', False), + 0x4c: ('l', False), + 0x4d: ('m', False), + 0x4e: ('n', False), + 0x4f: ('o', False), + 0x50: ('p', False), + 0x51: ('q', False), + 0x52: ('r', False), + 0x53: ('s', False), + 0x54: ('t', False), + 0x55: ('u', False), + 0x56: ('v', False), + 0x57: ('w', False), + 0x58: ('x', False), + 0x59: ('y', False), + 0x5a: ('z', False), + 0x5b: ('left windows', False), + 0x5c: ('right windows', False), + 0x5d: ('applications', False), + 0x5f: ('sleep', False), + 0x60: ('0', True), + 0x61: ('1', True), + 0x62: ('2', True), + 0x63: ('3', True), + 0x64: ('4', True), + 0x65: ('5', True), + 0x66: ('6', True), + 0x67: ('7', True), + 0x68: ('8', True), + 0x69: ('9', True), + 0x6a: ('*', True), + 0x6b: ('+', True), + 0x6c: ('separator', True), + 0x6d: ('-', True), + 0x6e: ('decimal', True), + 0x6f: ('/', True), + 0x70: ('f1', False), + 0x71: ('f2', False), + 0x72: ('f3', False), + 0x73: ('f4', False), + 0x74: ('f5', False), + 0x75: ('f6', False), + 0x76: ('f7', False), + 0x77: ('f8', False), + 0x78: ('f9', False), + 0x79: ('f10', False), + 0x7a: ('f11', False), + 0x7b: ('f12', False), + 0x7c: ('f13', False), + 0x7d: ('f14', False), + 0x7e: ('f15', False), + 0x7f: ('f16', False), + 0x80: ('f17', False), + 0x81: ('f18', False), + 0x82: ('f19', False), + 0x83: ('f20', False), + 0x84: ('f21', False), + 0x85: ('f22', False), + 0x86: ('f23', False), + 0x87: ('f24', False), + 0x90: ('num lock', False), + 0x91: ('scroll lock', False), + 0xa0: ('left shift', False), + 0xa1: ('right shift', False), + 0xa2: ('left ctrl', False), + 0xa3: ('right ctrl', False), + 0xa4: ('left menu', False), + 0xa5: ('right menu', False), + 0xa6: ('browser back', False), + 0xa7: ('browser forward', False), + 0xa8: ('browser refresh', False), + 0xa9: ('browser stop', False), + 0xaa: ('browser search key', False), + 0xab: ('browser favorites', False), + 0xac: ('browser start and home', False), + 0xad: ('volume mute', False), + 0xae: ('volume down', False), + 0xaf: ('volume up', False), + 0xb0: ('next track', False), + 0xb1: ('previous track', False), + 0xb2: ('stop media', False), + 0xb3: ('play/pause media', False), + 0xb4: ('start mail', False), + 0xb5: ('select media', False), + 0xb6: ('start application 1', False), + 0xb7: ('start application 2', False), + 0xbb: ('+', False), + 0xbc: (',', False), + 0xbd: ('-', False), + 0xbe: ('.', False), + #0xbe:('/', False), # Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the '/?. + 0xe5: ('ime process', False), + 0xf6: ('attn', False), + 0xf7: ('crsel', False), + 0xf8: ('exsel', False), + 0xf9: ('erase eof', False), + 0xfa: ('play', False), + 0xfb: ('zoom', False), + 0xfc: ('reserved ', False), + 0xfd: ('pa1', False), + 0xfe: ('clear', False), +} + +tables_lock = Lock() +to_name = defaultdict(list) +from_name = defaultdict(list) +scan_code_to_vk = {} + +distinct_modifiers = [ + (), + ('shift',), + ('alt gr',), + ('num lock',), + ('shift', 'num lock'), + ('caps lock',), + ('shift', 'caps lock'), + ('alt gr', 'num lock'), +] + +name_buffer = ctypes.create_unicode_buffer(32) +unicode_buffer = ctypes.create_unicode_buffer(32) +keyboard_state = keyboard_state_type() +def get_event_names(scan_code, vk, is_extended, modifiers): + is_keypad = (scan_code, vk, is_extended) in keypad_keys + is_official = vk in official_virtual_keys + if is_keypad and is_official: + yield official_virtual_keys[vk][0] + + keyboard_state[0x10] = 0x80 * ('shift' in modifiers) + keyboard_state[0x11] = 0x80 * ('alt gr' in modifiers) + keyboard_state[0x12] = 0x80 * ('alt gr' in modifiers) + keyboard_state[0x14] = 0x01 * ('caps lock' in modifiers) + keyboard_state[0x90] = 0x01 * ('num lock' in modifiers) + keyboard_state[0x91] = 0x01 * ('scroll lock' in modifiers) + unicode_ret = ToUnicode(vk, scan_code, keyboard_state, unicode_buffer, len(unicode_buffer), 0) + if unicode_ret and unicode_buffer.value: + yield unicode_buffer.value + # unicode_ret == -1 -> is dead key + # ToUnicode has the side effect of setting global flags for dead keys. + # Therefore we need to call it twice to clear those flags. + # If your 6 and 7 keys are named "^6" and "^7", this is the reason. + ToUnicode(vk, scan_code, keyboard_state, unicode_buffer, len(unicode_buffer), 0) + + name_ret = GetKeyNameText(scan_code << 16 | is_extended << 24, name_buffer, 1024) + if name_ret and name_buffer.value: + yield name_buffer.value + + char = user32.MapVirtualKeyW(vk, MAPVK_VK_TO_CHAR) & 0xFF + if char != 0: + yield chr(char) + + if not is_keypad and is_official: + yield official_virtual_keys[vk][0] + +def _setup_name_tables(): + """ + Ensures the scan code/virtual key code/name translation tables are + filled. + """ + with tables_lock: + if to_name: return + + # Go through every possible scan code, and map them to virtual key codes. + # Then vice-versa. + all_scan_codes = [(sc, user32.MapVirtualKeyExW(sc, MAPVK_VSC_TO_VK_EX, 0)) for sc in range(0x100)] + all_vks = [(user32.MapVirtualKeyExW(vk, MAPVK_VK_TO_VSC_EX, 0), vk) for vk in range(0x100)] + for scan_code, vk in all_scan_codes + all_vks: + # `to_name` and `from_name` entries will be a tuple (scan_code, vk, extended, shift_state). + if (scan_code, vk, 0, 0, 0) in to_name: + continue + + if scan_code not in scan_code_to_vk: + scan_code_to_vk[scan_code] = vk + + # Brute force all combinations to find all possible names. + for extended in [0, 1]: + for modifiers in distinct_modifiers: + entry = (scan_code, vk, extended, modifiers) + # Get key names from ToUnicode, GetKeyNameText, MapVirtualKeyW and official virtual keys. + names = list(get_event_names(*entry)) + if names: + # Also map lowercased key names, but only after the properly cased ones. + lowercase_names = [name.lower() for name in names] + to_name[entry] = names + lowercase_names + # Remember the "id" of the name, as the first techniques + # have better results and therefore priority. + for i, name in enumerate(map(normalize_name, names + lowercase_names)): + from_name[name].append((i, entry)) + + # TODO: single quotes on US INTL is returning the dead key (?), and therefore + # not typing properly. + + # Alt gr is way outside the usual range of keys (0..127) and on my + # computer is named as 'ctrl'. Therefore we add it manually and hope + # Windows is consistent in its inconsistency. + for extended in [0, 1]: + for modifiers in distinct_modifiers: + to_name[(541, 162, extended, modifiers)] = ['alt gr'] + from_name['alt gr'].append((1, (541, 162, extended, modifiers))) + + modifiers_preference = defaultdict(lambda: 10) + modifiers_preference.update({(): 0, ('shift',): 1, ('alt gr',): 2, ('ctrl',): 3, ('alt',): 4}) + def order_key(line): + i, entry = line + scan_code, vk, extended, modifiers = entry + return modifiers_preference[modifiers], i, extended, vk, scan_code + for name, entries in list(from_name.items()): + from_name[name] = sorted(set(entries), key=order_key) + +# Called by keyboard/__init__.py +init = _setup_name_tables + +# List created manually. +keypad_keys = [ + # (scan_code, virtual_key_code, is_extended) + (126, 194, 0), + (126, 194, 0), + (28, 13, 1), + (28, 13, 1), + (53, 111, 1), + (53, 111, 1), + (55, 106, 0), + (55, 106, 0), + (69, 144, 1), + (69, 144, 1), + (71, 103, 0), + (71, 36, 0), + (72, 104, 0), + (72, 38, 0), + (73, 105, 0), + (73, 33, 0), + (74, 109, 0), + (74, 109, 0), + (75, 100, 0), + (75, 37, 0), + (76, 101, 0), + (76, 12, 0), + (77, 102, 0), + (77, 39, 0), + (78, 107, 0), + (78, 107, 0), + (79, 35, 0), + (79, 97, 0), + (80, 40, 0), + (80, 98, 0), + (81, 34, 0), + (81, 99, 0), + (82, 45, 0), + (82, 96, 0), + (83, 110, 0), + (83, 46, 0), +] + +shift_is_pressed = False +altgr_is_pressed = False +ignore_next_right_alt = False +shift_vks = set([0x10, 0xa0, 0xa1]) +def prepare_intercept(callback): + """ + Registers a Windows low level keyboard hook. The provided callback will + be invoked for each high-level keyboard event, and is expected to return + True if the key event should be passed to the next program, or False if + the event is to be blocked. + + No event is processed until the Windows messages are pumped (see + start_intercept). + """ + _setup_name_tables() + + def process_key(event_type, vk, scan_code, is_extended): + global shift_is_pressed, altgr_is_pressed, ignore_next_right_alt + #print(event_type, vk, scan_code, is_extended) + + # Pressing alt-gr also generates an extra "right alt" event + if vk == 0xA5 and ignore_next_right_alt: + ignore_next_right_alt = False + return True + + modifiers = ( + ('shift',) * shift_is_pressed + + ('alt gr',) * altgr_is_pressed + + ('num lock',) * (user32.GetKeyState(0x90) & 1) + + ('caps lock',) * (user32.GetKeyState(0x14) & 1) + + ('scroll lock',) * (user32.GetKeyState(0x91) & 1) + ) + entry = (scan_code, vk, is_extended, modifiers) + if entry not in to_name: + to_name[entry] = list(get_event_names(*entry)) + + names = to_name[entry] + name = names[0] if names else None + + # TODO: inaccurate when holding multiple different shifts. + if vk in shift_vks: + shift_is_pressed = event_type == KEY_DOWN + if scan_code == 541 and vk == 162: + ignore_next_right_alt = True + altgr_is_pressed = event_type == KEY_DOWN + + is_keypad = (scan_code, vk, is_extended) in keypad_keys + return callback(KeyboardEvent(event_type=event_type, scan_code=scan_code or -vk, name=name, is_keypad=is_keypad)) + + def low_level_keyboard_handler(nCode, wParam, lParam): + try: + vk = lParam.contents.vk_code + # Ignore the second `alt` DOWN observed in some cases. + fake_alt = (LLKHF_INJECTED | 0x20) + # Ignore events generated by SendInput with Unicode. + if vk != VK_PACKET and lParam.contents.flags & fake_alt != fake_alt: + event_type = keyboard_event_types[wParam] + is_extended = lParam.contents.flags & 1 + scan_code = lParam.contents.scan_code + should_continue = process_key(event_type, vk, scan_code, is_extended) + if not should_continue: + return -1 + except Exception as e: + print('Error in keyboard hook:') + traceback.print_exc() + + return CallNextHookEx(None, nCode, wParam, lParam) + + WH_KEYBOARD_LL = c_int(13) + keyboard_callback = LowLevelKeyboardProc(low_level_keyboard_handler) + handle = GetModuleHandleW(None) + thread_id = DWORD(0) + keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_callback, handle, thread_id) + + # Register to remove the hook when the interpreter exits. Unfortunately a + # try/finally block doesn't seem to work here. + atexit.register(UnhookWindowsHookEx, keyboard_callback) + +def listen(callback): + prepare_intercept(callback) + msg = LPMSG() + while not GetMessage(msg, 0, 0, 0): + TranslateMessage(msg) + DispatchMessage(msg) + +def map_name(name): + _setup_name_tables() + + entries = from_name.get(name) + if not entries: + raise ValueError('Key name {} is not mapped to any known key.'.format(repr(name))) + for i, entry in entries: + scan_code, vk, is_extended, modifiers = entry + yield scan_code or -vk, modifiers + +def _send_event(code, event_type): + if code == 541: + # Alt-gr is made of ctrl+alt. Just sending even 541 doesn't do anything. + user32.keybd_event(0x11, code, event_type, 0) + user32.keybd_event(0x12, code, event_type, 0) + elif code > 0: + vk = scan_code_to_vk.get(code, 0) + user32.keybd_event(vk, code, event_type, 0) + else: + # Negative scan code is a way to indicate we don't have a scan code, + # and the value actually contains the Virtual key code. + user32.keybd_event(-code, 0, event_type, 0) + +def press(code): + _send_event(code, 0) + +def release(code): + _send_event(code, 2) + +def type_unicode(character): + # This code and related structures are based on + # http://stackoverflow.com/a/11910555/252218 + surrogates = bytearray(character.encode('utf-16le')) + presses = [] + releases = [] + for i in range(0, len(surrogates), 2): + higher, lower = surrogates[i:i+2] + structure = KEYBDINPUT(0, (lower << 8) + higher, KEYEVENTF_UNICODE, 0, None) + presses.append(INPUT(INPUT_KEYBOARD, _INPUTunion(ki=structure))) + structure = KEYBDINPUT(0, (lower << 8) + higher, KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, 0, None) + releases.append(INPUT(INPUT_KEYBOARD, _INPUTunion(ki=structure))) + inputs = presses + releases + nInputs = len(inputs) + LPINPUT = INPUT * nInputs + pInputs = LPINPUT(*inputs) + cbSize = c_int(ctypes.sizeof(INPUT)) + SendInput(nInputs, pInputs, cbSize) + +if __name__ == '__main__': + _setup_name_tables() + import pprint + pprint.pprint(to_name) + pprint.pprint(from_name) + #listen(lambda e: print(e.to_json()) or True) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/_winmouse.py b/CLI/venv/lib/python3.12/site-packages/keyboard/_winmouse.py new file mode 100644 index 0000000..ef16dd4 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/_winmouse.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +import ctypes +import time +from ctypes import c_short, c_char, c_uint8, c_int32, c_int, c_uint, c_uint32, c_long, byref, Structure, CFUNCTYPE, POINTER +from ctypes.wintypes import DWORD, BOOL, HHOOK, MSG, LPWSTR, WCHAR, WPARAM, LPARAM +LPMSG = POINTER(MSG) + +import atexit + +from ._mouse_event import ButtonEvent, WheelEvent, MoveEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN, DOUBLE, WHEEL, HORIZONTAL, VERTICAL + +#https://github.com/boppreh/mouse/issues/1 +#user32 = ctypes.windll.user32 +user32 = ctypes.WinDLL('user32', use_last_error = True) + +class MSLLHOOKSTRUCT(Structure): + _fields_ = [("x", c_long), + ("y", c_long), + ('data', c_int32), + ('reserved', c_int32), + ("flags", DWORD), + ("time", c_int), + ] + +LowLevelMouseProc = CFUNCTYPE(c_int, WPARAM, LPARAM, POINTER(MSLLHOOKSTRUCT)) + +SetWindowsHookEx = user32.SetWindowsHookExA +#SetWindowsHookEx.argtypes = [c_int, LowLevelMouseProc, c_int, c_int] +SetWindowsHookEx.restype = HHOOK + +CallNextHookEx = user32.CallNextHookEx +#CallNextHookEx.argtypes = [c_int , c_int, c_int, POINTER(MSLLHOOKSTRUCT)] +CallNextHookEx.restype = c_int + +UnhookWindowsHookEx = user32.UnhookWindowsHookEx +UnhookWindowsHookEx.argtypes = [HHOOK] +UnhookWindowsHookEx.restype = BOOL + +GetMessage = user32.GetMessageW +GetMessage.argtypes = [LPMSG, c_int, c_int, c_int] +GetMessage.restype = BOOL + +TranslateMessage = user32.TranslateMessage +TranslateMessage.argtypes = [LPMSG] +TranslateMessage.restype = BOOL + +DispatchMessage = user32.DispatchMessageA +DispatchMessage.argtypes = [LPMSG] + +# Beware, as of 2016-01-30 the official docs have a very incomplete list. +# This one was compiled from experience and may be incomplete. +WM_MOUSEMOVE = 0x200 +WM_LBUTTONDOWN = 0x201 +WM_LBUTTONUP = 0x202 +WM_LBUTTONDBLCLK = 0x203 +WM_RBUTTONDOWN = 0x204 +WM_RBUTTONUP = 0x205 +WM_RBUTTONDBLCLK = 0x206 +WM_MBUTTONDOWN = 0x207 +WM_MBUTTONUP = 0x208 +WM_MBUTTONDBLCLK = 0x209 +WM_MOUSEWHEEL = 0x20A +WM_XBUTTONDOWN = 0x20B +WM_XBUTTONUP = 0x20C +WM_XBUTTONDBLCLK = 0x20D +WM_NCXBUTTONDOWN = 0x00AB +WM_NCXBUTTONUP = 0x00AC +WM_NCXBUTTONDBLCLK = 0x00AD +WM_MOUSEHWHEEL = 0x20E +WM_LBUTTONDOWN = 0x0201 +WM_LBUTTONUP = 0x0202 +WM_MOUSEMOVE = 0x0200 +WM_MOUSEWHEEL = 0x020A +WM_MOUSEHWHEEL = 0x020E +WM_RBUTTONDOWN = 0x0204 +WM_RBUTTONUP = 0x0205 + +buttons_by_wm_code = { + WM_LBUTTONDOWN: (DOWN, LEFT), + WM_LBUTTONUP: (UP, LEFT), + WM_LBUTTONDBLCLK: (DOUBLE, LEFT), + + WM_RBUTTONDOWN: (DOWN, RIGHT), + WM_RBUTTONUP: (UP, RIGHT), + WM_RBUTTONDBLCLK: (DOUBLE, RIGHT), + + WM_MBUTTONDOWN: (DOWN, MIDDLE), + WM_MBUTTONUP: (UP, MIDDLE), + WM_MBUTTONDBLCLK: (DOUBLE, MIDDLE), + + WM_XBUTTONDOWN: (DOWN, X), + WM_XBUTTONUP: (UP, X), + WM_XBUTTONDBLCLK: (DOUBLE, X), +} + +MOUSEEVENTF_ABSOLUTE = 0x8000 +MOUSEEVENTF_MOVE = 0x1 +MOUSEEVENTF_WHEEL = 0x800 +MOUSEEVENTF_HWHEEL = 0x1000 +MOUSEEVENTF_LEFTDOWN = 0x2 +MOUSEEVENTF_LEFTUP = 0x4 +MOUSEEVENTF_RIGHTDOWN = 0x8 +MOUSEEVENTF_RIGHTUP = 0x10 +MOUSEEVENTF_MIDDLEDOWN = 0x20 +MOUSEEVENTF_MIDDLEUP = 0x40 +MOUSEEVENTF_XDOWN = 0x0080 +MOUSEEVENTF_XUP = 0x0100 + +simulated_mouse_codes = { + (WHEEL, HORIZONTAL): MOUSEEVENTF_HWHEEL, + (WHEEL, VERTICAL): MOUSEEVENTF_WHEEL, + + (DOWN, LEFT): MOUSEEVENTF_LEFTDOWN, + (UP, LEFT): MOUSEEVENTF_LEFTUP, + + (DOWN, RIGHT): MOUSEEVENTF_RIGHTDOWN, + (UP, RIGHT): MOUSEEVENTF_RIGHTUP, + + (DOWN, MIDDLE): MOUSEEVENTF_MIDDLEDOWN, + (UP, MIDDLE): MOUSEEVENTF_MIDDLEUP, + + (DOWN, X): MOUSEEVENTF_XDOWN, + (UP, X): MOUSEEVENTF_XUP, +} + +NULL = c_int(0) + +WHEEL_DELTA = 120 + +init = lambda: None + +def listen(queue): + def low_level_mouse_handler(nCode, wParam, lParam): + struct = lParam.contents + # Can't use struct.time because it's usually zero. + t = time.time() + + if wParam == WM_MOUSEMOVE: + event = MoveEvent(struct.x, struct.y, t) + elif wParam == WM_MOUSEWHEEL: + event = WheelEvent(struct.data / (WHEEL_DELTA * (2<<15)), t) + elif wParam in buttons_by_wm_code: + type, button = buttons_by_wm_code.get(wParam, ('?', '?')) + if wParam >= WM_XBUTTONDOWN: + button = {0x10000: X, 0x20000: X2}[struct.data] + event = ButtonEvent(type, button, t) + + queue.put(event) + return CallNextHookEx(NULL, nCode, wParam, lParam) + + WH_MOUSE_LL = c_int(14) + mouse_callback = LowLevelMouseProc(low_level_mouse_handler) + mouse_hook = SetWindowsHookEx(WH_MOUSE_LL, mouse_callback, NULL, NULL) + + # Register to remove the hook when the interpreter exits. Unfortunately a + # try/finally block doesn't seem to work here. + atexit.register(UnhookWindowsHookEx, mouse_hook) + + msg = LPMSG() + while not GetMessage(msg, NULL, NULL, NULL): + TranslateMessage(msg) + DispatchMessage(msg) + +def _translate_button(button): + if button == X or button == X2: + return X, {X: 0x10000, X2: 0x20000}[button] + else: + return button, 0 + +def press(button=LEFT): + button, data = _translate_button(button) + code = simulated_mouse_codes[(DOWN, button)] + user32.mouse_event(code, 0, 0, data, 0) + +def release(button=LEFT): + button, data = _translate_button(button) + code = simulated_mouse_codes[(UP, button)] + user32.mouse_event(code, 0, 0, data, 0) + +def wheel(delta=1): + code = simulated_mouse_codes[(WHEEL, VERTICAL)] + user32.mouse_event(code, 0, 0, int(delta * WHEEL_DELTA), 0) + +def move_to(x, y): + user32.SetCursorPos(int(x), int(y)) + +def move_relative(x, y): + user32.mouse_event(MOUSEEVENTF_MOVE, int(x), int(y), 0, 0) + +class POINT(Structure): + _fields_ = [("x", c_long), ("y", c_long)] + +def get_position(): + point = POINT() + user32.GetCursorPos(byref(point)) + return (point.x, point.y) + +if __name__ == '__main__': + def p(e): + print(e) + listen(p) diff --git a/CLI/venv/lib/python3.12/site-packages/keyboard/mouse.py b/CLI/venv/lib/python3.12/site-packages/keyboard/mouse.py new file mode 100644 index 0000000..315199e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/keyboard/mouse.py @@ -0,0 +1,232 @@ +# -*- coding: utf-8 -*- +import warnings +warnings.simplefilter('always', DeprecationWarning) +warnings.warn('The mouse sub-library is deprecated and will be removed in future versions. Please use the standalone package `mouse`.', DeprecationWarning, stacklevel=2) + +import time as _time + +import platform as _platform +if _platform.system() == 'Windows': + from. import _winmouse as _os_mouse +elif _platform.system() == 'Linux': + from. import _nixmouse as _os_mouse +elif _platform.system() == 'Darwin': + from. import _darwinmouse as _os_mouse +else: + raise OSError("Unsupported platform '{}'".format(_platform.system())) + +from ._mouse_event import ButtonEvent, MoveEvent, WheelEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN, DOUBLE +from ._generic import GenericListener as _GenericListener + +_pressed_events = set() +class _MouseListener(_GenericListener): + def init(self): + _os_mouse.init() + def pre_process_event(self, event): + if isinstance(event, ButtonEvent): + if event.event_type in (UP, DOUBLE): + _pressed_events.discard(event.button) + else: + _pressed_events.add(event.button) + return True + + def listen(self): + _os_mouse.listen(self.queue) + +_listener = _MouseListener() + +def is_pressed(button=LEFT): + """ Returns True if the given button is currently pressed. """ + _listener.start_if_necessary() + return button in _pressed_events + +def press(button=LEFT): + """ Presses the given button (but doesn't release). """ + _os_mouse.press(button) + +def release(button=LEFT): + """ Releases the given button. """ + _os_mouse.release(button) + +def click(button=LEFT): + """ Sends a click with the given button. """ + _os_mouse.press(button) + _os_mouse.release(button) + +def double_click(button=LEFT): + """ Sends a double click with the given button. """ + click(button) + click(button) + +def right_click(): + """ Sends a right click with the given button. """ + click(RIGHT) + +def wheel(delta=1): + """ Scrolls the wheel `delta` clicks. Sign indicates direction. """ + _os_mouse.wheel(delta) + +def move(x, y, absolute=True, duration=0): + """ + Moves the mouse. If `absolute`, to position (x, y), otherwise move relative + to the current position. If `duration` is non-zero, animates the movement. + """ + x = int(x) + y = int(y) + + # Requires an extra system call on Linux, but `move_relative` is measured + # in millimiters so we would lose precision. + position_x, position_y = get_position() + + if not absolute: + x = position_x + x + y = position_y + y + + if duration: + start_x = position_x + start_y = position_y + dx = x - start_x + dy = y - start_y + + if dx == 0 and dy == 0: + _time.sleep(duration) + else: + # 120 movements per second. + # Round and keep float to ensure float division in Python 2 + steps = max(1.0, float(int(duration * 120.0))) + for i in range(int(steps)+1): + move(start_x + dx*i/steps, start_y + dy*i/steps) + _time.sleep(duration/steps) + else: + _os_mouse.move_to(x, y) + +def drag(start_x, start_y, end_x, end_y, absolute=True, duration=0): + """ + Holds the left mouse button, moving from start to end position, then + releases. `absolute` and `duration` are parameters regarding the mouse + movement. + """ + if is_pressed(): + release() + move(start_x, start_y, absolute, 0) + press() + move(end_x, end_y, absolute, duration) + release() + +def on_button(callback, args=(), buttons=(LEFT, MIDDLE, RIGHT, X, X2), types=(UP, DOWN, DOUBLE)): + """ Invokes `callback` with `args` when the specified event happens. """ + if not isinstance(buttons, (tuple, list)): + buttons = (buttons,) + if not isinstance(types, (tuple, list)): + types = (types,) + + def handler(event): + if isinstance(event, ButtonEvent): + if event.event_type in types and event.button in buttons: + callback(*args) + _listener.add_handler(handler) + return handler + +def on_click(callback, args=()): + """ Invokes `callback` with `args` when the left button is clicked. """ + return on_button(callback, args, [LEFT], [UP]) + +def on_double_click(callback, args=()): + """ + Invokes `callback` with `args` when the left button is double clicked. + """ + return on_button(callback, args, [LEFT], [DOUBLE]) + +def on_right_click(callback, args=()): + """ Invokes `callback` with `args` when the right button is clicked. """ + return on_button(callback, args, [RIGHT], [UP]) + +def on_middle_click(callback, args=()): + """ Invokes `callback` with `args` when the middle button is clicked. """ + return on_button(callback, args, [MIDDLE], [UP]) + +def wait(button=LEFT, target_types=(UP, DOWN, DOUBLE)): + """ + Blocks program execution until the given button performs an event. + """ + from threading import Lock + lock = Lock() + lock.acquire() + handler = on_button(lock.release, (), [button], target_types) + lock.acquire() + _listener.remove_handler(handler) + +def get_position(): + """ Returns the (x, y) mouse position. """ + return _os_mouse.get_position() + +def hook(callback): + """ + Installs a global listener on all available mouses, invoking `callback` + each time it is moved, a key status changes or the wheel is spun. A mouse + event is passed as argument, with type either `mouse.ButtonEvent`, + `mouse.WheelEvent` or `mouse.MoveEvent`. + + Returns the given callback for easier development. + """ + _listener.add_handler(callback) + return callback + +def unhook(callback): + """ + Removes a previously installed hook. + """ + _listener.remove_handler(callback) + +def unhook_all(): + """ + Removes all hooks registered by this application. Note this may include + hooks installed by high level functions, such as `record`. + """ + del _listener.handlers[:] + +def record(button=RIGHT, target_types=(DOWN,)): + """ + Records all mouse events until the user presses the given button. + Then returns the list of events recorded. Pairs well with `play(events)`. + + Note: this is a blocking function. + Note: for more details on the mouse hook and events see `hook`. + """ + recorded = [] + hook(recorded.append) + wait(button=button, target_types=target_types) + unhook(recorded.append) + return recorded + +def play(events, speed_factor=1.0, include_clicks=True, include_moves=True, include_wheel=True): + """ + Plays a sequence of recorded events, maintaining the relative time + intervals. If speed_factor is <= 0 then the actions are replayed as fast + as the OS allows. Pairs well with `record()`. + + The parameters `include_*` define if events of that type should be inluded + in the replay or ignored. + """ + last_time = None + for event in events: + if speed_factor > 0 and last_time is not None: + _time.sleep((event.time - last_time) / speed_factor) + last_time = event.time + + if isinstance(event, ButtonEvent) and include_clicks: + if event.event_type == UP: + _os_mouse.release(event.button) + else: + _os_mouse.press(event.button) + elif isinstance(event, MoveEvent) and include_moves: + _os_mouse.move_to(event.x, event.y) + elif isinstance(event, WheelEvent) and include_wheel: + _os_mouse.wheel(event.delta) + +replay = play +hold = press + +if __name__ == '__main__': + print('Recording... Double click to stop and replay.') + play(record()) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/COPYING.LGPL b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/COPYING.LGPL new file mode 100644 index 0000000..0df067b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/COPYING.LGPL @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007-2024 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/INSTALLER b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/METADATA b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/METADATA new file mode 100644 index 0000000..fecb69e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/METADATA @@ -0,0 +1,914 @@ +Metadata-Version: 2.1 +Name: pynput +Version: 1.8.1 +Summary: Monitor and control user input devices +Home-page: https://github.com/moses-palmer/pynput +Author: Moses Palmér +Author-email: moses.palmer@gmail.com +License: LGPLv3 +Keywords: control mouse,mouse input,control keyboard,keyboard input +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000 +Classifier: Operating System :: POSIX +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Monitoring +License-File: COPYING.LGPL +Requires-Dist: six +Requires-Dist: evdev>=1.3; "linux" in sys_platform +Requires-Dist: python-xlib>=0.17; "linux" in sys_platform +Requires-Dist: enum34; python_version == "2.7" +Requires-Dist: pyobjc-framework-ApplicationServices>=8.0; sys_platform == "darwin" +Requires-Dist: pyobjc-framework-Quartz>=8.0; sys_platform == "darwin" + +pynput +====== + +This library allows you to control and monitor input devices. + +Currently, mouse and keyboard input and monitoring are supported. + +See `here `_ for the full +documentation. + + +Controlling the mouse +--------------------- + +Use ``pynput.mouse.Controller`` like this:: + + from pynput.mouse import Button, Controller + + mouse = Controller() + + # Read pointer position + print('The current pointer position is {}'.format( + mouse.position)) + + # Set pointer position + mouse.position = (10, 20) + print('Now we have moved it to {}'.format( + mouse.position)) + + # Move pointer relative to current position + mouse.move(5, -5) + + # Press and release + mouse.press(Button.left) + mouse.release(Button.left) + + # Double click; this is different from pressing and releasing + # twice on macOS + mouse.click(Button.left, 2) + + # Scroll two steps down + mouse.scroll(0, 2) + + +Monitoring the mouse +-------------------- + +Use ``pynput.mouse.Listener`` like this:: + + from pynput import mouse + + def on_move(x, y, injected): + print('Pointer moved to {}; it was {}'.format( + (x, y, 'faked' if injected else 'not faked'))) + + def on_click(x, y, button, pressed, injected): + print('{} at {}; it was {}'.format( + 'Pressed' if pressed else 'Released', + (x, y, 'faked' if injected else 'not faked'))) + if not pressed: + # Stop listener + return False + + def on_scroll(x, y, dx, dy, injected): + print('Scrolled {} at {}; it was {}'.format( + 'down' if dy < 0 else 'up', + (x, y, 'faked' if injected else 'not faked'))) + + # Collect events until released + with mouse.Listener( + on_move=on_move, + on_click=on_click, + on_scroll=on_scroll) as listener: + listener.join() + + # ...or, in a non-blocking fashion: + listener = mouse.Listener( + on_move=on_move, + on_click=on_click, + on_scroll=on_scroll) + listener.start() + +A mouse listener is a ``threading.Thread``, and all callbacks will be invoked +from the thread. + +Call ``pynput.mouse.Listener.stop`` from anywhere, raise ``StopException`` or +return ``False`` from a callback to stop the listener. + +When using the non-blocking version above, the current thread will continue +executing. This might be necessary when integrating with other GUI frameworks +that incorporate a main-loop, but when run from a script, this will cause the +program to terminate immediately. + + +The mouse listener thread +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The listener callbacks are invoked directly from an operating thread on some +platforms, notably *Windows*. + +This means that long running procedures and blocking operations should not be +invoked from the callback, as this risks freezing input for all processes. + +A possible workaround is to just dispatch incoming messages to a queue, and let +a separate thread handle them. + + +Handling mouse listener errors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a callback handler raises an exception, the listener will be stopped. Since +callbacks run in a dedicated thread, the exceptions will not automatically be +reraised. + +To be notified about callback errors, call ``Thread.join`` on the listener +instance:: + + from pynput import mouse + + class MyException(Exception): pass + + def on_click(x, y, button, pressed): + if button == mouse.Button.left: + raise MyException(button) + + # Collect events until released + with mouse.Listener( + on_click=on_click) as listener: + try: + listener.join() + except MyException as e: + print('{} was clicked'.format(e.args[0])) + + +Toggling event listening for the mouse listener +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once ``pynput.mouse.Listener.stop`` has been called, the listener cannot be +restarted, since listeners are instances of ``threading.Thread``. + +If your application requires toggling listening events, you must either add an +internal flag to ignore events when not required, or create a new listener when +resuming listening. + + +Synchronous event listening for the mouse listener +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To simplify scripting, synchronous event listening is supported through the +utility class ``pynput.mouse.Events``. This class supports reading single +events in a non-blocking fashion, as well as iterating over all events. + +To read a single event, use the following code:: + + from pynput import mouse + + # The event listener will be running in this block + with mouse.Events() as events: + # Block at most one second + event = events.get(1.0) + if event is None: + print('You did not interact with the mouse within one second') + else: + print('Received event {}'.format(event)) + +To iterate over mouse events, use the following code:: + + from pynput import mouse + + # The event listener will be running in this block + with mouse.Events() as events: + for event in events: + if event.button == mouse.Button.right: + break + else: + print('Received event {}'.format(event)) + +Please note that the iterator method does not support non-blocking operation, +so it will wait for at least one mouse event. + +The events will be instances of the inner classes found in +``pynput.mouse.Events``. + + +Ensuring consistent coordinates between listener and controller on Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Recent versions of _Windows_ support running legacy applications scaled when +the system scaling has been increased beyond 100%. This allows old applications +to scale, albeit with a blurry look, and avoids tiny, unusable user interfaces. + +This scaling is unfortunately inconsistently applied to a mouse listener and a +controller: the listener will receive physical coordinates, but the controller +has to work with scaled coordinates. + +This can be worked around by telling Windows that your application is DPI +aware. This is a process global setting, so _pynput_ cannot do it +automatically. Do enable DPI awareness, run the following code:: + + import ctypes + + + PROCESS_PER_MONITOR_DPI_AWARE = 2 + + ctypes.windll.shcore.SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE) + + +Controlling the keyboard +------------------------ + +Use ``pynput.keyboard.Controller`` like this:: + + from pynput.keyboard import Key, Controller + + keyboard = Controller() + + # Press and release space + keyboard.press(Key.space) + keyboard.release(Key.space) + + # Type a lower case A; this will work even if no key on the + # physical keyboard is labelled 'A' + keyboard.press('a') + keyboard.release('a') + + # Type two upper case As + keyboard.press('A') + keyboard.release('A') + with keyboard.pressed(Key.shift): + keyboard.press('a') + keyboard.release('a') + + # Type 'Hello World' using the shortcut type method + keyboard.type('Hello World') + + +Monitoring the keyboard +----------------------- + +Use ``pynput.keyboard.Listener`` like this:: + + from pynput import keyboard + + def on_press(key, injected): + try: + print('alphanumeric key {} pressed; it was {}'.format( + key.char, 'faked' if injected else 'not faked')) + except AttributeError: + print('special key {} pressed'.format( + key)) + + def on_release(key, injected): + print('{} released; it was {}'.format( + key, 'faked' if injected else 'not faked')) + if key == keyboard.Key.esc: + # Stop listener + return False + + # Collect events until released + with keyboard.Listener( + on_press=on_press, + on_release=on_release) as listener: + listener.join() + + # ...or, in a non-blocking fashion: + listener = keyboard.Listener( + on_press=on_press, + on_release=on_release) + listener.start() + +A keyboard listener is a ``threading.Thread``, and all callbacks will be +invoked from the thread. + +Call ``pynput.keyboard.Listener.stop`` from anywhere, raise ``StopException`` +or return ``False`` from a callback to stop the listener. + +The ``key`` parameter passed to callbacks is a ``pynput.keyboard.Key``, for +special keys, a ``pynput.keyboard.KeyCode`` for normal alphanumeric keys, or +just ``None`` for unknown keys. + +When using the non-blocking version above, the current thread will continue +executing. This might be necessary when integrating with other GUI frameworks +that incorporate a main-loop, but when run from a script, this will cause the +program to terminate immediately. + + +The keyboard listener thread +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The listener callbacks are invoked directly from an operating thread on some +platforms, notably *Windows*. + +This means that long running procedures and blocking operations should not be +invoked from the callback, as this risks freezing input for all processes. + +A possible workaround is to just dispatch incoming messages to a queue, and let +a separate thread handle them. + + +Handling keyboard listener errors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a callback handler raises an exception, the listener will be stopped. Since +callbacks run in a dedicated thread, the exceptions will not automatically be +reraised. + +To be notified about callback errors, call ``Thread.join`` on the listener +instance:: + + from pynput import keyboard + + class MyException(Exception): pass + + def on_press(key): + if key == keyboard.Key.esc: + raise MyException(key) + + # Collect events until released + with keyboard.Listener( + on_press=on_press) as listener: + try: + listener.join() + except MyException as e: + print('{} was pressed'.format(e.args[0])) + + +Toggling event listening for the keyboard listener +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once ``pynput.keyboard.Listener.stop`` has been called, the listener cannot be +restarted, since listeners are instances of ``threading.Thread``. + +If your application requires toggling listening events, you must either add an +internal flag to ignore events when not required, or create a new listener when +resuming listening. + + +Synchronous event listening for the keyboard listener +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To simplify scripting, synchronous event listening is supported through the +utility class ``pynput.keyboard.Events``. This class supports reading single +events in a non-blocking fashion, as well as iterating over all events. + +To read a single event, use the following code:: + + from pynput import keyboard + + # The event listener will be running in this block + with keyboard.Events() as events: + # Block at most one second + event = events.get(1.0) + if event is None: + print('You did not press a key within one second') + else: + print('Received event {}'.format(event)) + +To iterate over keyboard events, use the following code:: + + from pynput import keyboard + + # The event listener will be running in this block + with keyboard.Events() as events: + for event in events: + if event.key == keyboard.Key.esc: + break + else: + print('Received event {}'.format(event)) + +Please note that the iterator method does not support non-blocking operation, +so it will wait for at least one keyboard event. + +The events will be instances of the inner classes found in +``pynput.keyboard.Events``. + + +Global hotkeys +~~~~~~~~~~~~~~ + +A common use case for keyboard monitors is reacting to global hotkeys. Since a +listener does not maintain any state, hotkeys involving multiple keys must +store this state somewhere. + +*pynput* provides the class ``pynput.keyboard.HotKey`` for this purpose. It +contains two methods to update the state, designed to be easily interoperable +with a keyboard listener: ``pynput.keyboard.HotKey.press`` and +``pynput.keyboard.HotKey.release`` which can be directly passed as listener +callbacks. + +The intended usage is as follows:: + + from pynput import keyboard + + def on_activate(): + print('Global hotkey activated!') + + def for_canonical(f): + return lambda k: f(l.canonical(k)) + + hotkey = keyboard.HotKey( + keyboard.HotKey.parse('++h'), + on_activate) + with keyboard.Listener( + on_press=for_canonical(hotkey.press), + on_release=for_canonical(hotkey.release)) as l: + l.join() + +This will create a hotkey, and then use a listener to update its state. Once +all the specified keys are pressed simultaneously, ``on_activate`` will be +invoked. + +Note that keys are passed through ``pynput.keyboard.Listener.canonical`` before +being passed to the ``HotKey`` instance. This is to remove any modifier state +from the key events, and to normalise modifiers with more than one physical +button. + +The method ``pynput.keyboard.HotKey.parse`` is a convenience function to +transform shortcut strings to key collections. Please see its documentation for +more information. + +To register a number of global hotkeys, use the convenience class +``pynput.keyboard.GlobalHotKeys``:: + + from pynput import keyboard + + def on_activate_h(): + print('++h pressed') + + def on_activate_i(): + print('++i pressed') + + with keyboard.GlobalHotKeys({ + '++h': on_activate_h, + '++i': on_activate_i}) as h: + h.join() + + +Release Notes +============= + +v1.8.1 (2025-03-17) - Various fixes +----------------------------------- +* Remove incorrectly merged line for the *Xorg* backend. Thanks to *sphh*! +* Let events know about the new ``injected`` parameter. Thanks to + *phpjunkie420*! + + +v1.8.0 (2025-03-03) - Allow detecting injected events +----------------------------------------------------- +* Add a flag to callbacks to allow detecting injected input events. +* Add ``media_stop`` key for *macOS*. Thanks to *laura-3*! +* Add ``eject`` key for *macOS*. Thanks to *DiMNDev*! + + +v1.7.8 (2025-02-28) - Fixes for Python 3.12 +------------------------------------------- +* Rename method for listeners to not conflict with new ``threading.Thread`` + field. + + +v1.7.7 (2024-05-10) - Various fixes +----------------------------------- +* Small corrections to the documentation. +* Handle explicit timeout when calling ``join`` on listeners. +* Correct regression in hot key handling for special keys. +* Reverted changes to lazy loading of ``CoreFoundation`` and ``Quartz``, since + this still does not appear to work. Thanks to *Zach Zaiman*! +* Let the type of values in ``Key`` be ``KeyCode`` so that type checkers are + not confused. Thanks to *Amund Eggen Svandal*! +* Do not crash in ``__del__`` on *Xorg* if display creation fails. Thanks to + *Gabriele Pongelli*! +* Correct support for emojis on *Windows*. Thanks to *Yunus Emre*! + + +v1.7.6 (2022-01-01) - Various fixes +----------------------------------- +* Allow passing virtual key codes to the parser for global hot keys. +* Stop the recording context asynchronously on *Xorg*. +* Do not pass ``None`` to ``objc.objc_object``. Thanks to *yejunxi*! +* Do not crash when pressing the *alt* key on *uinput*. Thanks to *Caldas + Lopes*! +* Use the correct option prefix for listeners derived from the backend + implementations. Thanks to *Yu Wang*! + + +v1.7.5 (2021-11-19) - Various fixes +----------------------------------- +* Corrected crashes on *Xorg* when a listener was configured to suppress + system events. Thanks to *jpramosi*! +* Improved handling of keyboard controller on *Windows*. The controller now + has a greater change of working with applications using lower level events. + Thanks to *bhudax*! +* Updated *macOS* implementation to use new version of *pyobjc*. + + +v1.7.4 (2021-10-10) - Various fixes +----------------------------------- +* Detect whether permissions are lacking on *macOS*. Thanks to *Dane Finlay*! +* Eagerly import symbols from ``CoreFoundation`` and ``Quartz``. Thanks to + *Ronald Oussoren*! +* Improved handling of ``dumpkeys`` utility. Thanks to *Markus Niedermann*! +* Removed ambiguous license file. + + +v1.7.3 (2021-02-10) - Various fixes +----------------------------------- +* Corrected *keysym* handling on *Xorg*; not all groups were loaded, and the + fallback to our internal tables was never triggered. Thanks to *Philipp + Klaus*! +* Updated the version of *Quartz* used for the *macOS* backend to allow + *pynput* to be installed on *Big Sur*. Thanks to *Michael Madden*! +* Added missing function keys on *Windows*. Thanks to *Dave Atkinson*! +* Corrected scroll speed for mouse controller on *macOS*. Thanks to *Albert + Zeyer*! +* Corrected media keys for *Xorg*. Thanks to *Gabriele N. Tornetta*! +* Corrected parameter name in documentation. Thanks to *Jinesi Yelizati*! + + +v1.7.2 (2020-12-21) - Corrected uinput key mapping +-------------------------------------------------- +* Corrected mapping of virtual key codes to characters for the *uinput* + backend. +* Corrected spelling errors. Thanks to *Martin Michlmayr*! +* Corrected and improved documentation. + + +v1.7.1 (2020-08-30) - Corrected release notes +--------------------------------------------- +* Corrected thanks for arbitrary unicode character support for *Xorg*. + + +v1.7.0 (2020-08-30) - A new backend and many new features and bug fixes +----------------------------------------------------------------------- +* Added a new *uinput* based keyboard backend for *Linux*, when no *X* server + is available. +* Allow typing arbitrary unicode characters on *Xorg* backend. Thanks to + *gdiShun*! +* Allow overriding the automatically selected backend with an environment + variable, and added a dummy backend. +* Added support for mouse side button on *Windows*. Thanks to *danielkovarik*! +* Added convenience method to tap keys. +* Allow specifying raw virtual key codes in hotkeys. +* Improved error messages when a backend cannot be loaded. +* Include more information in stringification of events. +* Corrected return value of ``Events.get`` to that specified by the + documentation. +* Corrected keyboard listener not to type random characters on certain + keyboard layouts. +* Corrected errors when pressing certain keys on *Windows*, where the + operating system reports that they are dead but no combining version exists. +* Improved documentation. + + +v1.6.8 (2020-02-28) - Various fixes +----------------------------------- +* Updated documentation. +* Corrected lint warnings and tests. +* Do not use internal types in ``argtypes`` for ``win32`` functions; this + renders them uncallable for other code running in the same runtime. +* Include scan codes in events on *Windows*. Thanks to *bhudax*! +* Correctly apply transformation to scroll event values on *Windows*. Thanks + to *DOCCA0*! + + +v1.6.7 (2020-02-17) - Various fixes +----------------------------------- +* Corrected infinite scrolling on *macOS* when providing non-integer deltas. + Thanks to *Iván Munsuri Ibáñez*! +* Corrected controller and listener handling of media keys on *macOS*. Thanks + to *Iván Munsuri Ibáñez*! + + +v1.6.6 (2020-01-23) - Corrected hot key documentation +----------------------------------------------------- +* The code examples for the simple ``pynput.keyboard.HotKey`` now work. Thanks + to *jfongattw*! + + +v1.6.5 (2020-01-08) - Corrected media key mappings +-------------------------------------------------- +* Corrected media key mappings on *macOS*. Thanks to *Luis Nachtigall*! + + +v1.6.4 (2020-01-03) - Corrected imports yet again +------------------------------------------------- +* Corrected imports for keyboard Controller. Thanks to *rhystedstone*! + + +v1.6.3 (2019-12-28) - Corrected imports again +--------------------------------------------- +* Corrected imports for keyboard Controller. Thanks to *Matt Iversen*! + + +v1.6.2 (2019-12-28) - Corrected imports +--------------------------------------- +* Corrected imports for keyboard Controller. Thanks to *Matt Iversen*! + + +v1.6.1 (2019-12-27) - Corrections for *Windows* +----------------------------------------------- +* Corrected global hotkeys on *Windows*. +* Corrected pressed / released state for keyboard listener on *Windows*. + Thanks to *segalion*! + +v1.6.0 (2019-12-11) - Global Hotkeys +------------------------------------ +* Added support for global hotkeys. +* Added support for streaming listener events synchronously. + + +v1.5.2 (2019-12-06) - Corrected media key names for *Xorg* +---------------------------------------------------------- +* Removed media flag from *Xorg* keys. + + +v1.5.1 (2019-12-06) - Corrected media key names for *macOS* +----------------------------------------------------------- +* Corrected attribute names for media keys on *macOS*. Thanks to *ah3243*! + + +v1.5.0 (2019-12-04) - Various improvements +------------------------------------------ +* Corrected keyboard listener on *Windows*. Thanks to *akiratakasaki*, + *segalion*, *SpecialCharacter*! +* Corrected handling of some special keys, including arrow keys, when combined + with modifiers on *Windows*. Thanks to *tuessetr*! +* Updated documentation to include information about DPI scaling on *Windows*. + Thanks to *david-szarka*! +* Added experimental support for media keys. Thanks to *ShivamJoker*, + *StormTersteeg*! + + +v1.4.5 (2019-11-05) - Corrected errors on *Python 3.8* +------------------------------------------------------ +* Corrected errors about using `in` operator for enums on *Python 3.8* on + *macOS*. + + +v1.4.4 (2019-09-24) - Actually corrected keyboard listener on macOS +------------------------------------------------------------------- +* Included commit to correctly fall back on + ``CGEventKeyboardGetUnicodeString``. +* Corrected deprecation warnings about ``Enum`` usage on *Python 3.8*. + + +v1.4.3 (2019-09-24) - Corrected keyboard listener on macOS again +---------------------------------------------------------------- +* Correctly fall back on ``CGEventKeyboardGetUnicodeString``. +* Updated documentation. + + +v1.4.2 (2019-03-22) - Corrected keyboard listener on macOS +---------------------------------------------------------- +* Use ``CGEventKeyboardGetUnicodeString`` in *macOS* keyboard listener to send + correct characters. +* Include keysym instead of key code in *Xorg* keyboard listener. +* Corrected logging to not include expected ``StopException``. +* Updated and corrected documentation. + + +v1.4.1 (2018-09-07) - Logging +----------------------------- +* Log unhandled exceptions raised by listener callbacks. + + +v1.4 (2018-07-03) - Event suppression +------------------------------------- +* Added possibility to fully suppress events when listening. +* Added support for typing some control characters. +* Added support for mouse drag events on *OSX*. Thanks to *jungledrum*! +* Include the key code in keyboard listener events. +* Correctly handle the numeric key pad on *Xorg* with *num lock* active. + Thanks to *TheoRet*! +* Corrected handling of current thread keyboard layout on *Windows*. Thanks to + *Schmettaling*! +* Corrected stopping of listeners on *Xorg*. +* Corrected import of ``Xlib.keysymdef.xkb`` on *Xorg*. Thanks to *Glandos*! + + +v1.3.10 (2018-02-05) - Do not crash under *Xephyr* +-------------------------------------------------- +* Do not crash when ``Xlib.display.Display.get_input_focus`` returns an + integer, as it may when running under *Xephyr*. Thanks to *Eli Skeggs*! + + +v1.3.9 (2018-01-12) - Correctly handle the letter *A* on *OSX* +-------------------------------------------------------------- +* Corrected check for virtual key code when generating keyboard events on + *OSX*. This fixes an issue where pressing *A* with *shift* explicitly pressed + would still type a minuscule letter. + + +v1.3.8 (2017-12-08) - Do not crash on some keyboard layouts on *OSX* +-------------------------------------------------------------------- +* Fall back on a different method to retrieve the keyboard layout on *OSX*. + This helps for some keyboard layouts, such as *Chinese*. Thanks to + *haoflynet*! + + +v1.3.7 (2017-08-23) - *Xorg* corrections +---------------------------------------- +* Include mouse buttons up to *30* for *Xorg*. + + +v1.3.6 (2017-08-13) - *win32* corrections +----------------------------------------- +* Corrected double delivery of fake keyboard events on *Windows*. +* Corrected handling of synthetic unicode keys on *Windows*. + + +v1.3.5 (2017-06-07) - Corrected dependencies again +-------------------------------------------------- +* Reverted changes in *1.3.3*. +* Corrected platform specifier for *Python 2* on *Linux*. + + +v1.3.4 (2017-06-05) - *Xorg* corrections +---------------------------------------- +* Corrected bounds check for values on *Xorg*. + + +v1.3.3 (2017-06-05) - Make dependencies non-optional +---------------------------------------------------- +* Made platform dependencies non-optional. + + +v1.3.2 (2017-05-15) - Fix for button click on Mac +------------------------------------------------- +* Corrected regression from previous release where button clicks would + crash the *Mac* mouse listener. + + +v1.3.1 (2017-05-12) - Fixes for unknown buttons on Linux +-------------------------------------------------------- +* Fall back on `Button.unknown` for unknown mouse buttons in *Xorg* mouse + listener. + + +v1.3 (2017-04-10) - Platform specific features +---------------------------------------------- +* Added ability to stop event propagation on *Windows*. This will prevent + events from reaching other applications. +* Added ability to ignore events on *Windows*. This is a workaround for systems + where the keyboard monitor interferes with normal keyboard events. +* Added ability to modify events on *OSX*. This allows intercepting and + altering input events before they reach other applications. +* Corrected crash on *OSX* when some types of third party input sources are + installed. + + +v1.2 (2017-01-06) - Improved error handling +------------------------------------------- +* Allow catching exceptions thrown from listener callbacks. This changes the + API, as joining a listener now potentially raises unhandled exceptions, + and unhandled exceptions will stop listeners. +* Added support for the numeric keypad on *Linux*. +* Improved documentation. +* Thanks to *jollysean* and *gilleswijnker* for their input! + + +v1.1.7 (2017-01-02) - Handle middle button on Windows +----------------------------------------------------- +* Listen for and dispatch middle button mouse clicks on *Windows*. + + +v1.1.6 (2016-11-24) - Corrected context manager for pressing keys +----------------------------------------------------------------- +* Corrected bug in ``pynput.keyboard.Controller.pressed`` which caused it to + never release the key. Many thanks to Toby Southwell! + + +v1.1.5 (2016-11-17) - Corrected modifier key combinations on Linux +------------------------------------------------------------------ +* Corrected handling of modifier keys to allow them to be composable on + *Linux*. + + +v1.1.4 (2016-10-30) - Small bugfixes +------------------------------------ +* Corrected error generation when ``GetKeyboardState`` fails. +* Make sure to apply shift state to borrowed keys on *X*. +* Use *pylint*. + + +v1.1.3 (2016-09-27) - Changed Xlib backend library +-------------------------------------------------- +* Changed *Xlib* library. + + +v1.1.2 (2016-09-26) - Added missing type for Python 2 +----------------------------------------------------- +* Added missing ``LPDWORD`` for *Python 2* on *Windows*. + + +v1.1.1 (2016-09-26) - Fixes for listeners and controllers on Windows +-------------------------------------------------------------------- +* Corrected keyboard listener on *Windows*. Modifier keys and other keys + changing the state of the keyboard are now handled correctly. +* Corrected mouse click and release on *Windows*. +* Corrected code samples. + + +v1.1 (2016-06-22) - Simplified usage on Linux +--------------------------------------------- +* Propagate import errors raised on Linux to help troubleshoot missing + ``Xlib`` module. +* Declare ``python3-xlib`` as dependency on *Linux* for *Python 3*. + + +v1.0.6 (2016-04-19) - Universal wheel +------------------------------------- +* Make sure to build a universal wheel for all python versions. + + +v1.0.5 (2016-04-11) - Fixes for dragging on OSX +----------------------------------------------- +* Corrected dragging on *OSX*. +* Added scroll speed constant for *OSX* to correct slow scroll speed. + + +v1.0.4 (2016-04-11) - Fixes for clicking and scrolling on Windows +----------------------------------------------------------------- +* Corrected name of mouse input field when sending click and scroll events. + + +v1.0.3 (2016-04-05) - Fixes for Python 3 on Windows +--------------------------------------------------- +* Corrected use of ``ctypes`` on Windows. + + +v1.0.2 (2016-04-03) - Fixes for thread identifiers +-------------------------------------------------- +* Use thread identifiers to identify threads, not Thread instances. + + +v1.0.1 (2016-04-03) - Fixes for Python 3 +---------------------------------------- +* Corrected bugs which prevented the library from being used on *Python 3*. + + +v1.0 (2016-02-28) - Stable Release +---------------------------------- +* Changed license to *LGPL*. +* Corrected minor bugs and inconsistencies. +* Corrected and extended documentation. + + +v0.6 (2016-02-08) - Keyboard Monitor +------------------------------------ +* Added support for monitoring the keyboard. +* Corrected wheel packaging. +* Corrected deadlock when stopping a listener in some cases on *X*. +* Corrected key code constants on *Mac OSX*. +* Do not intercept events on *Mac OSX*. + + +v0.5.1 (2016-01-26) - Do not die on dead keys +--------------------------------------------- +* Corrected handling of dead keys. +* Corrected documentation. + + +v0.5 (2016-01-18) - Keyboard Modifiers +-------------------------------------- +* Added support for modifiers. + + +v0.4 (2015-12-22) - Keyboard Controller +--------------------------------------- +* Added keyboard controller. + + +v0.3 (2015-12-22) - Cleanup +--------------------------- +* Moved ``pynput.mouse.Controller.Button`` to top-level. + + +v0.2 (2015-10-28) - Initial Release +----------------------------------- +* Support for controlling the mouse on *Linux*, *Mac OSX* and *Windows*. +* Support for monitoring the mouse on *Linux*, *Mac OSX* and *Windows*. diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/RECORD b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/RECORD new file mode 100644 index 0000000..a71033b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/RECORD @@ -0,0 +1,55 @@ +pynput-1.8.1.dist-info/COPYING.LGPL,sha256=eInlwsfJhthC1m5_bBVCQ1Mmf5nTUtL8MpjKfZxi0LU,7656 +pynput-1.8.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pynput-1.8.1.dist-info/METADATA,sha256=YNPNdd5SDrz20GVbmn7XZ-viRHHlyyZu1rUhCoYTo0k,32018 +pynput-1.8.1.dist-info/RECORD,, +pynput-1.8.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pynput-1.8.1.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109 +pynput-1.8.1.dist-info/pbr.json,sha256=CAnWerrCQ6A-ekJTVVKkD9J-ia4q-xoZzQWKOlPcseQ,47 +pynput-1.8.1.dist-info/top_level.txt,sha256=DpJjYf-VkYaa_COk_yUczD0pHqsLndB9SjmwcQGkXJQ,7 +pynput-1.8.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +pynput/__init__.py,sha256=dJ7uVZs3BRQILOxuM9BqDNDS36Qav123Hpx-3HUklpo,1334 +pynput/__pycache__/__init__.cpython-312.pyc,, +pynput/__pycache__/_info.cpython-312.pyc,, +pynput/_info.py,sha256=2aajH_7soMpmZO_oMDHp7R2aXpMher6jdVa5Mnhjj6g,775 +pynput/_util/__init__.py,sha256=ZB2LiSbGsbeQlnlVUQP9TNze15Fv6cb9m1zXYuJmy5g,15482 +pynput/_util/__pycache__/__init__.cpython-312.pyc,, +pynput/_util/__pycache__/darwin.cpython-312.pyc,, +pynput/_util/__pycache__/darwin_vks.cpython-312.pyc,, +pynput/_util/__pycache__/uinput.cpython-312.pyc,, +pynput/_util/__pycache__/win32.cpython-312.pyc,, +pynput/_util/__pycache__/win32_vks.cpython-312.pyc,, +pynput/_util/__pycache__/xorg.cpython-312.pyc,, +pynput/_util/__pycache__/xorg_keysyms.cpython-312.pyc,, +pynput/_util/darwin.py,sha256=AxtbSopLkKzWI1WLdCIZWMQtUtTuCxbRvWB6-WKcsCM,9200 +pynput/_util/darwin_vks.py,sha256=x-SbG4VgJ6Qc5-ZyF8cniqN3qIqahuQtXzG8ei94uWI,1512 +pynput/_util/uinput.py,sha256=ZFYiTsjQ7lr4h43X2Axrj-_FvWxiVT6dik7Z7Ra_sQE,2837 +pynput/_util/win32.py,sha256=YzEct1u1pzQ8v69kRlF-PnMB9BxwqkxCroNFVy4Ychw,18135 +pynput/_util/win32_vks.py,sha256=lC4y8E85nCGHmr4avVs44SvuBvUHBxmDeikNZcPGt6o,2894 +pynput/_util/xorg.py,sha256=ETHqMURfpvnA4q1UFIFQpWCj0c_9YTgasH3e0M4PRrM,15251 +pynput/_util/xorg_keysyms.py,sha256=YGRUXj1P0HT0gEkci2HZHyI_wcOwt0imt6R-7wPQVJo,69338 +pynput/keyboard/__init__.py,sha256=-5KBcWTSFjv2z1tu6sMV40UwhcqcX5O-yIex9fAmC_o,7903 +pynput/keyboard/__pycache__/__init__.cpython-312.pyc,, +pynput/keyboard/__pycache__/_base.cpython-312.pyc,, +pynput/keyboard/__pycache__/_darwin.cpython-312.pyc,, +pynput/keyboard/__pycache__/_dummy.cpython-312.pyc,, +pynput/keyboard/__pycache__/_uinput.cpython-312.pyc,, +pynput/keyboard/__pycache__/_win32.cpython-312.pyc,, +pynput/keyboard/__pycache__/_xorg.cpython-312.pyc,, +pynput/keyboard/_base.py,sha256=CPkWx8uE-oEhYMiRUY3uxqZuAMgT7Phrv3k8WoYp-D0,24082 +pynput/keyboard/_darwin.py,sha256=apF_nOR5EECuo1q-tZ5bi66JM3uFa83ZJy7Cfpc6xSQ,11672 +pynput/keyboard/_dummy.py,sha256=hkBFRY7HWyl86B_HdFiTeLthJjg926kN2peF-HUUXB0,895 +pynput/keyboard/_uinput.py,sha256=EH9FJX45IlbmjGvE1x4O2Ixvgkynp7XOka-vbtjVEAI,14479 +pynput/keyboard/_win32.py,sha256=i3S975s2SlEL9wva9ZMTi0icrNMWHyoj2zPN6gLeqsQ,12645 +pynput/keyboard/_xorg.py,sha256=QEGbet8NreQElzaSGfyARLaVoZxEvcIOTtjU6EHPnRQ,22677 +pynput/mouse/__init__.py,sha256=RiwZMZiWJEikRr8amiMoqJDVTn9i0irEfFcy3IA-s4w,2864 +pynput/mouse/__pycache__/__init__.cpython-312.pyc,, +pynput/mouse/__pycache__/_base.cpython-312.pyc,, +pynput/mouse/__pycache__/_darwin.cpython-312.pyc,, +pynput/mouse/__pycache__/_dummy.cpython-312.pyc,, +pynput/mouse/__pycache__/_win32.cpython-312.pyc,, +pynput/mouse/__pycache__/_xorg.cpython-312.pyc,, +pynput/mouse/_base.py,sha256=FfxHWA126ts1vz05YdcOHJOWb3XaF6WTctM-_ix6FNU,9338 +pynput/mouse/_darwin.py,sha256=a6M_Od7yCzEdxxrYGWLlHuInOWk6Nibd6dKnm5HC79s,6793 +pynput/mouse/_dummy.py,sha256=p16GreQcJbLMhE51uf8H3F8iarHf7Tu2s0JGt3J2xeQ,874 +pynput/mouse/_win32.py,sha256=e1NYKhsKe_Z2W4SZOJK3xWqDjtAa7Dy-zmvT_WzKx7M,7117 +pynput/mouse/_xorg.py,sha256=0P-N-jvRw0VTXH5P1O4LVnTds8jeHlqBiiDRpoUxVzQ,5559 diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/REQUESTED b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/WHEEL b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/WHEEL new file mode 100644 index 0000000..de294b9 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: setuptools (74.1.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/pbr.json b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/pbr.json new file mode 100644 index 0000000..ab50f33 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/pbr.json @@ -0,0 +1 @@ +{"is_release": false, "git_version": "2d6ab69"} \ No newline at end of file diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/top_level.txt b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/top_level.txt new file mode 100644 index 0000000..91a67a9 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/top_level.txt @@ -0,0 +1 @@ +pynput diff --git a/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/zip-safe b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput-1.8.1.dist-info/zip-safe @@ -0,0 +1 @@ + diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/__init__.py b/CLI/venv/lib/python3.12/site-packages/pynput/__init__.py new file mode 100644 index 0000000..b6ab843 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/__init__.py @@ -0,0 +1,41 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The main *pynput* module. + +This module imports ``keyboard`` and ``mouse``. +""" + +def _logger(cls): + """Creates a logger with a name suitable for a specific class. + + This function takes into account that implementations for classes reside in + platform dependent modules, and thus removes the final part of the module + name. + + :param type cls: The class for which to create a logger. + + :return: a logger + """ + import logging + return logging.getLogger('{}.{}'.format( + '.'.join(cls.__module__.split('.', 2)[:2]), + cls.__name__)) + + +from . import keyboard +from . import mouse diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..3a86865 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/__pycache__/_info.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/__pycache__/_info.cpython-312.pyc new file mode 100644 index 0000000..a02037f Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/__pycache__/_info.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_info.py b/CLI/venv/lib/python3.12/site-packages/pynput/_info.py new file mode 100644 index 0000000..91bf033 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_info.py @@ -0,0 +1,19 @@ +# coding=utf-8 +# pystray +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +__author__ = u'Moses Palmér' +__version__ = (1, 8, 1) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__init__.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__init__.py new file mode 100644 index 0000000..c7d98b4 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__init__.py @@ -0,0 +1,489 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +General utility functions and classes. +""" + +# pylint: disable=R0903 +# We implement minimal mixins + +# pylint: disable=W0212 +# We implement an internal API + +import contextlib +import functools +import importlib +import inspect +import os +import sys +import threading +import time + +import six + +from six.moves import queue + + +#: Possible resolutions for import related errors. +RESOLUTIONS = { + 'darwin': 'Please make sure that you have Python bindings for the ' + 'system frameworks installed', + 'uinput': 'Please make sure that you are running as root, and that ' + 'the utility dumpkeys is installed', + 'xorg': 'Please make sure that you have an X server running, and that ' + 'the DISPLAY environment variable is set correctly'} + + +def backend(package): + """Returns the backend module for a package. + + :param str package: The package for which to load a backend. + """ + backend_name = os.environ.get( + 'PYNPUT_BACKEND_{}'.format(package.rsplit('.')[-1].upper()), + os.environ.get('PYNPUT_BACKEND', None)) + if backend_name: + modules = [backend_name] + elif sys.platform == 'darwin': + modules = ['darwin'] + elif sys.platform == 'win32': + modules = ['win32'] + else: + modules = ['xorg'] + + errors = [] + resolutions = [] + for module in modules: + try: + return importlib.import_module('._' + module, package) + except ImportError as e: + errors.append(e) + if module in RESOLUTIONS: + resolutions.append(RESOLUTIONS[module]) + + raise ImportError('this platform is not supported: {}'.format( + '; '.join(str(e) for e in errors)) + ('\n\n' + 'Try one of the following resolutions:\n\n' + + '\n\n'.join( + ' * {}'.format(s) + for s in resolutions)) + if resolutions else '') + + +def prefix(base, cls): + """Calculates the prefix to use for platform specific options for a + specific class. + + The prefix if the name of the module containing the class that is an + immediate subclass of ``base`` among the super classes of ``cls``. + """ + for super_cls in filter( + lambda cls: issubclass(cls, base), + cls.__mro__[1:]): + if super_cls is base: + return cls.__module__.rsplit('.', 1)[-1][1:] + '_' + else: + result = prefix(base, super_cls) + if result is not None: + return result + + +class AbstractListener(threading.Thread): + """A class implementing the basic behaviour for event listeners. + + Instances of this class can be used as context managers. This is equivalent + to the following code:: + + listener.start() + listener.wait() + try: + with_statements() + finally: + listener.stop() + + Actual implementations of this class must set the attribute ``_log``, which + must be an instance of :class:`logging.Logger`. + + :param bool suppress: Whether to suppress events. Setting this to ``True`` + will prevent the input events from being passed to the rest of the + system. + + :param kwargs: A mapping from callback attribute to callback handler. All + handlers will be wrapped in a function reading the return value of the + callback, and if it ``is False``, raising :class:`StopException`. + + Any callback that is falsy will be ignored. + """ + class StopException(Exception): + """If an event listener callback raises this exception, the current + listener is stopped. + """ + pass + + #: Exceptions that are handled outside of the emitter and should thus not + #: be passed through the queue + _HANDLED_EXCEPTIONS = tuple() + + def __init__(self, suppress=False, **kwargs): + super(AbstractListener, self).__init__() + + def wrapper(f): + def inner(*args): + if f(*args) is False: + raise self.StopException() + return inner + + self._suppress = suppress + self._running = False + self._thread = threading.current_thread() + self._condition = threading.Condition() + self._ready = False + + # Allow multiple calls to stop + self._queue = queue.Queue(10) + + self.daemon = True + + for name, callback in kwargs.items(): + setattr(self, name, wrapper(callback)) + + @property + def suppress(self): + """Whether to suppress events. + """ + return self._suppress + + @property + def running(self): + """Whether the listener is currently running. + """ + return self._running + + def stop(self): + """Stops listening for events. + + When this method returns, no more events will be delivered. Once this + method has been called, the listener instance cannot be used any more, + since a listener is a :class:`threading.Thread`, and once stopped it + cannot be restarted. + + To resume listening for event, a new listener must be created. + """ + if self._running: + self._running = False + self._queue.put(None) + self._stop_platform() + + def __enter__(self): + self.start() + self.wait() + return self + + def __exit__(self, exc_type, value, traceback): + self.stop() + + def wait(self): + """Waits for this listener to become ready. + """ + self._condition.acquire() + while not self._ready: + self._condition.wait() + self._condition.release() + + def run(self): + """The thread runner method. + """ + self._running = True + self._thread = threading.current_thread() + self._run() + + # Make sure that the queue contains something + self._queue.put(None) + + @classmethod + def _emitter(cls, f): + """A decorator to mark a method as the one emitting the callbacks. + + This decorator will wrap the method and catch exception. If a + :class:`StopException` is caught, the listener will be stopped + gracefully. If any other exception is caught, it will be propagated to + the thread calling :meth:`join` and reraised there. + """ + @functools.wraps(f) + def inner(self, *args, **kwargs): + # pylint: disable=W0702; we want to catch all exception + try: + return f(self, *args, **kwargs) + except Exception as e: + if not isinstance(e, self._HANDLED_EXCEPTIONS): + if not isinstance(e, AbstractListener.StopException): + self._log.exception( + 'Unhandled exception in listener callback') + self._queue.put( + None if isinstance(e, cls.StopException) + else sys.exc_info()) + self.stop() + raise + # pylint: enable=W0702 + + return inner + + def _mark_ready(self): + """Marks this listener as ready to receive events. + + This method must be called from :meth:`_run`. :meth:`wait` will block + until this method is called. + """ + self._condition.acquire() + self._ready = True + self._condition.notify() + self._condition.release() + + def _run(self): + """The implementation of the :meth:`run` method. + + This is a platform dependent implementation. + """ + raise NotImplementedError() + + def _stop_platform(self): + """The implementation of the :meth:`stop` method. + + This is a platform dependent implementation. + """ + raise NotImplementedError() + + def _wrap(self, f, args): + """Wraps a callable to make it accept ``args`` number of arguments. + + :param f: The callable to wrap. If this is ``None`` a no-op wrapper is + returned. + + :param int args: The number of arguments to accept. + + :raises ValueError: if f requires more than ``args`` arguments + """ + if f is None: + return lambda *a: None + else: + argspec = inspect.getfullargspec(f) + actual = len(inspect.signature(f).parameters) + defaults = len(argspec.defaults) if argspec.defaults else 0 + if actual - defaults > args: + raise ValueError(f) + elif actual >= args or argspec.varargs is not None: + return f + else: + return lambda *a: f(*a[:actual]) + + def join(self, timeout=None, *args): + start = time.time() + super(AbstractListener, self).join(timeout, *args) + timeout = max(0.0, timeout - (time.time() - start)) \ + if timeout is not None \ + else None + + # Reraise any exceptions; make sure not to block if a timeout was + # provided + try: + exc_type, exc_value, exc_traceback = self._queue.get( + timeout=timeout) + six.reraise(exc_type, exc_value, exc_traceback) + except queue.Empty: + pass + except TypeError: + return + + +class Events(object): + """A base class to enable iterating over events. + """ + #: The listener class providing events. + _Listener = None + + class Event(object): + def __str__(self): + return '{}({})'.format( + self.__class__.__name__, + ', '.join( + '{}={}'.format(k, v) + for (k, v) in vars(self).items())) + + def __eq__(self, other): + return self.__class__ == other.__class__ \ + and dir(self) == dir(other) \ + and all( + getattr(self, k) == getattr(other, k) + for k in dir(self)) + + def __init__(self, *args, **kwargs): + super(Events, self).__init__() + self._event_queue = queue.Queue() + self._sentinel = object() + self._listener = self._Listener(*args, **{ + key: self._event_mapper(value) + for (key, value) in kwargs.items()}) + self.start = self._listener.start + + def __enter__(self): + self._listener.__enter__() + return self + + def __exit__(self, *args): + self._listener.__exit__(*args) + + # Drain the queue to ensure that the put does not block + while True: + try: + self._event_queue.get_nowait() + except queue.Empty: + break + + self._event_queue.put(self._sentinel) + + def __iter__(self): + return self + + def __next__(self): + event = self.get() + if event is not None: + return event + else: + raise StopIteration() + + def get(self, timeout=None): + """Attempts to read the next event. + + :param int timeout: An optional timeout. If this is not provided, this + method may block infinitely. + + :return: the next event, or ``None`` if the source has been stopped or + no events were received + """ + try: + event = self._event_queue.get(timeout=timeout) + return event if event is not self._sentinel else None + except queue.Empty: + return None + + def _event_mapper(self, event): + """Generates an event callback to transforms the callback arguments to + an event and then publishes it. + + :param callback event: A function generating an event object. + + :return: a callback + """ + @functools.wraps(event) + def inner(*args): + try: + self._event_queue.put(event(*args), block=False) + except queue.Full: + pass + + return inner + + +class NotifierMixin(object): + """A mixin for notifiers of fake events. + + This mixin can be used for controllers on platforms where sending fake + events does not cause a listener to receive a notification. + """ + def _emit(self, action, *args): + """Sends a notification to all registered listeners. + + This method will ensure that listeners that raise + :class:`StopException` are stopped. + + :param str action: The name of the notification. + + :param args: The arguments to pass. + """ + stopped = [] + for listener in self._listeners(): + try: + getattr(listener, action)(*args) + except listener.StopException: + stopped.append(listener) + for listener in stopped: + listener.stop() + + @classmethod + def _receiver(cls, listener_class): + """A decorator to make a class able to receive fake events from a + controller. + + This decorator will add the method ``_receive`` to the decorated class. + + This method is a context manager which ensures that all calls to + :meth:`_emit` will invoke the named method in the listener instance + while the block is active. + """ + @contextlib.contextmanager + def receive(self): + """Executes a code block with this listener instance registered as + a receiver of fake input events. + """ + self._controller_class._add_listener(self) + try: + yield + finally: + self._controller_class._remove_listener(self) + + listener_class._receive = receive + listener_class._controller_class = cls + + # Make sure this class has the necessary attributes + if not hasattr(cls, '_listener_cache'): + cls._listener_cache = set() + cls._listener_lock = threading.Lock() + + return listener_class + + @classmethod + def _listeners(cls): + """Iterates over the set of running listeners. + + This method will quit without acquiring the lock if the set is empty, + so there is potential for race conditions. This is an optimisation, + since :class:`Controller` will need to call this method for every + control event. + """ + if not cls._listener_cache: + return + with cls._listener_lock: + for listener in cls._listener_cache: + yield listener + + @classmethod + def _add_listener(cls, listener): + """Adds a listener to the set of running listeners. + + :param listener: The listener for fake events. + """ + with cls._listener_lock: + cls._listener_cache.add(listener) + + @classmethod + def _remove_listener(cls, listener): + """Removes this listener from the set of running listeners. + + :param listener: The listener for fake events. + """ + with cls._listener_lock: + cls._listener_cache.remove(listener) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..83591ea Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/darwin.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/darwin.cpython-312.pyc new file mode 100644 index 0000000..89af837 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/darwin.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/darwin_vks.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/darwin_vks.cpython-312.pyc new file mode 100644 index 0000000..b195c39 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/darwin_vks.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/uinput.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/uinput.cpython-312.pyc new file mode 100644 index 0000000..f1945f6 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/uinput.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/win32.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/win32.cpython-312.pyc new file mode 100644 index 0000000..0b5a1cc Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/win32.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/win32_vks.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/win32_vks.cpython-312.pyc new file mode 100644 index 0000000..1606445 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/win32_vks.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/xorg.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/xorg.cpython-312.pyc new file mode 100644 index 0000000..ad837f2 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/xorg.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/xorg_keysyms.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/xorg_keysyms.cpython-312.pyc new file mode 100644 index 0000000..1f526e7 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/_util/__pycache__/xorg_keysyms.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/darwin.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/darwin.py new file mode 100644 index 0000000..fdc284b --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/darwin.py @@ -0,0 +1,302 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +Utility functions and classes for the *Darwin* backend. +""" + +# pylint: disable=C0103 +# pylint: disable=R0903 +# This module contains wrapper classes + +import contextlib +import ctypes +import ctypes.util +import six + +import objc +import HIServices + +from CoreFoundation import ( + CFRelease +) + +from Quartz import ( + CFMachPortCreateRunLoopSource, + CFRunLoopAddSource, + CFRunLoopGetCurrent, + CFRunLoopRunInMode, + CFRunLoopStop, + CGEventGetIntegerValueField, + CGEventTapCreate, + CGEventTapEnable, + kCFRunLoopDefaultMode, + kCFRunLoopRunTimedOut, + kCGEventSourceUnixProcessID, + kCGEventTapOptionDefault, + kCGEventTapOptionListenOnly, + kCGHeadInsertEventTap, + kCGSessionEventTap) + + +from . import AbstractListener + + +def _wrap_value(value): + """Converts a pointer to a *Python objc* value. + + :param value: The pointer to convert. + + :return: a wrapped value + """ + return objc.objc_object(c_void_p=value) if value is not None else None + + +@contextlib.contextmanager +def _wrapped(value): + """A context manager that converts a raw pointer to a *Python objc* value. + + When the block is exited, the value is released. + + :param value: The raw value to wrap. + """ + wrapped_value = _wrap_value(value) + + try: + yield value + finally: + CFRelease(wrapped_value) + + +class CarbonExtra(object): + """A class exposing some missing functionality from *Carbon* as class + attributes. + """ + _Carbon = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Carbon')) + + _Carbon.TISCopyCurrentKeyboardInputSource.argtypes = [] + _Carbon.TISCopyCurrentKeyboardInputSource.restype = ctypes.c_void_p + + _Carbon.TISCopyCurrentASCIICapableKeyboardLayoutInputSource.argtypes = [] + _Carbon.TISCopyCurrentASCIICapableKeyboardLayoutInputSource.restype = \ + ctypes.c_void_p + + _Carbon.TISGetInputSourceProperty.argtypes = [ + ctypes.c_void_p, ctypes.c_void_p] + _Carbon.TISGetInputSourceProperty.restype = ctypes.c_void_p + + _Carbon.LMGetKbdType.argtypes = [] + _Carbon.LMGetKbdType.restype = ctypes.c_uint32 + + _Carbon.UCKeyTranslate.argtypes = [ + ctypes.c_void_p, + ctypes.c_uint16, + ctypes.c_uint16, + ctypes.c_uint32, + ctypes.c_uint32, + ctypes.c_uint32, + ctypes.POINTER(ctypes.c_uint32), + ctypes.c_uint8, + ctypes.POINTER(ctypes.c_uint8), + ctypes.c_uint16 * 4] + _Carbon.UCKeyTranslate.restype = ctypes.c_uint32 + + TISCopyCurrentKeyboardInputSource = \ + _Carbon.TISCopyCurrentKeyboardInputSource + + TISCopyCurrentASCIICapableKeyboardLayoutInputSource = \ + _Carbon.TISCopyCurrentASCIICapableKeyboardLayoutInputSource + + kTISPropertyUnicodeKeyLayoutData = ctypes.c_void_p.in_dll( + _Carbon, 'kTISPropertyUnicodeKeyLayoutData') + + TISGetInputSourceProperty = \ + _Carbon.TISGetInputSourceProperty + + LMGetKbdType = \ + _Carbon.LMGetKbdType + + kUCKeyActionDisplay = 3 + kUCKeyTranslateNoDeadKeysBit = 0 + + UCKeyTranslate = \ + _Carbon.UCKeyTranslate + + +@contextlib.contextmanager +def keycode_context(): + """Returns an opaque value representing a context for translating keycodes + to strings. + """ + keyboard_type, layout_data = None, None + for source in [ + CarbonExtra.TISCopyCurrentKeyboardInputSource, + CarbonExtra.TISCopyCurrentASCIICapableKeyboardLayoutInputSource]: + with _wrapped(source()) as keyboard: + keyboard_type = CarbonExtra.LMGetKbdType() + layout = _wrap_value(CarbonExtra.TISGetInputSourceProperty( + keyboard, + CarbonExtra.kTISPropertyUnicodeKeyLayoutData)) + layout_data = layout.bytes().tobytes() if layout else None + if keyboard is not None and layout_data is not None: + break + yield (keyboard_type, layout_data) + + +def keycode_to_string(context, keycode, modifier_state=0): + """Converts a keycode to a string. + """ + LENGTH = 4 + + keyboard_type, layout_data = context + + dead_key_state = ctypes.c_uint32() + length = ctypes.c_uint8() + unicode_string = (ctypes.c_uint16 * LENGTH)() + CarbonExtra.UCKeyTranslate( + layout_data, + keycode, + CarbonExtra.kUCKeyActionDisplay, + modifier_state, + keyboard_type, + CarbonExtra.kUCKeyTranslateNoDeadKeysBit, + ctypes.byref(dead_key_state), + LENGTH, + ctypes.byref(length), + unicode_string) + return u''.join( + six.unichr(unicode_string[i]) + for i in range(length.value)) + + +def get_unicode_to_keycode_map(): + """Returns a mapping from unicode strings to virtual key codes. + + :return: a dict mapping key codes to strings + """ + with keycode_context() as context: + return { + keycode_to_string(context, keycode): keycode + for keycode in range(128)} + + +class ListenerMixin(object): + """A mixin for *Quartz* event listeners. + + Subclasses should set a value for :attr:`_EVENTS` and implement + :meth:`_handle_message`. + """ + #: The events that we listen to + _EVENTS = tuple() + + #: Whether this process is trusted to monitor input events. + IS_TRUSTED = False + + def _run(self): + self.IS_TRUSTED = HIServices.AXIsProcessTrusted() + if not self.IS_TRUSTED: + self._log.warning( + 'This process is not trusted! Input event monitoring will not ' + 'be possible until it is added to accessibility clients.') + + self._loop = None + try: + tap = self._create_event_tap() + if tap is None: + self._mark_ready() + return + + loop_source = CFMachPortCreateRunLoopSource( + None, tap, 0) + self._loop = CFRunLoopGetCurrent() + + CFRunLoopAddSource( + self._loop, loop_source, kCFRunLoopDefaultMode) + CGEventTapEnable(tap, True) + + self._mark_ready() + + # pylint: disable=W0702; we want to silence errors + try: + while self.running: + result = CFRunLoopRunInMode( + kCFRunLoopDefaultMode, 1, False) + try: + if result != kCFRunLoopRunTimedOut: + break + except AttributeError: + # This happens during teardown of the virtual machine + break + + except: + # This exception will have been passed to the main thread + pass + # pylint: enable=W0702 + + finally: + self._loop = None + + def _stop_platform(self): + # The base class sets the running flag to False; this will cause the + # loop around run loop invocations to terminate and set this event + try: + if self._loop is not None: + CFRunLoopStop(self._loop) + except AttributeError: + # The loop may not have been created + pass + + def _create_event_tap(self): + """Creates the event tap used by the listener. + + :return: an event tap + """ + return CGEventTapCreate( + kCGSessionEventTap, + kCGHeadInsertEventTap, + kCGEventTapOptionListenOnly if ( + True + and not self.suppress + and self._intercept is None) + else kCGEventTapOptionDefault, + self._EVENTS, + self._handler, + None) + + @AbstractListener._emitter + def _handler(self, proxy, event_type, event, refcon): + """The callback registered with *macOS* for mouse events. + + This method will call the callbacks registered on initialisation. + """ + # An injected event will have a Unix process ID attached + is_injected = (CGEventGetIntegerValueField( + event, + kCGEventSourceUnixProcessID)) != 0 + + self._handle_message(proxy, event_type, event, refcon, is_injected) + if self._intercept is not None: + return self._intercept(event_type, event) + elif self.suppress: + return None + + def _handle_message(self, proxy, event_type, event, refcon): + """The device specific callback handler. + + This method calls the appropriate callback registered when this + listener was created based on the event. + """ + raise NotImplementedError() diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/darwin_vks.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/darwin_vks.py new file mode 100644 index 0000000..6499fb1 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/darwin_vks.py @@ -0,0 +1,79 @@ +# coding: utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +# pylint: disable=C0111,C0302 + +SYMBOLS = { + 0: 'a', + 1: 's', + 2: 'd', + 3: 'f', + 4: 'h', + 5: 'g', + 6: 'z', + 7: 'x', + 8: 'c', + 9: 'v', + 11: 'b', + 12: 'q', + 13: 'w', + 14: 'e', + 15: 'r', + 16: 'y', + 17: 't', + 18: '1', + 19: '2', + 20: '3', + 21: '4', + 22: '6', + 23: '5', + 24: '=', + 25: '9', + 26: '7', + 27: '-', + 28: '8', + 29: '0', + 30: ']', + 31: 'o', + 32: 'u', + 33: '[', + 34: 'i', + 35: 'p', + 37: 'l', + 38: 'j', + 39: '\'', + 40: 'k', + 41: ';', + 42: '\\', + 43: ',', + 44: '/', + 45: 'n', + 46: 'm', + 47: '.', + 49: ' ', + 50: '`', + 82: '0', + 83: '1', + 84: '2', + 85: '3', + 86: '4', + 87: '5', + 88: '6', + 89: '7', + 91: '8', + 92: '9', +} diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/uinput.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/uinput.py new file mode 100644 index 0000000..b0a6a78 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/uinput.py @@ -0,0 +1,99 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +Utility functions and classes for the *uinput* backend. +""" + +# pylint: disable=R0903 +# We implement stubs + +import evdev + + +# Check that we have permissions to continue +def _check(): + # TODO: Implement! + pass +_check() +del _check + + +class ListenerMixin(object): + """A mixin for *uinput* event listeners. + + Subclasses should set a value for :attr:`_EVENTS` and implement + :meth:`_handle_message`. + """ + #: The events for which to listen + _EVENTS = tuple() + + def __init__(self, *args, **kwargs): + super(ListenerMixin, self).__init__(*args, **kwargs) + self._dev = self._device(self._options.get( + 'device_paths', + evdev.list_devices())) + if self.suppress: + self._dev.grab() + + def _run(self): + for event in self._dev.read_loop(): + if event.type in self._EVENTS: + self._handle_message(event) + + def _stop_platform(self): + self._dev.close() + + def _device(self, paths): + """Attempts to load a readable keyboard device. + + :param paths: A list of paths. + + :return: a compatible device + """ + dev, count = None, 0 + for path in paths: + # Open the device + try: + next_dev = evdev.InputDevice(path) + except OSError: + continue + + # Does this device provide more handled event codes? + capabilities = next_dev.capabilities() + next_count = sum( + len(codes) + for event, codes in capabilities.items() + if event in self._EVENTS) + if next_count > count: + dev = next_dev + count = next_count + else: + next_dev.close() + + if dev is None: + raise OSError('no keyboard device available') + else: + return dev + + def _handle_message(self, event): + """Handles a single event. + + This method should call one of the registered event callbacks. + + :param event: The event. + """ + raise NotImplementedError() diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/win32.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/win32.py new file mode 100644 index 0000000..b945a59 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/win32.py @@ -0,0 +1,598 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +Utility functions and classes for the *win32* backend. +""" + +# pylint: disable=C0103 +# We want to make it obvious how structs are related + +# pylint: disable=R0903 +# This module contains a number of structs + +import contextlib +import ctypes +import itertools +import threading + +from ctypes import ( + windll, + wintypes) + +from . import AbstractListener, win32_vks as VK + + +# LPDWORD is not in ctypes.wintypes on Python 2 +if not hasattr(wintypes, 'LPDWORD'): + wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD) + + +class MOUSEINPUT(ctypes.Structure): + """Contains information about a simulated mouse event. + """ + MOVE = 0x0001 + LEFTDOWN = 0x0002 + LEFTUP = 0x0004 + RIGHTDOWN = 0x0008 + RIGHTUP = 0x0010 + MIDDLEDOWN = 0x0020 + MIDDLEUP = 0x0040 + XDOWN = 0x0080 + XUP = 0x0100 + WHEEL = 0x0800 + HWHEEL = 0x1000 + ABSOLUTE = 0x8000 + + XBUTTON1 = 0x0001 + XBUTTON2 = 0x0002 + + _fields_ = [ + ('dx', wintypes.LONG), + ('dy', wintypes.LONG), + ('mouseData', wintypes.DWORD), + ('dwFlags', wintypes.DWORD), + ('time', wintypes.DWORD), + ('dwExtraInfo', ctypes.c_void_p)] + + +class KEYBDINPUT(ctypes.Structure): + """Contains information about a simulated keyboard event. + """ + EXTENDEDKEY = 0x0001 + KEYUP = 0x0002 + SCANCODE = 0x0008 + UNICODE = 0x0004 + + _fields_ = [ + ('wVk', wintypes.WORD), + ('wScan', wintypes.WORD), + ('dwFlags', wintypes.DWORD), + ('time', wintypes.DWORD), + ('dwExtraInfo', ctypes.c_void_p)] + + +class HARDWAREINPUT(ctypes.Structure): + """Contains information about a simulated message generated by an input + device other than a keyboard or mouse. + """ + _fields_ = [ + ('uMsg', wintypes.DWORD), + ('wParamL', wintypes.WORD), + ('wParamH', wintypes.WORD)] + + +class INPUT_union(ctypes.Union): + """Represents the union of input types in :class:`INPUT`. + """ + _fields_ = [ + ('mi', MOUSEINPUT), + ('ki', KEYBDINPUT), + ('hi', HARDWAREINPUT)] + + +class INPUT(ctypes.Structure): + """Used by :attr:`SendInput` to store information for synthesizing input + events such as keystrokes, mouse movement, and mouse clicks. + """ + MOUSE = 0 + KEYBOARD = 1 + HARDWARE = 2 + + _fields_ = [ + ('type', wintypes.DWORD), + ('value', INPUT_union)] + + +LPINPUT = ctypes.POINTER(INPUT) + +VkKeyScan = windll.user32.VkKeyScanW +VkKeyScan.argtypes = ( + wintypes.WCHAR,) + +MapVirtualKey = windll.user32.MapVirtualKeyW +MapVirtualKey.argtypes = ( + wintypes.UINT, + wintypes.UINT) +MapVirtualKey.MAPVK_VK_TO_VSC = 0 + +SendInput = windll.user32.SendInput +SendInput.argtypes = ( + wintypes.UINT, + ctypes.c_voidp, # Really LPINPUT + ctypes.c_int) + +GetCurrentThreadId = windll.kernel32.GetCurrentThreadId +GetCurrentThreadId.restype = wintypes.DWORD + + +class MessageLoop(object): + """A class representing a message loop. + """ + #: The message that signals this loop to terminate + WM_STOP = 0x0401 + + _LPMSG = ctypes.POINTER(wintypes.MSG) + + _GetMessage = windll.user32.GetMessageW + _GetMessage.argtypes = ( + ctypes.c_voidp, # Really _LPMSG + wintypes.HWND, + wintypes.UINT, + wintypes.UINT) + _PeekMessage = windll.user32.PeekMessageW + _PeekMessage.argtypes = ( + ctypes.c_voidp, # Really _LPMSG + wintypes.HWND, + wintypes.UINT, + wintypes.UINT, + wintypes.UINT) + _PostThreadMessage = windll.user32.PostThreadMessageW + _PostThreadMessage.argtypes = ( + wintypes.DWORD, + wintypes.UINT, + wintypes.WPARAM, + wintypes.LPARAM) + + PM_NOREMOVE = 0 + + def __init__(self): + self._threadid = None + self._event = threading.Event() + self.thread = None + + def __iter__(self): + """Initialises the message loop and yields all messages until + :meth:`stop` is called. + + :raises AssertionError: if :meth:`start` has not been called + """ + assert self._threadid is not None + + try: + # Pump messages until WM_STOP + while True: + msg = wintypes.MSG() + lpmsg = ctypes.byref(msg) + r = self._GetMessage(lpmsg, None, 0, 0) + if r <= 0 or msg.message == self.WM_STOP: + break + else: + yield msg + + finally: + self._threadid = None + self.thread = None + + def start(self): + """Starts the message loop. + + This method must be called before iterating over messages, and it must + be called from the same thread. + """ + self._threadid = GetCurrentThreadId() + self.thread = threading.current_thread() + + # Create the message loop + msg = wintypes.MSG() + lpmsg = ctypes.byref(msg) + self._PeekMessage(lpmsg, None, 0x0400, 0x0400, self.PM_NOREMOVE) + + # Set the event to signal to other threads that the loop is created + self._event.set() + + def stop(self): + """Stops the message loop. + """ + self._event.wait() + if self._threadid: + self.post(self.WM_STOP, 0, 0) + + def post(self, msg, wparam, lparam): + """Posts a message to this message loop. + + :param ctypes.wintypes.UINT msg: The message. + + :param ctypes.wintypes.WPARAM wparam: The value of ``wParam``. + + :param ctypes.wintypes.LPARAM lparam: The value of ``lParam``. + """ + self._PostThreadMessage(self._threadid, msg, wparam, lparam) + + +class SystemHook(object): + """A class to handle Windows hooks. + """ + #: The hook action value for actions we should check + HC_ACTION = 0 + + _HOOKPROC = ctypes.WINFUNCTYPE( + wintypes.LPARAM, + ctypes.c_int32, wintypes.WPARAM, wintypes.LPARAM) + + _SetWindowsHookEx = windll.user32.SetWindowsHookExW + _SetWindowsHookEx.argtypes = ( + ctypes.c_int, + _HOOKPROC, + wintypes.HINSTANCE, + wintypes.DWORD) + _UnhookWindowsHookEx = windll.user32.UnhookWindowsHookEx + _UnhookWindowsHookEx.argtypes = ( + wintypes.HHOOK,) + _CallNextHookEx = windll.user32.CallNextHookEx + _CallNextHookEx.argtypes = ( + wintypes.HHOOK, + ctypes.c_int, + wintypes.WPARAM, + wintypes.LPARAM) + + #: The registered hook procedures + _HOOKS = {} + + class SuppressException(Exception): + """An exception raised by a hook callback to suppress further + propagation of events. + """ + pass + + def __init__(self, hook_id, on_hook=lambda code, msg, lpdata: None): + self.hook_id = hook_id + self.on_hook = on_hook + self._hook = None + + def __enter__(self): + key = threading.current_thread().ident + assert key not in self._HOOKS + + # Add ourself to lookup table and install the hook + self._HOOKS[key] = self + self._hook = self._SetWindowsHookEx( + self.hook_id, + self._handler, + None, + 0) + + return self + + def __exit__(self, exc_type, value, traceback): + key = threading.current_thread().ident + assert key in self._HOOKS + + if self._hook is not None: + # Uninstall the hook and remove ourself from lookup table + self._UnhookWindowsHookEx(self._hook) + del self._HOOKS[key] + + @staticmethod + @_HOOKPROC + def _handler(code, msg, lpdata): + key = threading.current_thread().ident + self = SystemHook._HOOKS.get(key, None) + if self: + # pylint: disable=W0702; we want to silence errors + try: + self.on_hook(code, msg, lpdata) + except self.SuppressException: + # Return non-zero to stop event propagation + return 1 + except: + # Ignore any errors + pass + # pylint: enable=W0702 + return SystemHook._CallNextHookEx(0, code, msg, lpdata) + + +class ListenerMixin(object): + """A mixin for *win32* event listeners. + + Subclasses should set a value for :attr:`_EVENTS` and implement + :meth:`_handle_message`. + + Subclasses must also be decorated with a decorator compatible with + :meth:`pynput._util.NotifierMixin._receiver` or implement the method + ``_receive()``. + """ + #: The Windows hook ID for the events to capture. + _EVENTS = None + + #: The window message used to signal that an even should be handled. + _WM_PROCESS = 0x410 + + #: Additional window messages to propagate to the subclass handler. + _WM_NOTIFICATIONS = [] + + def suppress_event(self): + """Causes the currently filtered event to be suppressed. + + This has a system wide effect and will generally result in no + applications receiving the event. + + This method will raise an undefined exception. + """ + raise SystemHook.SuppressException() + + def _run(self): + self._message_loop = MessageLoop() + with self._receive(): + self._mark_ready() + self._message_loop.start() + + # pylint: disable=W0702; we want to silence errors + try: + with SystemHook(self._EVENTS, self._handler): + # Just pump messages + for msg in self._message_loop: + if not self.running: + break + if msg.message == self._WM_PROCESS: + self._process(msg.wParam, msg.lParam) + elif msg.message in self._WM_NOTIFICATIONS: + self._on_notification( + msg.message, msg.wParam, msg.lParam) + except: + # This exception will have been passed to the main thread + pass + # pylint: enable=W0702 + + def _stop_platform(self): + try: + self._message_loop.stop() + except AttributeError: + # The loop may not have been created + pass + + @AbstractListener._emitter + def _handler(self, code, msg, lpdata): + """The callback registered with *Windows* for events. + + This method will post the message :attr:`_WM_PROCESS` to the message + loop started with this listener using :meth:`MessageLoop.post`. The + parameters are retrieved with a call to :meth:`_handle`. + """ + try: + converted = self._convert(code, msg, lpdata) + if converted is not None: + self._message_loop.post(self._WM_PROCESS, *converted) + except NotImplementedError: + self._handle_message(code, msg, lpdata) + + if self.suppress: + self.suppress_event() + + def _convert(self, code, msg, lpdata): + """The device specific callback handler. + + This method converts a low-level message and data to a + ``WPARAM`` / ``LPARAM`` pair. + """ + raise NotImplementedError() + + def _process(self, wparam, lparam): + """The device specific callback handler. + + This method performs the actual dispatching of events. + """ + raise NotImplementedError() + + def _handle_message(self, code, msg, lpdata): + """The device specific callback handler. + + This method calls the appropriate callback registered when this + listener was created based on the event. + + This method is only called if :meth:`_convert` is not implemented. + """ + raise NotImplementedError() + + def _on_notification(self, code, wparam, lparam): + """An additional notification handler. + + This method will be called for every message in + :attr:`_WM_NOTIFICATIONS`. + """ + raise NotImplementedError() + + +class KeyTranslator(object): + """A class to translate virtual key codes to characters. + """ + _GetAsyncKeyState = ctypes.windll.user32.GetAsyncKeyState + _GetAsyncKeyState.argtypes = ( + ctypes.c_int,) + _GetKeyboardLayout = ctypes.windll.user32.GetKeyboardLayout + _GetKeyboardLayout.argtypes = ( + wintypes.DWORD,) + _GetKeyboardState = ctypes.windll.user32.GetKeyboardState + _GetKeyboardState.argtypes = ( + ctypes.c_voidp,) + _GetKeyState = ctypes.windll.user32.GetAsyncKeyState + _GetKeyState.argtypes = ( + ctypes.c_int,) + _MapVirtualKeyEx = ctypes.windll.user32.MapVirtualKeyExW + _MapVirtualKeyEx.argtypes = ( + wintypes.UINT, + wintypes.UINT, + wintypes.HKL) + _ToUnicodeEx = ctypes.windll.user32.ToUnicodeEx + _ToUnicodeEx.argtypes = ( + wintypes.UINT, + wintypes.UINT, + ctypes.c_voidp, + ctypes.c_voidp, + ctypes.c_int, + wintypes.UINT, + wintypes.HKL) + + _MAPVK_VK_TO_VSC = 0 + _MAPVK_VSC_TO_VK = 1 + _MAPVK_VK_TO_CHAR = 2 + + def __init__(self): + self.update_layout() + + def __call__(self, vk, is_press): + """Converts a virtual key code to a string. + + :param int vk: The virtual key code. + + :param bool is_press: Whether this is a press. + + :return: parameters suitable for the :class:`pynput.keyboard.KeyCode` + constructor + + :raises OSError: if a call to any *win32* function fails + """ + # Get a string representation of the key + layout_data = self._layout_data[self._modifier_state()] + scan = self._to_scan(vk, self._layout) + character, is_dead = layout_data[scan] + + return { + 'char': character, + 'is_dead': is_dead, + 'vk': vk, + '_scan': scan} + + def update_layout(self): + """Updates the cached layout data. + """ + self._layout, self._layout_data = self._generate_layout() + + def char_from_scan(self, scan): + """Translates a scan code to a character, if possible. + + :param int scan: The scan code to translate. + + :return: maybe a character + :rtype: str or None + """ + return self._layout_data[(False, False, False)][scan][0] + + def _generate_layout(self): + """Generates the keyboard layout. + + This method will call ``ToUnicodeEx``, which modifies kernel buffers, + so it must *not* be called from the keyboard hook. + + The return value is the tuple ``(layout_handle, layout_data)``, where + ``layout_data`` is a mapping from the tuple ``(shift, ctrl, alt)`` to + an array indexed by scan code containing the data + ``(character, is_dead)``, and ``layout_handle`` is the handle of the + layout. + + :return: a composite layout + """ + layout_data = {} + + state = (ctypes.c_ubyte * 255)() + with self._thread_input() as active_thread: + layout = self._GetKeyboardLayout(active_thread) + vks = [ + self._to_vk(scan, layout) + for scan in range(len(state))] + + for shift, ctrl, alt in itertools.product( + (False, True), (False, True), (False, True)): + current = [(None, False)] * len(state) + layout_data[(shift, ctrl, alt)] = current + + # Update the keyboard state based on the modifier state + state[VK.SHIFT] = 0x80 if shift else 0x00 + state[VK.CONTROL] = 0x80 if ctrl else 0x00 + state[VK.MENU] = 0x80 if alt else 0x00 + + # For each virtual key code... + out = (ctypes.wintypes.WCHAR * 5)() + for (scan, vk) in enumerate(vks): + # ...translate it to a unicode character + count = self._ToUnicodeEx( + vk, scan, ctypes.byref(state), ctypes.byref(out), + len(out), 0, layout) + + # Cache the result if a key is mapped + if count != 0: + character = out[0] + is_dead = count < 0 + current[scan] = (character, is_dead) + + # If the key is dead, flush the keyboard state + if is_dead: + self._ToUnicodeEx( + vk, scan, ctypes.byref(state), + ctypes.byref(out), len(out), 0, layout) + + return (layout, layout_data) + + def _to_scan(self, vk, layout): + """Retrieves the scan code for a virtual key code. + + :param int vk: The virtual key code. + + :param layout: The keyboard layout. + + :return: the scan code + """ + return self._MapVirtualKeyEx( + vk, self._MAPVK_VK_TO_VSC, layout) + + def _to_vk(self, scan, layout): + """Retrieves the virtual key code for a scan code. + + :param int vscan: The scan code. + + :param layout: The keyboard layout. + + :return: the virtual key code + """ + return self._MapVirtualKeyEx( + scan, self._MAPVK_VSC_TO_VK, layout) + + def _modifier_state(self): + """Returns a key into :attr:`_layout_data` for the current modifier + state. + + :return: the current modifier state + """ + shift = bool(self._GetAsyncKeyState(VK.SHIFT) & 0x8000) + ctrl = bool(self._GetAsyncKeyState(VK.CONTROL) & 0x8000) + alt = bool(self._GetAsyncKeyState(VK.MENU) & 0x8000) + return (shift, ctrl, alt) + + @contextlib.contextmanager + def _thread_input(self): + """Yields the current thread ID. + """ + yield GetCurrentThreadId() diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/win32_vks.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/win32_vks.py new file mode 100644 index 0000000..7b30238 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/win32_vks.py @@ -0,0 +1,179 @@ +# coding: utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +# pylint: disable=C0111,C0302 + +LBUTTON = 1 +RBUTTON = 2 +CANCEL = 3 +MBUTTON = 4 +XBUTTON1 = 5 +XBUTTON2 = 6 +BACK = 8 +TAB = 9 +CLEAR = 12 +RETURN = 13 +SHIFT = 16 +CONTROL = 17 +MENU = 18 +PAUSE = 19 +CAPITAL = 20 +KANA = 21 +HANGEUL = 21 +HANGUL = 21 +JUNJA = 23 +FINAL = 24 +HANJA = 25 +KANJI = 25 +ESCAPE = 27 +CONVERT = 28 +NONCONVERT = 29 +ACCEPT = 30 +MODECHANGE = 31 +SPACE = 32 +PRIOR = 33 +NEXT = 34 +END = 35 +HOME = 36 +LEFT = 37 +UP = 38 +RIGHT = 39 +DOWN = 40 +SELECT = 41 +PRINT = 42 +EXECUTE = 43 +SNAPSHOT = 44 +INSERT = 45 +DELETE = 46 +HELP = 47 +LWIN = 91 +RWIN = 92 +APPS = 93 +SLEEP = 95 +NUMPAD0 = 96 +NUMPAD1 = 97 +NUMPAD2 = 98 +NUMPAD3 = 99 +NUMPAD4 = 100 +NUMPAD5 = 101 +NUMPAD6 = 102 +NUMPAD7 = 103 +NUMPAD8 = 104 +NUMPAD9 = 105 +MULTIPLY = 106 +ADD = 107 +SEPARATOR = 108 +SUBTRACT = 109 +DECIMAL = 110 +DIVIDE = 111 +F1 = 112 +F2 = 113 +F3 = 114 +F4 = 115 +F5 = 116 +F6 = 117 +F7 = 118 +F8 = 119 +F9 = 120 +F10 = 121 +F11 = 122 +F12 = 123 +F13 = 124 +F14 = 125 +F15 = 126 +F16 = 127 +F17 = 128 +F18 = 129 +F19 = 130 +F20 = 131 +F21 = 132 +F22 = 133 +F23 = 134 +F24 = 135 +NUMLOCK = 144 +SCROLL = 145 +OEM_NEC_EQUAL = 146 +OEM_FJ_JISHO = 146 +OEM_FJ_MASSHOU = 147 +OEM_FJ_TOUROKU = 148 +OEM_FJ_LOYA = 149 +OEM_FJ_ROYA = 150 +LSHIFT = 160 +RSHIFT = 161 +LCONTROL = 162 +RCONTROL = 163 +LMENU = 164 +RMENU = 165 +BROWSER_BACK = 166 +BROWSER_FORWARD = 167 +BROWSER_REFRESH = 168 +BROWSER_STOP = 169 +BROWSER_SEARCH = 170 +BROWSER_FAVORITES = 171 +BROWSER_HOME = 172 +VOLUME_MUTE = 173 +VOLUME_DOWN = 174 +VOLUME_UP = 175 +MEDIA_NEXT_TRACK = 176 +MEDIA_PREV_TRACK = 177 +MEDIA_STOP = 178 +MEDIA_PLAY_PAUSE = 179 +LAUNCH_MAIL = 180 +LAUNCH_MEDIA_SELECT = 181 +LAUNCH_APP1 = 182 +LAUNCH_APP2 = 183 +OEM_1 = 186 +OEM_PLUS = 187 +OEM_COMMA = 188 +OEM_MINUS = 189 +OEM_PERIOD = 190 +OEM_2 = 191 +OEM_3 = 192 +OEM_4 = 219 +OEM_5 = 220 +OEM_6 = 221 +OEM_7 = 222 +OEM_8 = 223 +OEM_AX = 225 +OEM_102 = 226 +ICO_HELP = 227 +ICO_00 = 228 +PROCESSKEY = 229 +ICO_CLEAR = 230 +PACKET = 231 +OEM_RESET = 233 +OEM_JUMP = 234 +OEM_PA1 = 235 +OEM_PA2 = 236 +OEM_PA3 = 237 +OEM_WSCTRL = 238 +OEM_CUSEL = 239 +OEM_ATTN = 240 +OEM_FINISH = 241 +OEM_COPY = 242 +OEM_AUTO = 243 +OEM_ENLW = 244 +OEM_BACKTAB = 245 +ATTN = 246 +CRSEL = 247 +EXSEL = 248 +EREOF = 249 +PLAY = 250 +ZOOM = 251 +NONAME = 252 +PA1 = 253 +OEM_CLEAR = 254 diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/xorg.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/xorg.py new file mode 100644 index 0000000..52995f3 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/xorg.py @@ -0,0 +1,496 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +Utility functions and classes for the *Xorg* backend. +""" + +# pylint: disable=R0903 +# We implement stubs + +import contextlib +import functools +import itertools +import operator +import Xlib.display +import Xlib.keysymdef +import Xlib.threaded +import Xlib.XK + +from . import AbstractListener +from .xorg_keysyms import SYMBOLS + + +# Create a display to verify that we have an X connection +def _check_and_initialize(): + display = Xlib.display.Display() + display.close() + + for group in Xlib.keysymdef.__all__: + Xlib.XK.load_keysym_group(group) +_check_and_initialize() +del _check_and_initialize + + +class X11Error(Exception): + """An error that is thrown at the end of a code block managed by a + :func:`display_manager` if an *X11* error occurred. + """ + pass + + +@contextlib.contextmanager +def display_manager(display): + """Traps *X* errors and raises an :class:``X11Error`` at the end if any + error occurred. + + This handler also ensures that the :class:`Xlib.display.Display` being + managed is sync'd. + + :param Xlib.display.Display display: The *X* display. + + :return: the display + :rtype: Xlib.display.Display + """ + errors = [] + + def handler(*args): + """The *Xlib* error handler. + """ + errors.append(args) + + old_handler = display.set_error_handler(handler) + try: + yield display + display.sync() + finally: + display.set_error_handler(old_handler) + if errors: + raise X11Error(errors) + + +def _find_mask(display, symbol): + """Returns the mode flags to use for a modifier symbol. + + :param Xlib.display.Display display: The *X* display. + + :param str symbol: The name of the symbol. + + :return: the modifier mask + """ + # Get the key code for the symbol + modifier_keycode = display.keysym_to_keycode( + Xlib.XK.string_to_keysym(symbol)) + + for index, keycodes in enumerate(display.get_modifier_mapping()): + for keycode in keycodes: + if keycode == modifier_keycode: + return 1 << index + + return 0 + + +def alt_mask(display): + """Returns the *alt* mask flags. + + The first time this function is called for a display, the value is cached. + Subsequent calls will return the cached value. + + :param Xlib.display.Display display: The *X* display. + + :return: the modifier mask + """ + if not hasattr(display, '__alt_mask'): + display.__alt_mask = _find_mask(display, 'Alt_L') + return display.__alt_mask + + +def alt_gr_mask(display): + """Returns the *alt* mask flags. + + The first time this function is called for a display, the value is cached. + Subsequent calls will return the cached value. + + :param Xlib.display.Display display: The *X* display. + + :return: the modifier mask + """ + if not hasattr(display, '__altgr_mask'): + display.__altgr_mask = _find_mask(display, 'Mode_switch') + return display.__altgr_mask + + +def numlock_mask(display): + """Returns the *numlock* mask flags. + + The first time this function is called for a display, the value is cached. + Subsequent calls will return the cached value. + + :param Xlib.display.Display display: The *X* display. + + :return: the modifier mask + """ + if not hasattr(display, '__numlock_mask'): + display.__numlock_mask = _find_mask(display, 'Num_Lock') + return display.__numlock_mask + + +def keysym_is_latin_upper(keysym): + """Determines whether a *keysym* is an upper case *latin* character. + + This is true only if ``XK_A`` <= ``keysym`` <= ` XK_Z``. + + :param in keysym: The *keysym* to check. + """ + return Xlib.XK.XK_A <= keysym <= Xlib.XK.XK_Z + + +def keysym_is_latin_lower(keysym): + """Determines whether a *keysym* is a lower case *latin* character. + + This is true only if ``XK_a`` <= ``keysym`` <= ` XK_z``. + + :param in keysym: The *keysym* to check. + """ + return Xlib.XK.XK_a <= keysym <= Xlib.XK.XK_z + + +def keysym_group(ks1, ks2): + """Generates a group from two *keysyms*. + + The implementation of this function comes from: + + Within each group, if the second element of the group is ``NoSymbol``, + then the group should be treated as if the second element were the same + as the first element, except when the first element is an alphabetic + *KeySym* ``K`` for which both lowercase and uppercase forms are + defined. + + In that case, the group should be treated as if the first element were + the lowercase form of ``K`` and the second element were the uppercase + form of ``K``. + + This function assumes that *alphabetic* means *latin*; this assumption + appears to be consistent with observations of the return values from + ``XGetKeyboardMapping``. + + :param ks1: The first *keysym*. + + :param ks2: The second *keysym*. + + :return: a tuple conforming to the description above + """ + if ks2 == Xlib.XK.NoSymbol: + if keysym_is_latin_upper(ks1): + return (Xlib.XK.XK_a + ks1 - Xlib.XK.XK_A, ks1) + elif keysym_is_latin_lower(ks1): + return (ks1, Xlib.XK.XK_A + ks1 - Xlib.XK.XK_a) + else: + return (ks1, ks1) + else: + return (ks1, ks2) + + +def keysym_normalize(keysym): + """Normalises a list of *keysyms*. + + The implementation of this function comes from: + + If the list (ignoring trailing ``NoSymbol`` entries) is a single + *KeySym* ``K``, then the list is treated as if it were the list + ``K NoSymbol K NoSymbol``. + + If the list (ignoring trailing ``NoSymbol`` entries) is a pair of + *KeySyms* ``K1 K2``, then the list is treated as if it were the list + ``K1 K2 K1 K2``. + + If the list (ignoring trailing ``NoSymbol`` entries) is a triple of + *KeySyms* ``K1 K2 K3``, then the list is treated as if it were the list + ``K1 K2 K3 NoSymbol``. + + This function will also group the *keysyms* using :func:`keysym_group`. + + :param keysyms: A list of keysyms. + + :return: the tuple ``(group_1, group_2)`` or ``None`` + """ + # Remove trailing NoSymbol + stripped = list(reversed(list( + itertools.dropwhile( + lambda n: n == Xlib.XK.NoSymbol, + reversed(keysym))))) + + if not stripped: + return + + elif len(stripped) == 1: + return ( + keysym_group(stripped[0], Xlib.XK.NoSymbol), + keysym_group(stripped[0], Xlib.XK.NoSymbol)) + + elif len(stripped) == 2: + return ( + keysym_group(stripped[0], stripped[1]), + keysym_group(stripped[0], stripped[1])) + + elif len(stripped) == 3: + return ( + keysym_group(stripped[0], stripped[1]), + keysym_group(stripped[2], Xlib.XK.NoSymbol)) + + elif len(stripped) >= 6: + # TODO: Find out why this is necessary; using only the documented + # behaviour may lead to only a US layout being used? + return ( + keysym_group(stripped[0], stripped[1]), + keysym_group(stripped[4], stripped[5])) + + else: + return ( + keysym_group(stripped[0], stripped[1]), + keysym_group(stripped[2], stripped[3])) + + +def index_to_shift(display, index): + """Converts an index in a *key code* list to the corresponding shift state. + + :param Xlib.display.Display display: The display for which to retrieve the + shift mask. + + :param int index: The keyboard mapping *key code* index. + + :return: a shift mask + """ + return ( + (1 << 0 if index & 1 else 0) | + (alt_gr_mask(display) if index & 2 else 0)) + + +def shift_to_index(display, shift): + """Converts an index in a *key code* list to the corresponding shift state. + + :param Xlib.display.Display display: The display for which to retrieve the + shift mask. + + :param int index: The keyboard mapping *key code* index. + + :return: a shift mask + """ + return ( + (1 if shift & 1 else 0) + + (2 if shift & alt_gr_mask(display) else 0)) + + +def keyboard_mapping(display): + """Generates a mapping from *keysyms* to *key codes* and required + modifier shift states. + + :param Xlib.display.Display display: The display for which to retrieve the + keyboard mapping. + + :return: the keyboard mapping + """ + mapping = {} + + shift_mask = 1 << 0 + group_mask = alt_gr_mask(display) + + # Iterate over all keysym lists in the keyboard mapping + min_keycode = display.display.info.min_keycode + keycode_count = display.display.info.max_keycode - min_keycode + 1 + for index, keysyms in enumerate(display.get_keyboard_mapping( + min_keycode, keycode_count)): + key_code = index + min_keycode + + # Normalise the keysym list to yield a tuple containing the two groups + normalized = keysym_normalize(keysyms) + if not normalized: + continue + + # Iterate over the groups to extract the shift and modifier state + for groups, group in zip(normalized, (False, True)): + for keysym, shift in zip(groups, (False, True)): + if not keysym: + continue + shift_state = 0 \ + | (shift_mask if shift else 0) \ + | (group_mask if group else 0) + + # Prefer already known lesser shift states + if keysym in mapping and mapping[keysym][1] < shift_state: + continue + mapping[keysym] = (key_code, shift_state) + + return mapping + + +def char_to_keysym(char): + """Converts a unicode character to a *keysym*. + + :param str char: The unicode character. + + :return: the corresponding *keysym*, or ``0`` if it cannot be found + """ + ordinal = ord(char) + if ordinal < 0x100: + return ordinal + else: + return ordinal | 0x01000000 + + +def symbol_to_keysym(symbol): + """Converts a symbol name to a *keysym*. + + :param str symbol: The name of the symbol. + + :return: the corresponding *keysym*, or ``0`` if it cannot be found + """ + # First try simple translation, the try a module attribute of + # Xlib.keysymdef.xkb and fall back on our pre-generated table + return (0 + or Xlib.XK.string_to_keysym(symbol) + or getattr(Xlib.keysymdef.xkb, "XK_" + symbol, 0) + or SYMBOLS.get(symbol, (0,))[0]) + + +class ListenerMixin(object): + """A mixin for *X* event listeners. + + Subclasses should set a value for :attr:`_EVENTS` and implement + :meth:`_handle_message`. + """ + #: The events for which to listen + _EVENTS = tuple() + + #: We use this instance for parsing the binary data + _EVENT_PARSER = Xlib.protocol.rq.EventField(None) + + def _run(self): + self._display_stop = Xlib.display.Display() + self._display_record = Xlib.display.Display() + self._stopped = False + with display_manager(self._display_record) as dm: + self._context = dm.record_create_context( + 0, + [Xlib.ext.record.AllClients], + [{ + 'core_requests': (0, 0), + 'core_replies': (0, 0), + 'ext_requests': (0, 0, 0, 0), + 'ext_replies': (0, 0, 0, 0), + 'delivered_events': (0, 0), + 'device_events': self._EVENTS, + 'errors': (0, 0), + 'client_started': False, + 'client_died': False}]) + + # pylint: disable=W0702; we want to silence errors + try: + self._initialize(self._display_stop) + self._mark_ready() + if self.suppress: + with display_manager(self._display_stop) as dm: + self._suppress_start(dm) + self._display_record.record_enable_context( + self._context, self._handler) + except: + # This exception will have been passed to the main thread + pass + finally: + if self.suppress: + with display_manager(self._display_stop) as dm: + self._suppress_stop(dm) + self._display_stop.record_disable_context(self._context) + self._display_stop.flush() + self._display_record.record_free_context(self._context) + self._display_stop.close() + self._display_record.close() + # pylint: enable=W0702 + + def _stop_platform(self): + if not hasattr(self, '_context'): + self.wait() + + # Do this asynchronously to avoid deadlocks + self._display_record.record_disable_context(self._context) + + def _suppress_start(self, display): + """Starts suppressing events. + + :param Xlib.display.Display display: The display for which to suppress + events. + """ + raise NotImplementedError() + + def _suppress_stop(self, display): + """Starts suppressing events. + + :param Xlib.display.Display display: The display for which to suppress + events. + """ + raise NotImplementedError() + + @property + def _event_mask(self): + """The event mask. + """ + return functools.reduce(operator.__or__, self._EVENTS, 0) + + @AbstractListener._emitter + def _handler(self, events): + """The callback registered with *X* for mouse events. + + This method will parse the response and call the callbacks registered + on initialisation. + + :param events: The events passed by *X*. This is a binary block + parsable by :attr:`_EVENT_PARSER`. + """ + if not self.running: + raise self.StopException() + + data = events.data + + while data and len(data): + event, data = self._EVENT_PARSER.parse_binary_value( + data, self._display_record.display, None, None) + + injected = event.send_event + self._handle_message(self._display_stop, event, injected) + + def _initialize(self, display): + """Initialises this listener. + + This method is called immediately before the event loop, from the + handler thread. + + :param display: The display being used. + """ + pass + + def _handle_message(self, display, event, injected): + """The device specific callback handler. + + This method calls the appropriate callback registered when this + listener was created based on the event. + + :param display: The display being used. + + :param event: The event. + + :param bool injected: Whether the event was injected. + """ + pass diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/_util/xorg_keysyms.py b/CLI/venv/lib/python3.12/site-packages/pynput/_util/xorg_keysyms.py new file mode 100644 index 0000000..7505e89 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/_util/xorg_keysyms.py @@ -0,0 +1,1715 @@ +# coding: utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +# pylint: disable=C0111,C0302 + +SYMBOLS = { + '0': (0x0030, u'\u0030'), + '1': (0x0031, u'\u0031'), + '2': (0x0032, u'\u0032'), + '3': (0x0033, u'\u0033'), + '4': (0x0034, u'\u0034'), + '5': (0x0035, u'\u0035'), + '6': (0x0036, u'\u0036'), + '7': (0x0037, u'\u0037'), + '8': (0x0038, u'\u0038'), + '9': (0x0039, u'\u0039'), + 'A': (0x0041, u'\u0041'), + 'AE': (0x00c6, u'\u00C6'), + 'Aacute': (0x00c1, u'\u00C1'), + 'Abelowdot': (0x1001ea0, u'\u1EA0'), + 'Abreve': (0x01c3, u'\u0102'), + 'Abreveacute': (0x1001eae, u'\u1EAE'), + 'Abrevebelowdot': (0x1001eb6, u'\u1EB6'), + 'Abrevegrave': (0x1001eb0, u'\u1EB0'), + 'Abrevehook': (0x1001eb2, u'\u1EB2'), + 'Abrevetilde': (0x1001eb4, u'\u1EB4'), + 'Acircumflex': (0x00c2, u'\u00C2'), + 'Acircumflexacute': (0x1001ea4, u'\u1EA4'), + 'Acircumflexbelowdot': (0x1001eac, u'\u1EAC'), + 'Acircumflexgrave': (0x1001ea6, u'\u1EA6'), + 'Acircumflexhook': (0x1001ea8, u'\u1EA8'), + 'Acircumflextilde': (0x1001eaa, u'\u1EAA'), + 'Adiaeresis': (0x00c4, u'\u00C4'), + 'Agrave': (0x00c0, u'\u00C0'), + 'Ahook': (0x1001ea2, u'\u1EA2'), + 'Amacron': (0x03c0, u'\u0100'), + 'Aogonek': (0x01a1, u'\u0104'), + 'Arabic_0': (0x1000660, u'\u0660'), + 'Arabic_1': (0x1000661, u'\u0661'), + 'Arabic_2': (0x1000662, u'\u0662'), + 'Arabic_3': (0x1000663, u'\u0663'), + 'Arabic_4': (0x1000664, u'\u0664'), + 'Arabic_5': (0x1000665, u'\u0665'), + 'Arabic_6': (0x1000666, u'\u0666'), + 'Arabic_7': (0x1000667, u'\u0667'), + 'Arabic_8': (0x1000668, u'\u0668'), + 'Arabic_9': (0x1000669, u'\u0669'), + 'Arabic_ain': (0x05d9, u'\u0639'), + 'Arabic_alef': (0x05c7, u'\u0627'), + 'Arabic_alefmaksura': (0x05e9, u'\u0649'), + 'Arabic_beh': (0x05c8, u'\u0628'), + 'Arabic_comma': (0x05ac, u'\u060C'), + 'Arabic_dad': (0x05d6, u'\u0636'), + 'Arabic_dal': (0x05cf, u'\u062F'), + 'Arabic_damma': (0x05ef, u'\u064F'), + 'Arabic_dammatan': (0x05ec, u'\u064C'), + 'Arabic_ddal': (0x1000688, u'\u0688'), + 'Arabic_farsi_yeh': (0x10006cc, u'\u06CC'), + 'Arabic_fatha': (0x05ee, u'\u064E'), + 'Arabic_fathatan': (0x05eb, u'\u064B'), + 'Arabic_feh': (0x05e1, u'\u0641'), + 'Arabic_fullstop': (0x10006d4, u'\u06D4'), + 'Arabic_gaf': (0x10006af, u'\u06AF'), + 'Arabic_ghain': (0x05da, u'\u063A'), + 'Arabic_ha': (0x05e7, u'\u0647'), + 'Arabic_hah': (0x05cd, u'\u062D'), + 'Arabic_hamza': (0x05c1, u'\u0621'), + 'Arabic_hamza_above': (0x1000654, u'\u0654'), + 'Arabic_hamza_below': (0x1000655, u'\u0655'), + 'Arabic_hamzaonalef': (0x05c3, u'\u0623'), + 'Arabic_hamzaonwaw': (0x05c4, u'\u0624'), + 'Arabic_hamzaonyeh': (0x05c6, u'\u0626'), + 'Arabic_hamzaunderalef': (0x05c5, u'\u0625'), + 'Arabic_heh_doachashmee': (0x10006be, u'\u06BE'), + 'Arabic_heh_goal': (0x10006c1, u'\u06C1'), + 'Arabic_jeem': (0x05cc, u'\u062C'), + 'Arabic_jeh': (0x1000698, u'\u0698'), + 'Arabic_kaf': (0x05e3, u'\u0643'), + 'Arabic_kasra': (0x05f0, u'\u0650'), + 'Arabic_kasratan': (0x05ed, u'\u064D'), + 'Arabic_keheh': (0x10006a9, u'\u06A9'), + 'Arabic_khah': (0x05ce, u'\u062E'), + 'Arabic_lam': (0x05e4, u'\u0644'), + 'Arabic_madda_above': (0x1000653, u'\u0653'), + 'Arabic_maddaonalef': (0x05c2, u'\u0622'), + 'Arabic_meem': (0x05e5, u'\u0645'), + 'Arabic_noon': (0x05e6, u'\u0646'), + 'Arabic_noon_ghunna': (0x10006ba, u'\u06BA'), + 'Arabic_peh': (0x100067e, u'\u067E'), + 'Arabic_percent': (0x100066a, u'\u066A'), + 'Arabic_qaf': (0x05e2, u'\u0642'), + 'Arabic_question_mark': (0x05bf, u'\u061F'), + 'Arabic_ra': (0x05d1, u'\u0631'), + 'Arabic_rreh': (0x1000691, u'\u0691'), + 'Arabic_sad': (0x05d5, u'\u0635'), + 'Arabic_seen': (0x05d3, u'\u0633'), + 'Arabic_semicolon': (0x05bb, u'\u061B'), + 'Arabic_shadda': (0x05f1, u'\u0651'), + 'Arabic_sheen': (0x05d4, u'\u0634'), + 'Arabic_sukun': (0x05f2, u'\u0652'), + 'Arabic_superscript_alef': (0x1000670, u'\u0670'), + 'Arabic_tah': (0x05d7, u'\u0637'), + 'Arabic_tatweel': (0x05e0, u'\u0640'), + 'Arabic_tcheh': (0x1000686, u'\u0686'), + 'Arabic_teh': (0x05ca, u'\u062A'), + 'Arabic_tehmarbuta': (0x05c9, u'\u0629'), + 'Arabic_thal': (0x05d0, u'\u0630'), + 'Arabic_theh': (0x05cb, u'\u062B'), + 'Arabic_tteh': (0x1000679, u'\u0679'), + 'Arabic_veh': (0x10006a4, u'\u06A4'), + 'Arabic_waw': (0x05e8, u'\u0648'), + 'Arabic_yeh': (0x05ea, u'\u064A'), + 'Arabic_yeh_baree': (0x10006d2, u'\u06D2'), + 'Arabic_zah': (0x05d8, u'\u0638'), + 'Arabic_zain': (0x05d2, u'\u0632'), + 'Aring': (0x00c5, u'\u00C5'), + 'Armenian_AT': (0x1000538, u'\u0538'), + 'Armenian_AYB': (0x1000531, u'\u0531'), + 'Armenian_BEN': (0x1000532, u'\u0532'), + 'Armenian_CHA': (0x1000549, u'\u0549'), + 'Armenian_DA': (0x1000534, u'\u0534'), + 'Armenian_DZA': (0x1000541, u'\u0541'), + 'Armenian_E': (0x1000537, u'\u0537'), + 'Armenian_FE': (0x1000556, u'\u0556'), + 'Armenian_GHAT': (0x1000542, u'\u0542'), + 'Armenian_GIM': (0x1000533, u'\u0533'), + 'Armenian_HI': (0x1000545, u'\u0545'), + 'Armenian_HO': (0x1000540, u'\u0540'), + 'Armenian_INI': (0x100053b, u'\u053B'), + 'Armenian_JE': (0x100054b, u'\u054B'), + 'Armenian_KE': (0x1000554, u'\u0554'), + 'Armenian_KEN': (0x100053f, u'\u053F'), + 'Armenian_KHE': (0x100053d, u'\u053D'), + 'Armenian_LYUN': (0x100053c, u'\u053C'), + 'Armenian_MEN': (0x1000544, u'\u0544'), + 'Armenian_NU': (0x1000546, u'\u0546'), + 'Armenian_O': (0x1000555, u'\u0555'), + 'Armenian_PE': (0x100054a, u'\u054A'), + 'Armenian_PYUR': (0x1000553, u'\u0553'), + 'Armenian_RA': (0x100054c, u'\u054C'), + 'Armenian_RE': (0x1000550, u'\u0550'), + 'Armenian_SE': (0x100054d, u'\u054D'), + 'Armenian_SHA': (0x1000547, u'\u0547'), + 'Armenian_TCHE': (0x1000543, u'\u0543'), + 'Armenian_TO': (0x1000539, u'\u0539'), + 'Armenian_TSA': (0x100053e, u'\u053E'), + 'Armenian_TSO': (0x1000551, u'\u0551'), + 'Armenian_TYUN': (0x100054f, u'\u054F'), + 'Armenian_VEV': (0x100054e, u'\u054E'), + 'Armenian_VO': (0x1000548, u'\u0548'), + 'Armenian_VYUN': (0x1000552, u'\u0552'), + 'Armenian_YECH': (0x1000535, u'\u0535'), + 'Armenian_ZA': (0x1000536, u'\u0536'), + 'Armenian_ZHE': (0x100053a, u'\u053A'), + 'Armenian_accent': (0x100055b, u'\u055B'), + 'Armenian_amanak': (0x100055c, u'\u055C'), + 'Armenian_apostrophe': (0x100055a, u'\u055A'), + 'Armenian_at': (0x1000568, u'\u0568'), + 'Armenian_ayb': (0x1000561, u'\u0561'), + 'Armenian_ben': (0x1000562, u'\u0562'), + 'Armenian_but': (0x100055d, u'\u055D'), + 'Armenian_cha': (0x1000579, u'\u0579'), + 'Armenian_da': (0x1000564, u'\u0564'), + 'Armenian_dza': (0x1000571, u'\u0571'), + 'Armenian_e': (0x1000567, u'\u0567'), + 'Armenian_exclam': (0x100055c, u'\u055C'), + 'Armenian_fe': (0x1000586, u'\u0586'), + 'Armenian_full_stop': (0x1000589, u'\u0589'), + 'Armenian_ghat': (0x1000572, u'\u0572'), + 'Armenian_gim': (0x1000563, u'\u0563'), + 'Armenian_hi': (0x1000575, u'\u0575'), + 'Armenian_ho': (0x1000570, u'\u0570'), + 'Armenian_hyphen': (0x100058a, u'\u058A'), + 'Armenian_ini': (0x100056b, u'\u056B'), + 'Armenian_je': (0x100057b, u'\u057B'), + 'Armenian_ke': (0x1000584, u'\u0584'), + 'Armenian_ken': (0x100056f, u'\u056F'), + 'Armenian_khe': (0x100056d, u'\u056D'), + 'Armenian_ligature_ew': (0x1000587, u'\u0587'), + 'Armenian_lyun': (0x100056c, u'\u056C'), + 'Armenian_men': (0x1000574, u'\u0574'), + 'Armenian_nu': (0x1000576, u'\u0576'), + 'Armenian_o': (0x1000585, u'\u0585'), + 'Armenian_paruyk': (0x100055e, u'\u055E'), + 'Armenian_pe': (0x100057a, u'\u057A'), + 'Armenian_pyur': (0x1000583, u'\u0583'), + 'Armenian_question': (0x100055e, u'\u055E'), + 'Armenian_ra': (0x100057c, u'\u057C'), + 'Armenian_re': (0x1000580, u'\u0580'), + 'Armenian_se': (0x100057d, u'\u057D'), + 'Armenian_separation_mark': (0x100055d, u'\u055D'), + 'Armenian_sha': (0x1000577, u'\u0577'), + 'Armenian_shesht': (0x100055b, u'\u055B'), + 'Armenian_tche': (0x1000573, u'\u0573'), + 'Armenian_to': (0x1000569, u'\u0569'), + 'Armenian_tsa': (0x100056e, u'\u056E'), + 'Armenian_tso': (0x1000581, u'\u0581'), + 'Armenian_tyun': (0x100057f, u'\u057F'), + 'Armenian_verjaket': (0x1000589, u'\u0589'), + 'Armenian_vev': (0x100057e, u'\u057E'), + 'Armenian_vo': (0x1000578, u'\u0578'), + 'Armenian_vyun': (0x1000582, u'\u0582'), + 'Armenian_yech': (0x1000565, u'\u0565'), + 'Armenian_yentamna': (0x100058a, u'\u058A'), + 'Armenian_za': (0x1000566, u'\u0566'), + 'Armenian_zhe': (0x100056a, u'\u056A'), + 'Atilde': (0x00c3, u'\u00C3'), + 'B': (0x0042, u'\u0042'), + 'Babovedot': (0x1001e02, u'\u1E02'), + 'Byelorussian_SHORTU': (0x06be, u'\u040E'), + 'Byelorussian_shortu': (0x06ae, u'\u045E'), + 'C': (0x0043, u'\u0043'), + 'Cabovedot': (0x02c5, u'\u010A'), + 'Cacute': (0x01c6, u'\u0106'), + 'Ccaron': (0x01c8, u'\u010C'), + 'Ccedilla': (0x00c7, u'\u00C7'), + 'Ccircumflex': (0x02c6, u'\u0108'), + 'ColonSign': (0x10020a1, u'\u20A1'), + 'CruzeiroSign': (0x10020a2, u'\u20A2'), + 'Cyrillic_A': (0x06e1, u'\u0410'), + 'Cyrillic_BE': (0x06e2, u'\u0411'), + 'Cyrillic_CHE': (0x06fe, u'\u0427'), + 'Cyrillic_CHE_descender': (0x10004b6, u'\u04B6'), + 'Cyrillic_CHE_vertstroke': (0x10004b8, u'\u04B8'), + 'Cyrillic_DE': (0x06e4, u'\u0414'), + 'Cyrillic_DZHE': (0x06bf, u'\u040F'), + 'Cyrillic_E': (0x06fc, u'\u042D'), + 'Cyrillic_EF': (0x06e6, u'\u0424'), + 'Cyrillic_EL': (0x06ec, u'\u041B'), + 'Cyrillic_EM': (0x06ed, u'\u041C'), + 'Cyrillic_EN': (0x06ee, u'\u041D'), + 'Cyrillic_EN_descender': (0x10004a2, u'\u04A2'), + 'Cyrillic_ER': (0x06f2, u'\u0420'), + 'Cyrillic_ES': (0x06f3, u'\u0421'), + 'Cyrillic_GHE': (0x06e7, u'\u0413'), + 'Cyrillic_GHE_bar': (0x1000492, u'\u0492'), + 'Cyrillic_HA': (0x06e8, u'\u0425'), + 'Cyrillic_HARDSIGN': (0x06ff, u'\u042A'), + 'Cyrillic_HA_descender': (0x10004b2, u'\u04B2'), + 'Cyrillic_I': (0x06e9, u'\u0418'), + 'Cyrillic_IE': (0x06e5, u'\u0415'), + 'Cyrillic_IO': (0x06b3, u'\u0401'), + 'Cyrillic_I_macron': (0x10004e2, u'\u04E2'), + 'Cyrillic_JE': (0x06b8, u'\u0408'), + 'Cyrillic_KA': (0x06eb, u'\u041A'), + 'Cyrillic_KA_descender': (0x100049a, u'\u049A'), + 'Cyrillic_KA_vertstroke': (0x100049c, u'\u049C'), + 'Cyrillic_LJE': (0x06b9, u'\u0409'), + 'Cyrillic_NJE': (0x06ba, u'\u040A'), + 'Cyrillic_O': (0x06ef, u'\u041E'), + 'Cyrillic_O_bar': (0x10004e8, u'\u04E8'), + 'Cyrillic_PE': (0x06f0, u'\u041F'), + 'Cyrillic_SCHWA': (0x10004d8, u'\u04D8'), + 'Cyrillic_SHA': (0x06fb, u'\u0428'), + 'Cyrillic_SHCHA': (0x06fd, u'\u0429'), + 'Cyrillic_SHHA': (0x10004ba, u'\u04BA'), + 'Cyrillic_SHORTI': (0x06ea, u'\u0419'), + 'Cyrillic_SOFTSIGN': (0x06f8, u'\u042C'), + 'Cyrillic_TE': (0x06f4, u'\u0422'), + 'Cyrillic_TSE': (0x06e3, u'\u0426'), + 'Cyrillic_U': (0x06f5, u'\u0423'), + 'Cyrillic_U_macron': (0x10004ee, u'\u04EE'), + 'Cyrillic_U_straight': (0x10004ae, u'\u04AE'), + 'Cyrillic_U_straight_bar': (0x10004b0, u'\u04B0'), + 'Cyrillic_VE': (0x06f7, u'\u0412'), + 'Cyrillic_YA': (0x06f1, u'\u042F'), + 'Cyrillic_YERU': (0x06f9, u'\u042B'), + 'Cyrillic_YU': (0x06e0, u'\u042E'), + 'Cyrillic_ZE': (0x06fa, u'\u0417'), + 'Cyrillic_ZHE': (0x06f6, u'\u0416'), + 'Cyrillic_ZHE_descender': (0x1000496, u'\u0496'), + 'Cyrillic_a': (0x06c1, u'\u0430'), + 'Cyrillic_be': (0x06c2, u'\u0431'), + 'Cyrillic_che': (0x06de, u'\u0447'), + 'Cyrillic_che_descender': (0x10004b7, u'\u04B7'), + 'Cyrillic_che_vertstroke': (0x10004b9, u'\u04B9'), + 'Cyrillic_de': (0x06c4, u'\u0434'), + 'Cyrillic_dzhe': (0x06af, u'\u045F'), + 'Cyrillic_e': (0x06dc, u'\u044D'), + 'Cyrillic_ef': (0x06c6, u'\u0444'), + 'Cyrillic_el': (0x06cc, u'\u043B'), + 'Cyrillic_em': (0x06cd, u'\u043C'), + 'Cyrillic_en': (0x06ce, u'\u043D'), + 'Cyrillic_en_descender': (0x10004a3, u'\u04A3'), + 'Cyrillic_er': (0x06d2, u'\u0440'), + 'Cyrillic_es': (0x06d3, u'\u0441'), + 'Cyrillic_ghe': (0x06c7, u'\u0433'), + 'Cyrillic_ghe_bar': (0x1000493, u'\u0493'), + 'Cyrillic_ha': (0x06c8, u'\u0445'), + 'Cyrillic_ha_descender': (0x10004b3, u'\u04B3'), + 'Cyrillic_hardsign': (0x06df, u'\u044A'), + 'Cyrillic_i': (0x06c9, u'\u0438'), + 'Cyrillic_i_macron': (0x10004e3, u'\u04E3'), + 'Cyrillic_ie': (0x06c5, u'\u0435'), + 'Cyrillic_io': (0x06a3, u'\u0451'), + 'Cyrillic_je': (0x06a8, u'\u0458'), + 'Cyrillic_ka': (0x06cb, u'\u043A'), + 'Cyrillic_ka_descender': (0x100049b, u'\u049B'), + 'Cyrillic_ka_vertstroke': (0x100049d, u'\u049D'), + 'Cyrillic_lje': (0x06a9, u'\u0459'), + 'Cyrillic_nje': (0x06aa, u'\u045A'), + 'Cyrillic_o': (0x06cf, u'\u043E'), + 'Cyrillic_o_bar': (0x10004e9, u'\u04E9'), + 'Cyrillic_pe': (0x06d0, u'\u043F'), + 'Cyrillic_schwa': (0x10004d9, u'\u04D9'), + 'Cyrillic_sha': (0x06db, u'\u0448'), + 'Cyrillic_shcha': (0x06dd, u'\u0449'), + 'Cyrillic_shha': (0x10004bb, u'\u04BB'), + 'Cyrillic_shorti': (0x06ca, u'\u0439'), + 'Cyrillic_softsign': (0x06d8, u'\u044C'), + 'Cyrillic_te': (0x06d4, u'\u0442'), + 'Cyrillic_tse': (0x06c3, u'\u0446'), + 'Cyrillic_u': (0x06d5, u'\u0443'), + 'Cyrillic_u_macron': (0x10004ef, u'\u04EF'), + 'Cyrillic_u_straight': (0x10004af, u'\u04AF'), + 'Cyrillic_u_straight_bar': (0x10004b1, u'\u04B1'), + 'Cyrillic_ve': (0x06d7, u'\u0432'), + 'Cyrillic_ya': (0x06d1, u'\u044F'), + 'Cyrillic_yeru': (0x06d9, u'\u044B'), + 'Cyrillic_yu': (0x06c0, u'\u044E'), + 'Cyrillic_ze': (0x06da, u'\u0437'), + 'Cyrillic_zhe': (0x06d6, u'\u0436'), + 'Cyrillic_zhe_descender': (0x1000497, u'\u0497'), + 'D': (0x0044, u'\u0044'), + 'Dabovedot': (0x1001e0a, u'\u1E0A'), + 'Dcaron': (0x01cf, u'\u010E'), + 'DongSign': (0x10020ab, u'\u20AB'), + 'Dstroke': (0x01d0, u'\u0110'), + 'E': (0x0045, u'\u0045'), + 'ENG': (0x03bd, u'\u014A'), + 'ETH': (0x00d0, u'\u00D0'), + 'EZH': (0x10001b7, u'\u01B7'), + 'Eabovedot': (0x03cc, u'\u0116'), + 'Eacute': (0x00c9, u'\u00C9'), + 'Ebelowdot': (0x1001eb8, u'\u1EB8'), + 'Ecaron': (0x01cc, u'\u011A'), + 'Ecircumflex': (0x00ca, u'\u00CA'), + 'Ecircumflexacute': (0x1001ebe, u'\u1EBE'), + 'Ecircumflexbelowdot': (0x1001ec6, u'\u1EC6'), + 'Ecircumflexgrave': (0x1001ec0, u'\u1EC0'), + 'Ecircumflexhook': (0x1001ec2, u'\u1EC2'), + 'Ecircumflextilde': (0x1001ec4, u'\u1EC4'), + 'EcuSign': (0x10020a0, u'\u20A0'), + 'Ediaeresis': (0x00cb, u'\u00CB'), + 'Egrave': (0x00c8, u'\u00C8'), + 'Ehook': (0x1001eba, u'\u1EBA'), + 'Emacron': (0x03aa, u'\u0112'), + 'Eogonek': (0x01ca, u'\u0118'), + 'Etilde': (0x1001ebc, u'\u1EBC'), + 'EuroSign': (0x20ac, u'\u20AC'), + 'F': (0x0046, u'\u0046'), + 'FFrancSign': (0x10020a3, u'\u20A3'), + 'Fabovedot': (0x1001e1e, u'\u1E1E'), + 'Farsi_0': (0x10006f0, u'\u06F0'), + 'Farsi_1': (0x10006f1, u'\u06F1'), + 'Farsi_2': (0x10006f2, u'\u06F2'), + 'Farsi_3': (0x10006f3, u'\u06F3'), + 'Farsi_4': (0x10006f4, u'\u06F4'), + 'Farsi_5': (0x10006f5, u'\u06F5'), + 'Farsi_6': (0x10006f6, u'\u06F6'), + 'Farsi_7': (0x10006f7, u'\u06F7'), + 'Farsi_8': (0x10006f8, u'\u06F8'), + 'Farsi_9': (0x10006f9, u'\u06F9'), + 'Farsi_yeh': (0x10006cc, u'\u06CC'), + 'G': (0x0047, u'\u0047'), + 'Gabovedot': (0x02d5, u'\u0120'), + 'Gbreve': (0x02ab, u'\u011E'), + 'Gcaron': (0x10001e6, u'\u01E6'), + 'Gcedilla': (0x03ab, u'\u0122'), + 'Gcircumflex': (0x02d8, u'\u011C'), + 'Georgian_an': (0x10010d0, u'\u10D0'), + 'Georgian_ban': (0x10010d1, u'\u10D1'), + 'Georgian_can': (0x10010ea, u'\u10EA'), + 'Georgian_char': (0x10010ed, u'\u10ED'), + 'Georgian_chin': (0x10010e9, u'\u10E9'), + 'Georgian_cil': (0x10010ec, u'\u10EC'), + 'Georgian_don': (0x10010d3, u'\u10D3'), + 'Georgian_en': (0x10010d4, u'\u10D4'), + 'Georgian_fi': (0x10010f6, u'\u10F6'), + 'Georgian_gan': (0x10010d2, u'\u10D2'), + 'Georgian_ghan': (0x10010e6, u'\u10E6'), + 'Georgian_hae': (0x10010f0, u'\u10F0'), + 'Georgian_har': (0x10010f4, u'\u10F4'), + 'Georgian_he': (0x10010f1, u'\u10F1'), + 'Georgian_hie': (0x10010f2, u'\u10F2'), + 'Georgian_hoe': (0x10010f5, u'\u10F5'), + 'Georgian_in': (0x10010d8, u'\u10D8'), + 'Georgian_jhan': (0x10010ef, u'\u10EF'), + 'Georgian_jil': (0x10010eb, u'\u10EB'), + 'Georgian_kan': (0x10010d9, u'\u10D9'), + 'Georgian_khar': (0x10010e5, u'\u10E5'), + 'Georgian_las': (0x10010da, u'\u10DA'), + 'Georgian_man': (0x10010db, u'\u10DB'), + 'Georgian_nar': (0x10010dc, u'\u10DC'), + 'Georgian_on': (0x10010dd, u'\u10DD'), + 'Georgian_par': (0x10010de, u'\u10DE'), + 'Georgian_phar': (0x10010e4, u'\u10E4'), + 'Georgian_qar': (0x10010e7, u'\u10E7'), + 'Georgian_rae': (0x10010e0, u'\u10E0'), + 'Georgian_san': (0x10010e1, u'\u10E1'), + 'Georgian_shin': (0x10010e8, u'\u10E8'), + 'Georgian_tan': (0x10010d7, u'\u10D7'), + 'Georgian_tar': (0x10010e2, u'\u10E2'), + 'Georgian_un': (0x10010e3, u'\u10E3'), + 'Georgian_vin': (0x10010d5, u'\u10D5'), + 'Georgian_we': (0x10010f3, u'\u10F3'), + 'Georgian_xan': (0x10010ee, u'\u10EE'), + 'Georgian_zen': (0x10010d6, u'\u10D6'), + 'Georgian_zhar': (0x10010df, u'\u10DF'), + 'Greek_ALPHA': (0x07c1, u'\u0391'), + 'Greek_ALPHAaccent': (0x07a1, u'\u0386'), + 'Greek_BETA': (0x07c2, u'\u0392'), + 'Greek_CHI': (0x07d7, u'\u03A7'), + 'Greek_DELTA': (0x07c4, u'\u0394'), + 'Greek_EPSILON': (0x07c5, u'\u0395'), + 'Greek_EPSILONaccent': (0x07a2, u'\u0388'), + 'Greek_ETA': (0x07c7, u'\u0397'), + 'Greek_ETAaccent': (0x07a3, u'\u0389'), + 'Greek_GAMMA': (0x07c3, u'\u0393'), + 'Greek_IOTA': (0x07c9, u'\u0399'), + 'Greek_IOTAaccent': (0x07a4, u'\u038A'), + 'Greek_IOTAdieresis': (0x07a5, u'\u03AA'), + 'Greek_KAPPA': (0x07ca, u'\u039A'), + 'Greek_LAMBDA': (0x07cb, u'\u039B'), + 'Greek_LAMDA': (0x07cb, u'\u039B'), + 'Greek_MU': (0x07cc, u'\u039C'), + 'Greek_NU': (0x07cd, u'\u039D'), + 'Greek_OMEGA': (0x07d9, u'\u03A9'), + 'Greek_OMEGAaccent': (0x07ab, u'\u038F'), + 'Greek_OMICRON': (0x07cf, u'\u039F'), + 'Greek_OMICRONaccent': (0x07a7, u'\u038C'), + 'Greek_PHI': (0x07d6, u'\u03A6'), + 'Greek_PI': (0x07d0, u'\u03A0'), + 'Greek_PSI': (0x07d8, u'\u03A8'), + 'Greek_RHO': (0x07d1, u'\u03A1'), + 'Greek_SIGMA': (0x07d2, u'\u03A3'), + 'Greek_TAU': (0x07d4, u'\u03A4'), + 'Greek_THETA': (0x07c8, u'\u0398'), + 'Greek_UPSILON': (0x07d5, u'\u03A5'), + 'Greek_UPSILONaccent': (0x07a8, u'\u038E'), + 'Greek_UPSILONdieresis': (0x07a9, u'\u03AB'), + 'Greek_XI': (0x07ce, u'\u039E'), + 'Greek_ZETA': (0x07c6, u'\u0396'), + 'Greek_accentdieresis': (0x07ae, u'\u0385'), + 'Greek_alpha': (0x07e1, u'\u03B1'), + 'Greek_alphaaccent': (0x07b1, u'\u03AC'), + 'Greek_beta': (0x07e2, u'\u03B2'), + 'Greek_chi': (0x07f7, u'\u03C7'), + 'Greek_delta': (0x07e4, u'\u03B4'), + 'Greek_epsilon': (0x07e5, u'\u03B5'), + 'Greek_epsilonaccent': (0x07b2, u'\u03AD'), + 'Greek_eta': (0x07e7, u'\u03B7'), + 'Greek_etaaccent': (0x07b3, u'\u03AE'), + 'Greek_finalsmallsigma': (0x07f3, u'\u03C2'), + 'Greek_gamma': (0x07e3, u'\u03B3'), + 'Greek_horizbar': (0x07af, u'\u2015'), + 'Greek_iota': (0x07e9, u'\u03B9'), + 'Greek_iotaaccent': (0x07b4, u'\u03AF'), + 'Greek_iotaaccentdieresis': (0x07b6, u'\u0390'), + 'Greek_iotadieresis': (0x07b5, u'\u03CA'), + 'Greek_kappa': (0x07ea, u'\u03BA'), + 'Greek_lambda': (0x07eb, u'\u03BB'), + 'Greek_lamda': (0x07eb, u'\u03BB'), + 'Greek_mu': (0x07ec, u'\u03BC'), + 'Greek_nu': (0x07ed, u'\u03BD'), + 'Greek_omega': (0x07f9, u'\u03C9'), + 'Greek_omegaaccent': (0x07bb, u'\u03CE'), + 'Greek_omicron': (0x07ef, u'\u03BF'), + 'Greek_omicronaccent': (0x07b7, u'\u03CC'), + 'Greek_phi': (0x07f6, u'\u03C6'), + 'Greek_pi': (0x07f0, u'\u03C0'), + 'Greek_psi': (0x07f8, u'\u03C8'), + 'Greek_rho': (0x07f1, u'\u03C1'), + 'Greek_sigma': (0x07f2, u'\u03C3'), + 'Greek_tau': (0x07f4, u'\u03C4'), + 'Greek_theta': (0x07e8, u'\u03B8'), + 'Greek_upsilon': (0x07f5, u'\u03C5'), + 'Greek_upsilonaccent': (0x07b8, u'\u03CD'), + 'Greek_upsilonaccentdieresis': (0x07ba, u'\u03B0'), + 'Greek_upsilondieresis': (0x07b9, u'\u03CB'), + 'Greek_xi': (0x07ee, u'\u03BE'), + 'Greek_zeta': (0x07e6, u'\u03B6'), + 'H': (0x0048, u'\u0048'), + 'Hcircumflex': (0x02a6, u'\u0124'), + 'Hstroke': (0x02a1, u'\u0126'), + 'I': (0x0049, u'\u0049'), + 'Iabovedot': (0x02a9, u'\u0130'), + 'Iacute': (0x00cd, u'\u00CD'), + 'Ibelowdot': (0x1001eca, u'\u1ECA'), + 'Ibreve': (0x100012c, u'\u012C'), + 'Icircumflex': (0x00ce, u'\u00CE'), + 'Idiaeresis': (0x00cf, u'\u00CF'), + 'Igrave': (0x00cc, u'\u00CC'), + 'Ihook': (0x1001ec8, u'\u1EC8'), + 'Imacron': (0x03cf, u'\u012A'), + 'Iogonek': (0x03c7, u'\u012E'), + 'Itilde': (0x03a5, u'\u0128'), + 'J': (0x004a, u'\u004A'), + 'Jcircumflex': (0x02ac, u'\u0134'), + 'K': (0x004b, u'\u004B'), + 'KP_0': (0xffb0, None), + 'KP_1': (0xffb1, None), + 'KP_2': (0xffb2, None), + 'KP_3': (0xffb3, None), + 'KP_4': (0xffb4, None), + 'KP_5': (0xffb5, None), + 'KP_6': (0xffb6, None), + 'KP_7': (0xffb7, None), + 'KP_8': (0xffb8, None), + 'KP_9': (0xffb9, None), + 'KP_Add': (0xffab, None), + 'KP_Begin': (0xff9d, None), + 'KP_Decimal': (0xffae, None), + 'KP_Delete': (0xff9f, None), + 'KP_Divide': (0xffaf, None), + 'KP_Down': (0xff99, None), + 'KP_End': (0xff9c, None), + 'KP_Enter': (0xff8d, None), + 'KP_Equal': (0xffbd, None), + 'KP_F1': (0xff91, None), + 'KP_F2': (0xff92, None), + 'KP_F3': (0xff93, None), + 'KP_F4': (0xff94, None), + 'KP_Home': (0xff95, None), + 'KP_Insert': (0xff9e, None), + 'KP_Left': (0xff96, None), + 'KP_Multiply': (0xffaa, None), + 'KP_Next': (0xff9b, None), + 'KP_Page_Down': (0xff9b, None), + 'KP_Page_Up': (0xff9a, None), + 'KP_Prior': (0xff9a, None), + 'KP_Right': (0xff98, None), + 'KP_Separator': (0xffac, None), + 'KP_Space': (0xff80, None), + 'KP_Subtract': (0xffad, None), + 'KP_Tab': (0xff89, None), + 'KP_Up': (0xff97, None), + 'Kcedilla': (0x03d3, u'\u0136'), + 'L': (0x004c, u'\u004C'), + 'Lacute': (0x01c5, u'\u0139'), + 'Lbelowdot': (0x1001e36, u'\u1E36'), + 'Lcaron': (0x01a5, u'\u013D'), + 'Lcedilla': (0x03a6, u'\u013B'), + 'LiraSign': (0x10020a4, u'\u20A4'), + 'Lstroke': (0x01a3, u'\u0141'), + 'M': (0x004d, u'\u004D'), + 'Mabovedot': (0x1001e40, u'\u1E40'), + 'Macedonia_DSE': (0x06b5, u'\u0405'), + 'Macedonia_GJE': (0x06b2, u'\u0403'), + 'Macedonia_KJE': (0x06bc, u'\u040C'), + 'Macedonia_dse': (0x06a5, u'\u0455'), + 'Macedonia_gje': (0x06a2, u'\u0453'), + 'Macedonia_kje': (0x06ac, u'\u045C'), + 'MillSign': (0x10020a5, u'\u20A5'), + 'N': (0x004e, u'\u004E'), + 'Nacute': (0x01d1, u'\u0143'), + 'NairaSign': (0x10020a6, u'\u20A6'), + 'Ncaron': (0x01d2, u'\u0147'), + 'Ncedilla': (0x03d1, u'\u0145'), + 'NewSheqelSign': (0x10020aa, u'\u20AA'), + 'Ntilde': (0x00d1, u'\u00D1'), + 'O': (0x004f, u'\u004F'), + 'OE': (0x13bc, u'\u0152'), + 'Oacute': (0x00d3, u'\u00D3'), + 'Obarred': (0x100019f, u'\u019F'), + 'Obelowdot': (0x1001ecc, u'\u1ECC'), + 'Ocaron': (0x10001d1, u'\u01D2'), + 'Ocircumflex': (0x00d4, u'\u00D4'), + 'Ocircumflexacute': (0x1001ed0, u'\u1ED0'), + 'Ocircumflexbelowdot': (0x1001ed8, u'\u1ED8'), + 'Ocircumflexgrave': (0x1001ed2, u'\u1ED2'), + 'Ocircumflexhook': (0x1001ed4, u'\u1ED4'), + 'Ocircumflextilde': (0x1001ed6, u'\u1ED6'), + 'Odiaeresis': (0x00d6, u'\u00D6'), + 'Odoubleacute': (0x01d5, u'\u0150'), + 'Ograve': (0x00d2, u'\u00D2'), + 'Ohook': (0x1001ece, u'\u1ECE'), + 'Ohorn': (0x10001a0, u'\u01A0'), + 'Ohornacute': (0x1001eda, u'\u1EDA'), + 'Ohornbelowdot': (0x1001ee2, u'\u1EE2'), + 'Ohorngrave': (0x1001edc, u'\u1EDC'), + 'Ohornhook': (0x1001ede, u'\u1EDE'), + 'Ohorntilde': (0x1001ee0, u'\u1EE0'), + 'Omacron': (0x03d2, u'\u014C'), + 'Ooblique': (0x00d8, u'\u00D8'), + 'Oslash': (0x00d8, u'\u00D8'), + 'Otilde': (0x00d5, u'\u00D5'), + 'P': (0x0050, u'\u0050'), + 'Pabovedot': (0x1001e56, u'\u1E56'), + 'PesetaSign': (0x10020a7, u'\u20A7'), + 'Q': (0x0051, u'\u0051'), + 'R': (0x0052, u'\u0052'), + 'Racute': (0x01c0, u'\u0154'), + 'Rcaron': (0x01d8, u'\u0158'), + 'Rcedilla': (0x03a3, u'\u0156'), + 'RupeeSign': (0x10020a8, u'\u20A8'), + 'S': (0x0053, u'\u0053'), + 'SCHWA': (0x100018f, u'\u018F'), + 'Sabovedot': (0x1001e60, u'\u1E60'), + 'Sacute': (0x01a6, u'\u015A'), + 'Scaron': (0x01a9, u'\u0160'), + 'Scedilla': (0x01aa, u'\u015E'), + 'Scircumflex': (0x02de, u'\u015C'), + 'Serbian_DJE': (0x06b1, u'\u0402'), + 'Serbian_TSHE': (0x06bb, u'\u040B'), + 'Serbian_dje': (0x06a1, u'\u0452'), + 'Serbian_tshe': (0x06ab, u'\u045B'), + 'Sinh_a': (0x1000d85, u'\u0D85'), + 'Sinh_aa': (0x1000d86, u'\u0D86'), + 'Sinh_aa2': (0x1000dcf, u'\u0DCF'), + 'Sinh_ae': (0x1000d87, u'\u0D87'), + 'Sinh_ae2': (0x1000dd0, u'\u0DD0'), + 'Sinh_aee': (0x1000d88, u'\u0D88'), + 'Sinh_aee2': (0x1000dd1, u'\u0DD1'), + 'Sinh_ai': (0x1000d93, u'\u0D93'), + 'Sinh_ai2': (0x1000ddb, u'\u0DDB'), + 'Sinh_al': (0x1000dca, u'\u0DCA'), + 'Sinh_au': (0x1000d96, u'\u0D96'), + 'Sinh_au2': (0x1000dde, u'\u0DDE'), + 'Sinh_ba': (0x1000db6, u'\u0DB6'), + 'Sinh_bha': (0x1000db7, u'\u0DB7'), + 'Sinh_ca': (0x1000da0, u'\u0DA0'), + 'Sinh_cha': (0x1000da1, u'\u0DA1'), + 'Sinh_dda': (0x1000da9, u'\u0DA9'), + 'Sinh_ddha': (0x1000daa, u'\u0DAA'), + 'Sinh_dha': (0x1000daf, u'\u0DAF'), + 'Sinh_dhha': (0x1000db0, u'\u0DB0'), + 'Sinh_e': (0x1000d91, u'\u0D91'), + 'Sinh_e2': (0x1000dd9, u'\u0DD9'), + 'Sinh_ee': (0x1000d92, u'\u0D92'), + 'Sinh_ee2': (0x1000dda, u'\u0DDA'), + 'Sinh_fa': (0x1000dc6, u'\u0DC6'), + 'Sinh_ga': (0x1000d9c, u'\u0D9C'), + 'Sinh_gha': (0x1000d9d, u'\u0D9D'), + 'Sinh_h2': (0x1000d83, u'\u0D83'), + 'Sinh_ha': (0x1000dc4, u'\u0DC4'), + 'Sinh_i': (0x1000d89, u'\u0D89'), + 'Sinh_i2': (0x1000dd2, u'\u0DD2'), + 'Sinh_ii': (0x1000d8a, u'\u0D8A'), + 'Sinh_ii2': (0x1000dd3, u'\u0DD3'), + 'Sinh_ja': (0x1000da2, u'\u0DA2'), + 'Sinh_jha': (0x1000da3, u'\u0DA3'), + 'Sinh_jnya': (0x1000da5, u'\u0DA5'), + 'Sinh_ka': (0x1000d9a, u'\u0D9A'), + 'Sinh_kha': (0x1000d9b, u'\u0D9B'), + 'Sinh_kunddaliya': (0x1000df4, u'\u0DF4'), + 'Sinh_la': (0x1000dbd, u'\u0DBD'), + 'Sinh_lla': (0x1000dc5, u'\u0DC5'), + 'Sinh_lu': (0x1000d8f, u'\u0D8F'), + 'Sinh_lu2': (0x1000ddf, u'\u0DDF'), + 'Sinh_luu': (0x1000d90, u'\u0D90'), + 'Sinh_luu2': (0x1000df3, u'\u0DF3'), + 'Sinh_ma': (0x1000db8, u'\u0DB8'), + 'Sinh_mba': (0x1000db9, u'\u0DB9'), + 'Sinh_na': (0x1000db1, u'\u0DB1'), + 'Sinh_ndda': (0x1000dac, u'\u0DAC'), + 'Sinh_ndha': (0x1000db3, u'\u0DB3'), + 'Sinh_ng': (0x1000d82, u'\u0D82'), + 'Sinh_ng2': (0x1000d9e, u'\u0D9E'), + 'Sinh_nga': (0x1000d9f, u'\u0D9F'), + 'Sinh_nja': (0x1000da6, u'\u0DA6'), + 'Sinh_nna': (0x1000dab, u'\u0DAB'), + 'Sinh_nya': (0x1000da4, u'\u0DA4'), + 'Sinh_o': (0x1000d94, u'\u0D94'), + 'Sinh_o2': (0x1000ddc, u'\u0DDC'), + 'Sinh_oo': (0x1000d95, u'\u0D95'), + 'Sinh_oo2': (0x1000ddd, u'\u0DDD'), + 'Sinh_pa': (0x1000db4, u'\u0DB4'), + 'Sinh_pha': (0x1000db5, u'\u0DB5'), + 'Sinh_ra': (0x1000dbb, u'\u0DBB'), + 'Sinh_ri': (0x1000d8d, u'\u0D8D'), + 'Sinh_rii': (0x1000d8e, u'\u0D8E'), + 'Sinh_ru2': (0x1000dd8, u'\u0DD8'), + 'Sinh_ruu2': (0x1000df2, u'\u0DF2'), + 'Sinh_sa': (0x1000dc3, u'\u0DC3'), + 'Sinh_sha': (0x1000dc1, u'\u0DC1'), + 'Sinh_ssha': (0x1000dc2, u'\u0DC2'), + 'Sinh_tha': (0x1000dad, u'\u0DAD'), + 'Sinh_thha': (0x1000dae, u'\u0DAE'), + 'Sinh_tta': (0x1000da7, u'\u0DA7'), + 'Sinh_ttha': (0x1000da8, u'\u0DA8'), + 'Sinh_u': (0x1000d8b, u'\u0D8B'), + 'Sinh_u2': (0x1000dd4, u'\u0DD4'), + 'Sinh_uu': (0x1000d8c, u'\u0D8C'), + 'Sinh_uu2': (0x1000dd6, u'\u0DD6'), + 'Sinh_va': (0x1000dc0, u'\u0DC0'), + 'Sinh_ya': (0x1000dba, u'\u0DBA'), + 'T': (0x0054, u'\u0054'), + 'THORN': (0x00de, u'\u00DE'), + 'Tabovedot': (0x1001e6a, u'\u1E6A'), + 'Tcaron': (0x01ab, u'\u0164'), + 'Tcedilla': (0x01de, u'\u0162'), + 'Thai_baht': (0x0ddf, u'\u0E3F'), + 'Thai_bobaimai': (0x0dba, u'\u0E1A'), + 'Thai_chochan': (0x0da8, u'\u0E08'), + 'Thai_chochang': (0x0daa, u'\u0E0A'), + 'Thai_choching': (0x0da9, u'\u0E09'), + 'Thai_chochoe': (0x0dac, u'\u0E0C'), + 'Thai_dochada': (0x0dae, u'\u0E0E'), + 'Thai_dodek': (0x0db4, u'\u0E14'), + 'Thai_fofa': (0x0dbd, u'\u0E1D'), + 'Thai_fofan': (0x0dbf, u'\u0E1F'), + 'Thai_hohip': (0x0dcb, u'\u0E2B'), + 'Thai_honokhuk': (0x0dce, u'\u0E2E'), + 'Thai_khokhai': (0x0da2, u'\u0E02'), + 'Thai_khokhon': (0x0da5, u'\u0E05'), + 'Thai_khokhuat': (0x0da3, u'\u0E03'), + 'Thai_khokhwai': (0x0da4, u'\u0E04'), + 'Thai_khorakhang': (0x0da6, u'\u0E06'), + 'Thai_kokai': (0x0da1, u'\u0E01'), + 'Thai_lakkhangyao': (0x0de5, u'\u0E45'), + 'Thai_lekchet': (0x0df7, u'\u0E57'), + 'Thai_lekha': (0x0df5, u'\u0E55'), + 'Thai_lekhok': (0x0df6, u'\u0E56'), + 'Thai_lekkao': (0x0df9, u'\u0E59'), + 'Thai_leknung': (0x0df1, u'\u0E51'), + 'Thai_lekpaet': (0x0df8, u'\u0E58'), + 'Thai_leksam': (0x0df3, u'\u0E53'), + 'Thai_leksi': (0x0df4, u'\u0E54'), + 'Thai_leksong': (0x0df2, u'\u0E52'), + 'Thai_leksun': (0x0df0, u'\u0E50'), + 'Thai_lochula': (0x0dcc, u'\u0E2C'), + 'Thai_loling': (0x0dc5, u'\u0E25'), + 'Thai_lu': (0x0dc6, u'\u0E26'), + 'Thai_maichattawa': (0x0deb, u'\u0E4B'), + 'Thai_maiek': (0x0de8, u'\u0E48'), + 'Thai_maihanakat': (0x0dd1, u'\u0E31'), + 'Thai_maitaikhu': (0x0de7, u'\u0E47'), + 'Thai_maitho': (0x0de9, u'\u0E49'), + 'Thai_maitri': (0x0dea, u'\u0E4A'), + 'Thai_maiyamok': (0x0de6, u'\u0E46'), + 'Thai_moma': (0x0dc1, u'\u0E21'), + 'Thai_ngongu': (0x0da7, u'\u0E07'), + 'Thai_nikhahit': (0x0ded, u'\u0E4D'), + 'Thai_nonen': (0x0db3, u'\u0E13'), + 'Thai_nonu': (0x0db9, u'\u0E19'), + 'Thai_oang': (0x0dcd, u'\u0E2D'), + 'Thai_paiyannoi': (0x0dcf, u'\u0E2F'), + 'Thai_phinthu': (0x0dda, u'\u0E3A'), + 'Thai_phophan': (0x0dbe, u'\u0E1E'), + 'Thai_phophung': (0x0dbc, u'\u0E1C'), + 'Thai_phosamphao': (0x0dc0, u'\u0E20'), + 'Thai_popla': (0x0dbb, u'\u0E1B'), + 'Thai_rorua': (0x0dc3, u'\u0E23'), + 'Thai_ru': (0x0dc4, u'\u0E24'), + 'Thai_saraa': (0x0dd0, u'\u0E30'), + 'Thai_saraaa': (0x0dd2, u'\u0E32'), + 'Thai_saraae': (0x0de1, u'\u0E41'), + 'Thai_saraaimaimalai': (0x0de4, u'\u0E44'), + 'Thai_saraaimaimuan': (0x0de3, u'\u0E43'), + 'Thai_saraam': (0x0dd3, u'\u0E33'), + 'Thai_sarae': (0x0de0, u'\u0E40'), + 'Thai_sarai': (0x0dd4, u'\u0E34'), + 'Thai_saraii': (0x0dd5, u'\u0E35'), + 'Thai_sarao': (0x0de2, u'\u0E42'), + 'Thai_sarau': (0x0dd8, u'\u0E38'), + 'Thai_saraue': (0x0dd6, u'\u0E36'), + 'Thai_sarauee': (0x0dd7, u'\u0E37'), + 'Thai_sarauu': (0x0dd9, u'\u0E39'), + 'Thai_sorusi': (0x0dc9, u'\u0E29'), + 'Thai_sosala': (0x0dc8, u'\u0E28'), + 'Thai_soso': (0x0dab, u'\u0E0B'), + 'Thai_sosua': (0x0dca, u'\u0E2A'), + 'Thai_thanthakhat': (0x0dec, u'\u0E4C'), + 'Thai_thonangmontho': (0x0db1, u'\u0E11'), + 'Thai_thophuthao': (0x0db2, u'\u0E12'), + 'Thai_thothahan': (0x0db7, u'\u0E17'), + 'Thai_thothan': (0x0db0, u'\u0E10'), + 'Thai_thothong': (0x0db8, u'\u0E18'), + 'Thai_thothung': (0x0db6, u'\u0E16'), + 'Thai_topatak': (0x0daf, u'\u0E0F'), + 'Thai_totao': (0x0db5, u'\u0E15'), + 'Thai_wowaen': (0x0dc7, u'\u0E27'), + 'Thai_yoyak': (0x0dc2, u'\u0E22'), + 'Thai_yoying': (0x0dad, u'\u0E0D'), + 'Tslash': (0x03ac, u'\u0166'), + 'U': (0x0055, u'\u0055'), + 'Uacute': (0x00da, u'\u00DA'), + 'Ubelowdot': (0x1001ee4, u'\u1EE4'), + 'Ubreve': (0x02dd, u'\u016C'), + 'Ucircumflex': (0x00db, u'\u00DB'), + 'Udiaeresis': (0x00dc, u'\u00DC'), + 'Udoubleacute': (0x01db, u'\u0170'), + 'Ugrave': (0x00d9, u'\u00D9'), + 'Uhook': (0x1001ee6, u'\u1EE6'), + 'Uhorn': (0x10001af, u'\u01AF'), + 'Uhornacute': (0x1001ee8, u'\u1EE8'), + 'Uhornbelowdot': (0x1001ef0, u'\u1EF0'), + 'Uhorngrave': (0x1001eea, u'\u1EEA'), + 'Uhornhook': (0x1001eec, u'\u1EEC'), + 'Uhorntilde': (0x1001eee, u'\u1EEE'), + 'Ukrainian_GHE_WITH_UPTURN': (0x06bd, u'\u0490'), + 'Ukrainian_I': (0x06b6, u'\u0406'), + 'Ukrainian_IE': (0x06b4, u'\u0404'), + 'Ukrainian_YI': (0x06b7, u'\u0407'), + 'Ukrainian_ghe_with_upturn': (0x06ad, u'\u0491'), + 'Ukrainian_i': (0x06a6, u'\u0456'), + 'Ukrainian_ie': (0x06a4, u'\u0454'), + 'Ukrainian_yi': (0x06a7, u'\u0457'), + 'Umacron': (0x03de, u'\u016A'), + 'Uogonek': (0x03d9, u'\u0172'), + 'Uring': (0x01d9, u'\u016E'), + 'Utilde': (0x03dd, u'\u0168'), + 'V': (0x0056, u'\u0056'), + 'W': (0x0057, u'\u0057'), + 'Wacute': (0x1001e82, u'\u1E82'), + 'Wcircumflex': (0x1000174, u'\u0174'), + 'Wdiaeresis': (0x1001e84, u'\u1E84'), + 'Wgrave': (0x1001e80, u'\u1E80'), + 'WonSign': (0x10020a9, u'\u20A9'), + 'X': (0x0058, u'\u0058'), + 'Xabovedot': (0x1001e8a, u'\u1E8A'), + 'Y': (0x0059, u'\u0059'), + 'Yacute': (0x00dd, u'\u00DD'), + 'Ybelowdot': (0x1001ef4, u'\u1EF4'), + 'Ycircumflex': (0x1000176, u'\u0176'), + 'Ydiaeresis': (0x13be, u'\u0178'), + 'Ygrave': (0x1001ef2, u'\u1EF2'), + 'Yhook': (0x1001ef6, u'\u1EF6'), + 'Ytilde': (0x1001ef8, u'\u1EF8'), + 'Z': (0x005a, u'\u005A'), + 'Zabovedot': (0x01af, u'\u017B'), + 'Zacute': (0x01ac, u'\u0179'), + 'Zcaron': (0x01ae, u'\u017D'), + 'Zstroke': (0x10001b5, u'\u01B5'), + 'a': (0x0061, u'\u0061'), + 'aacute': (0x00e1, u'\u00E1'), + 'abelowdot': (0x1001ea1, u'\u1EA1'), + 'abovedot': (0x01ff, u'\u02D9'), + 'abreve': (0x01e3, u'\u0103'), + 'abreveacute': (0x1001eaf, u'\u1EAF'), + 'abrevebelowdot': (0x1001eb7, u'\u1EB7'), + 'abrevegrave': (0x1001eb1, u'\u1EB1'), + 'abrevehook': (0x1001eb3, u'\u1EB3'), + 'abrevetilde': (0x1001eb5, u'\u1EB5'), + 'acircumflex': (0x00e2, u'\u00E2'), + 'acircumflexacute': (0x1001ea5, u'\u1EA5'), + 'acircumflexbelowdot': (0x1001ead, u'\u1EAD'), + 'acircumflexgrave': (0x1001ea7, u'\u1EA7'), + 'acircumflexhook': (0x1001ea9, u'\u1EA9'), + 'acircumflextilde': (0x1001eab, u'\u1EAB'), + 'acute': (0x00b4, u'\u00B4'), + 'adiaeresis': (0x00e4, u'\u00E4'), + 'ae': (0x00e6, u'\u00E6'), + 'agrave': (0x00e0, u'\u00E0'), + 'ahook': (0x1001ea3, u'\u1EA3'), + 'amacron': (0x03e0, u'\u0101'), + 'ampersand': (0x0026, u'\u0026'), + 'aogonek': (0x01b1, u'\u0105'), + 'apostrophe': (0x0027, u'\u0027'), + 'approxeq': (0x1002248, u'\u2245'), + 'approximate': (0x08c8, u'\u223C'), + 'aring': (0x00e5, u'\u00E5'), + 'asciicircum': (0x005e, u'\u005E'), + 'asciitilde': (0x007e, u'\u007E'), + 'asterisk': (0x002a, u'\u002A'), + 'at': (0x0040, u'\u0040'), + 'atilde': (0x00e3, u'\u00E3'), + 'b': (0x0062, u'\u0062'), + 'babovedot': (0x1001e03, u'\u1E03'), + 'backslash': (0x005c, u'\u005C'), + 'ballotcross': (0x0af4, u'\u2717'), + 'bar': (0x007c, u'\u007C'), + 'because': (0x1002235, u'\u2235'), + 'botintegral': (0x08a5, u'\u2321'), + 'botleftparens': (0x08ac, u'\u239D'), + 'botleftsqbracket': (0x08a8, u'\u23A3'), + 'botrightparens': (0x08ae, u'\u23A0'), + 'botrightsqbracket': (0x08aa, u'\u23A6'), + 'bott': (0x09f6, u'\u2534'), + 'braceleft': (0x007b, u'\u007B'), + 'braceright': (0x007d, u'\u007D'), + 'bracketleft': (0x005b, u'\u005B'), + 'bracketright': (0x005d, u'\u005D'), + 'braille_blank': (0x1002800, u'\u2800'), + 'braille_dots_1': (0x1002801, u'\u2801'), + 'braille_dots_12': (0x1002803, u'\u2803'), + 'braille_dots_123': (0x1002807, u'\u2807'), + 'braille_dots_1234': (0x100280f, u'\u280f'), + 'braille_dots_12345': (0x100281f, u'\u281f'), + 'braille_dots_123456': (0x100283f, u'\u283f'), + 'braille_dots_1234567': (0x100287f, u'\u287f'), + 'braille_dots_12345678': (0x10028ff, u'\u28ff'), + 'braille_dots_1234568': (0x10028bf, u'\u28bf'), + 'braille_dots_123457': (0x100285f, u'\u285f'), + 'braille_dots_1234578': (0x10028df, u'\u28df'), + 'braille_dots_123458': (0x100289f, u'\u289f'), + 'braille_dots_12346': (0x100282f, u'\u282f'), + 'braille_dots_123467': (0x100286f, u'\u286f'), + 'braille_dots_1234678': (0x10028ef, u'\u28ef'), + 'braille_dots_123468': (0x10028af, u'\u28af'), + 'braille_dots_12347': (0x100284f, u'\u284f'), + 'braille_dots_123478': (0x10028cf, u'\u28cf'), + 'braille_dots_12348': (0x100288f, u'\u288f'), + 'braille_dots_1235': (0x1002817, u'\u2817'), + 'braille_dots_12356': (0x1002837, u'\u2837'), + 'braille_dots_123567': (0x1002877, u'\u2877'), + 'braille_dots_1235678': (0x10028f7, u'\u28f7'), + 'braille_dots_123568': (0x10028b7, u'\u28b7'), + 'braille_dots_12357': (0x1002857, u'\u2857'), + 'braille_dots_123578': (0x10028d7, u'\u28d7'), + 'braille_dots_12358': (0x1002897, u'\u2897'), + 'braille_dots_1236': (0x1002827, u'\u2827'), + 'braille_dots_12367': (0x1002867, u'\u2867'), + 'braille_dots_123678': (0x10028e7, u'\u28e7'), + 'braille_dots_12368': (0x10028a7, u'\u28a7'), + 'braille_dots_1237': (0x1002847, u'\u2847'), + 'braille_dots_12378': (0x10028c7, u'\u28c7'), + 'braille_dots_1238': (0x1002887, u'\u2887'), + 'braille_dots_124': (0x100280b, u'\u280b'), + 'braille_dots_1245': (0x100281b, u'\u281b'), + 'braille_dots_12456': (0x100283b, u'\u283b'), + 'braille_dots_124567': (0x100287b, u'\u287b'), + 'braille_dots_1245678': (0x10028fb, u'\u28fb'), + 'braille_dots_124568': (0x10028bb, u'\u28bb'), + 'braille_dots_12457': (0x100285b, u'\u285b'), + 'braille_dots_124578': (0x10028db, u'\u28db'), + 'braille_dots_12458': (0x100289b, u'\u289b'), + 'braille_dots_1246': (0x100282b, u'\u282b'), + 'braille_dots_12467': (0x100286b, u'\u286b'), + 'braille_dots_124678': (0x10028eb, u'\u28eb'), + 'braille_dots_12468': (0x10028ab, u'\u28ab'), + 'braille_dots_1247': (0x100284b, u'\u284b'), + 'braille_dots_12478': (0x10028cb, u'\u28cb'), + 'braille_dots_1248': (0x100288b, u'\u288b'), + 'braille_dots_125': (0x1002813, u'\u2813'), + 'braille_dots_1256': (0x1002833, u'\u2833'), + 'braille_dots_12567': (0x1002873, u'\u2873'), + 'braille_dots_125678': (0x10028f3, u'\u28f3'), + 'braille_dots_12568': (0x10028b3, u'\u28b3'), + 'braille_dots_1257': (0x1002853, u'\u2853'), + 'braille_dots_12578': (0x10028d3, u'\u28d3'), + 'braille_dots_1258': (0x1002893, u'\u2893'), + 'braille_dots_126': (0x1002823, u'\u2823'), + 'braille_dots_1267': (0x1002863, u'\u2863'), + 'braille_dots_12678': (0x10028e3, u'\u28e3'), + 'braille_dots_1268': (0x10028a3, u'\u28a3'), + 'braille_dots_127': (0x1002843, u'\u2843'), + 'braille_dots_1278': (0x10028c3, u'\u28c3'), + 'braille_dots_128': (0x1002883, u'\u2883'), + 'braille_dots_13': (0x1002805, u'\u2805'), + 'braille_dots_134': (0x100280d, u'\u280d'), + 'braille_dots_1345': (0x100281d, u'\u281d'), + 'braille_dots_13456': (0x100283d, u'\u283d'), + 'braille_dots_134567': (0x100287d, u'\u287d'), + 'braille_dots_1345678': (0x10028fd, u'\u28fd'), + 'braille_dots_134568': (0x10028bd, u'\u28bd'), + 'braille_dots_13457': (0x100285d, u'\u285d'), + 'braille_dots_134578': (0x10028dd, u'\u28dd'), + 'braille_dots_13458': (0x100289d, u'\u289d'), + 'braille_dots_1346': (0x100282d, u'\u282d'), + 'braille_dots_13467': (0x100286d, u'\u286d'), + 'braille_dots_134678': (0x10028ed, u'\u28ed'), + 'braille_dots_13468': (0x10028ad, u'\u28ad'), + 'braille_dots_1347': (0x100284d, u'\u284d'), + 'braille_dots_13478': (0x10028cd, u'\u28cd'), + 'braille_dots_1348': (0x100288d, u'\u288d'), + 'braille_dots_135': (0x1002815, u'\u2815'), + 'braille_dots_1356': (0x1002835, u'\u2835'), + 'braille_dots_13567': (0x1002875, u'\u2875'), + 'braille_dots_135678': (0x10028f5, u'\u28f5'), + 'braille_dots_13568': (0x10028b5, u'\u28b5'), + 'braille_dots_1357': (0x1002855, u'\u2855'), + 'braille_dots_13578': (0x10028d5, u'\u28d5'), + 'braille_dots_1358': (0x1002895, u'\u2895'), + 'braille_dots_136': (0x1002825, u'\u2825'), + 'braille_dots_1367': (0x1002865, u'\u2865'), + 'braille_dots_13678': (0x10028e5, u'\u28e5'), + 'braille_dots_1368': (0x10028a5, u'\u28a5'), + 'braille_dots_137': (0x1002845, u'\u2845'), + 'braille_dots_1378': (0x10028c5, u'\u28c5'), + 'braille_dots_138': (0x1002885, u'\u2885'), + 'braille_dots_14': (0x1002809, u'\u2809'), + 'braille_dots_145': (0x1002819, u'\u2819'), + 'braille_dots_1456': (0x1002839, u'\u2839'), + 'braille_dots_14567': (0x1002879, u'\u2879'), + 'braille_dots_145678': (0x10028f9, u'\u28f9'), + 'braille_dots_14568': (0x10028b9, u'\u28b9'), + 'braille_dots_1457': (0x1002859, u'\u2859'), + 'braille_dots_14578': (0x10028d9, u'\u28d9'), + 'braille_dots_1458': (0x1002899, u'\u2899'), + 'braille_dots_146': (0x1002829, u'\u2829'), + 'braille_dots_1467': (0x1002869, u'\u2869'), + 'braille_dots_14678': (0x10028e9, u'\u28e9'), + 'braille_dots_1468': (0x10028a9, u'\u28a9'), + 'braille_dots_147': (0x1002849, u'\u2849'), + 'braille_dots_1478': (0x10028c9, u'\u28c9'), + 'braille_dots_148': (0x1002889, u'\u2889'), + 'braille_dots_15': (0x1002811, u'\u2811'), + 'braille_dots_156': (0x1002831, u'\u2831'), + 'braille_dots_1567': (0x1002871, u'\u2871'), + 'braille_dots_15678': (0x10028f1, u'\u28f1'), + 'braille_dots_1568': (0x10028b1, u'\u28b1'), + 'braille_dots_157': (0x1002851, u'\u2851'), + 'braille_dots_1578': (0x10028d1, u'\u28d1'), + 'braille_dots_158': (0x1002891, u'\u2891'), + 'braille_dots_16': (0x1002821, u'\u2821'), + 'braille_dots_167': (0x1002861, u'\u2861'), + 'braille_dots_1678': (0x10028e1, u'\u28e1'), + 'braille_dots_168': (0x10028a1, u'\u28a1'), + 'braille_dots_17': (0x1002841, u'\u2841'), + 'braille_dots_178': (0x10028c1, u'\u28c1'), + 'braille_dots_18': (0x1002881, u'\u2881'), + 'braille_dots_2': (0x1002802, u'\u2802'), + 'braille_dots_23': (0x1002806, u'\u2806'), + 'braille_dots_234': (0x100280e, u'\u280e'), + 'braille_dots_2345': (0x100281e, u'\u281e'), + 'braille_dots_23456': (0x100283e, u'\u283e'), + 'braille_dots_234567': (0x100287e, u'\u287e'), + 'braille_dots_2345678': (0x10028fe, u'\u28fe'), + 'braille_dots_234568': (0x10028be, u'\u28be'), + 'braille_dots_23457': (0x100285e, u'\u285e'), + 'braille_dots_234578': (0x10028de, u'\u28de'), + 'braille_dots_23458': (0x100289e, u'\u289e'), + 'braille_dots_2346': (0x100282e, u'\u282e'), + 'braille_dots_23467': (0x100286e, u'\u286e'), + 'braille_dots_234678': (0x10028ee, u'\u28ee'), + 'braille_dots_23468': (0x10028ae, u'\u28ae'), + 'braille_dots_2347': (0x100284e, u'\u284e'), + 'braille_dots_23478': (0x10028ce, u'\u28ce'), + 'braille_dots_2348': (0x100288e, u'\u288e'), + 'braille_dots_235': (0x1002816, u'\u2816'), + 'braille_dots_2356': (0x1002836, u'\u2836'), + 'braille_dots_23567': (0x1002876, u'\u2876'), + 'braille_dots_235678': (0x10028f6, u'\u28f6'), + 'braille_dots_23568': (0x10028b6, u'\u28b6'), + 'braille_dots_2357': (0x1002856, u'\u2856'), + 'braille_dots_23578': (0x10028d6, u'\u28d6'), + 'braille_dots_2358': (0x1002896, u'\u2896'), + 'braille_dots_236': (0x1002826, u'\u2826'), + 'braille_dots_2367': (0x1002866, u'\u2866'), + 'braille_dots_23678': (0x10028e6, u'\u28e6'), + 'braille_dots_2368': (0x10028a6, u'\u28a6'), + 'braille_dots_237': (0x1002846, u'\u2846'), + 'braille_dots_2378': (0x10028c6, u'\u28c6'), + 'braille_dots_238': (0x1002886, u'\u2886'), + 'braille_dots_24': (0x100280a, u'\u280a'), + 'braille_dots_245': (0x100281a, u'\u281a'), + 'braille_dots_2456': (0x100283a, u'\u283a'), + 'braille_dots_24567': (0x100287a, u'\u287a'), + 'braille_dots_245678': (0x10028fa, u'\u28fa'), + 'braille_dots_24568': (0x10028ba, u'\u28ba'), + 'braille_dots_2457': (0x100285a, u'\u285a'), + 'braille_dots_24578': (0x10028da, u'\u28da'), + 'braille_dots_2458': (0x100289a, u'\u289a'), + 'braille_dots_246': (0x100282a, u'\u282a'), + 'braille_dots_2467': (0x100286a, u'\u286a'), + 'braille_dots_24678': (0x10028ea, u'\u28ea'), + 'braille_dots_2468': (0x10028aa, u'\u28aa'), + 'braille_dots_247': (0x100284a, u'\u284a'), + 'braille_dots_2478': (0x10028ca, u'\u28ca'), + 'braille_dots_248': (0x100288a, u'\u288a'), + 'braille_dots_25': (0x1002812, u'\u2812'), + 'braille_dots_256': (0x1002832, u'\u2832'), + 'braille_dots_2567': (0x1002872, u'\u2872'), + 'braille_dots_25678': (0x10028f2, u'\u28f2'), + 'braille_dots_2568': (0x10028b2, u'\u28b2'), + 'braille_dots_257': (0x1002852, u'\u2852'), + 'braille_dots_2578': (0x10028d2, u'\u28d2'), + 'braille_dots_258': (0x1002892, u'\u2892'), + 'braille_dots_26': (0x1002822, u'\u2822'), + 'braille_dots_267': (0x1002862, u'\u2862'), + 'braille_dots_2678': (0x10028e2, u'\u28e2'), + 'braille_dots_268': (0x10028a2, u'\u28a2'), + 'braille_dots_27': (0x1002842, u'\u2842'), + 'braille_dots_278': (0x10028c2, u'\u28c2'), + 'braille_dots_28': (0x1002882, u'\u2882'), + 'braille_dots_3': (0x1002804, u'\u2804'), + 'braille_dots_34': (0x100280c, u'\u280c'), + 'braille_dots_345': (0x100281c, u'\u281c'), + 'braille_dots_3456': (0x100283c, u'\u283c'), + 'braille_dots_34567': (0x100287c, u'\u287c'), + 'braille_dots_345678': (0x10028fc, u'\u28fc'), + 'braille_dots_34568': (0x10028bc, u'\u28bc'), + 'braille_dots_3457': (0x100285c, u'\u285c'), + 'braille_dots_34578': (0x10028dc, u'\u28dc'), + 'braille_dots_3458': (0x100289c, u'\u289c'), + 'braille_dots_346': (0x100282c, u'\u282c'), + 'braille_dots_3467': (0x100286c, u'\u286c'), + 'braille_dots_34678': (0x10028ec, u'\u28ec'), + 'braille_dots_3468': (0x10028ac, u'\u28ac'), + 'braille_dots_347': (0x100284c, u'\u284c'), + 'braille_dots_3478': (0x10028cc, u'\u28cc'), + 'braille_dots_348': (0x100288c, u'\u288c'), + 'braille_dots_35': (0x1002814, u'\u2814'), + 'braille_dots_356': (0x1002834, u'\u2834'), + 'braille_dots_3567': (0x1002874, u'\u2874'), + 'braille_dots_35678': (0x10028f4, u'\u28f4'), + 'braille_dots_3568': (0x10028b4, u'\u28b4'), + 'braille_dots_357': (0x1002854, u'\u2854'), + 'braille_dots_3578': (0x10028d4, u'\u28d4'), + 'braille_dots_358': (0x1002894, u'\u2894'), + 'braille_dots_36': (0x1002824, u'\u2824'), + 'braille_dots_367': (0x1002864, u'\u2864'), + 'braille_dots_3678': (0x10028e4, u'\u28e4'), + 'braille_dots_368': (0x10028a4, u'\u28a4'), + 'braille_dots_37': (0x1002844, u'\u2844'), + 'braille_dots_378': (0x10028c4, u'\u28c4'), + 'braille_dots_38': (0x1002884, u'\u2884'), + 'braille_dots_4': (0x1002808, u'\u2808'), + 'braille_dots_45': (0x1002818, u'\u2818'), + 'braille_dots_456': (0x1002838, u'\u2838'), + 'braille_dots_4567': (0x1002878, u'\u2878'), + 'braille_dots_45678': (0x10028f8, u'\u28f8'), + 'braille_dots_4568': (0x10028b8, u'\u28b8'), + 'braille_dots_457': (0x1002858, u'\u2858'), + 'braille_dots_4578': (0x10028d8, u'\u28d8'), + 'braille_dots_458': (0x1002898, u'\u2898'), + 'braille_dots_46': (0x1002828, u'\u2828'), + 'braille_dots_467': (0x1002868, u'\u2868'), + 'braille_dots_4678': (0x10028e8, u'\u28e8'), + 'braille_dots_468': (0x10028a8, u'\u28a8'), + 'braille_dots_47': (0x1002848, u'\u2848'), + 'braille_dots_478': (0x10028c8, u'\u28c8'), + 'braille_dots_48': (0x1002888, u'\u2888'), + 'braille_dots_5': (0x1002810, u'\u2810'), + 'braille_dots_56': (0x1002830, u'\u2830'), + 'braille_dots_567': (0x1002870, u'\u2870'), + 'braille_dots_5678': (0x10028f0, u'\u28f0'), + 'braille_dots_568': (0x10028b0, u'\u28b0'), + 'braille_dots_57': (0x1002850, u'\u2850'), + 'braille_dots_578': (0x10028d0, u'\u28d0'), + 'braille_dots_58': (0x1002890, u'\u2890'), + 'braille_dots_6': (0x1002820, u'\u2820'), + 'braille_dots_67': (0x1002860, u'\u2860'), + 'braille_dots_678': (0x10028e0, u'\u28e0'), + 'braille_dots_68': (0x10028a0, u'\u28a0'), + 'braille_dots_7': (0x1002840, u'\u2840'), + 'braille_dots_78': (0x10028c0, u'\u28c0'), + 'braille_dots_8': (0x1002880, u'\u2880'), + 'breve': (0x01a2, u'\u02D8'), + 'brokenbar': (0x00a6, u'\u00A6'), + 'c': (0x0063, u'\u0063'), + 'cabovedot': (0x02e5, u'\u010B'), + 'cacute': (0x01e6, u'\u0107'), + 'careof': (0x0ab8, u'\u2105'), + 'caret': (0x0afc, u'\u2038'), + 'caron': (0x01b7, u'\u02C7'), + 'ccaron': (0x01e8, u'\u010D'), + 'ccedilla': (0x00e7, u'\u00E7'), + 'ccircumflex': (0x02e6, u'\u0109'), + 'cedilla': (0x00b8, u'\u00B8'), + 'cent': (0x00a2, u'\u00A2'), + 'checkerboard': (0x09e1, u'\u2592'), + 'checkmark': (0x0af3, u'\u2713'), + 'circle': (0x0bcf, u'\u25CB'), + 'club': (0x0aec, u'\u2663'), + 'colon': (0x003a, u'\u003A'), + 'comma': (0x002c, u'\u002C'), + 'containsas': (0x100220B, u'\u220B'), + 'copyright': (0x00a9, u'\u00A9'), + 'cr': (0x09e4, u'\u240D'), + 'crossinglines': (0x09ee, u'\u253C'), + 'cuberoot': (0x100221B, u'\u221B'), + 'currency': (0x00a4, u'\u00A4'), + 'd': (0x0064, u'\u0064'), + 'dabovedot': (0x1001e0b, u'\u1E0B'), + 'dagger': (0x0af1, u'\u2020'), + 'dcaron': (0x01ef, u'\u010F'), + 'dead_A': (0xfe81, None), + 'dead_E': (0xfe83, None), + 'dead_I': (0xfe85, None), + 'dead_O': (0xfe87, None), + 'dead_U': (0xfe89, None), + 'dead_a': (0xfe80, None), + 'dead_abovecomma': (0xfe64, u'\u0315'), + 'dead_abovedot': (0xfe56, u'\u0307'), + 'dead_abovereversedcomma': (0xfe65, u'\u0312'), + 'dead_abovering': (0xfe58, u'\u030A'), + 'dead_aboveverticalline': (0xfe91, u'\u030D'), + 'dead_acute': (0xfe51, u'\u0301'), + 'dead_belowbreve': (0xfe6b, u'\u032E'), + 'dead_belowcircumflex': (0xfe69, u'\u032D'), + 'dead_belowcomma': (0xfe6e, u'\u0326'), + 'dead_belowdiaeresis': (0xfe6c, u'\u0324'), + 'dead_belowdot': (0xfe60, u'\u0323'), + 'dead_belowmacron': (0xfe68, u'\u0331'), + 'dead_belowring': (0xfe67, u'\u0325'), + 'dead_belowtilde': (0xfe6a, u'\u0330'), + 'dead_belowverticalline': (0xfe92, u'\u0329'), + 'dead_breve': (0xfe55, u'\u0306'), + 'dead_capital_schwa': (0xfe8b, None), + 'dead_caron': (0xfe5a, u'\u030C'), + 'dead_cedilla': (0xfe5b, u'\u0327'), + 'dead_circumflex': (0xfe52, u'\u0302'), + 'dead_currency': (0xfe6f, None), + 'dead_diaeresis': (0xfe57, u'\u0308'), + 'dead_doubleacute': (0xfe59, u'\u030B'), + 'dead_doublegrave': (0xfe66, u'\u030F'), + 'dead_e': (0xfe82, None), + 'dead_grave': (0xfe50, u'\u0300'), + 'dead_greek': (0xfe8c, None), + 'dead_hook': (0xfe61, u'\u0309'), + 'dead_horn': (0xfe62, u'\u031B'), + 'dead_i': (0xfe84, None), + 'dead_invertedbreve': (0xfe6d, u'\u032F'), + 'dead_iota': (0xfe5d, u'\u0345'), + 'dead_longsolidusoverlay': (0xfe93, u'\u0338'), + 'dead_lowline': (0xfe90, u'\u0332'), + 'dead_macron': (0xfe54, u'\u0304'), + 'dead_o': (0xfe86, None), + 'dead_ogonek': (0xfe5c, u'\u0328'), + 'dead_semivoiced_sound': (0xfe5f, None), + 'dead_small_schwa': (0xfe8a, None), + 'dead_stroke': (0xfe63, u'\u0335'), + 'dead_tilde': (0xfe53, u'\u0303'), + 'dead_u': (0xfe88, None), + 'dead_voiced_sound': (0xfe5e, None), + 'degree': (0x00b0, u'\u00B0'), + 'diaeresis': (0x00a8, u'\u00A8'), + 'diamond': (0x0aed, u'\u2666'), + 'digitspace': (0x0aa5, u'\u2007'), + 'dintegral': (0x100222C, u'\u222C'), + 'division': (0x00f7, u'\u00F7'), + 'dollar': (0x0024, u'\u0024'), + 'doubbaselinedot': (0x0aaf, u'\u2025'), + 'doubleacute': (0x01bd, u'\u02DD'), + 'doubledagger': (0x0af2, u'\u2021'), + 'doublelowquotemark': (0x0afe, u'\u201E'), + 'downarrow': (0x08fe, u'\u2193'), + 'downstile': (0x0bc4, u'\u230A'), + 'downtack': (0x0bc2, u'\u22A4'), + 'dstroke': (0x01f0, u'\u0111'), + 'e': (0x0065, u'\u0065'), + 'eabovedot': (0x03ec, u'\u0117'), + 'eacute': (0x00e9, u'\u00E9'), + 'ebelowdot': (0x1001eb9, u'\u1EB9'), + 'ecaron': (0x01ec, u'\u011B'), + 'ecircumflex': (0x00ea, u'\u00EA'), + 'ecircumflexacute': (0x1001ebf, u'\u1EBF'), + 'ecircumflexbelowdot': (0x1001ec7, u'\u1EC7'), + 'ecircumflexgrave': (0x1001ec1, u'\u1EC1'), + 'ecircumflexhook': (0x1001ec3, u'\u1EC3'), + 'ecircumflextilde': (0x1001ec5, u'\u1EC5'), + 'ediaeresis': (0x00eb, u'\u00EB'), + 'egrave': (0x00e8, u'\u00E8'), + 'ehook': (0x1001ebb, u'\u1EBB'), + 'eightsubscript': (0x1002088, u'\u2088'), + 'eightsuperior': (0x1002078, u'\u2078'), + 'elementof': (0x1002208, u'\u2208'), + 'ellipsis': (0x0aae, u'\u2026'), + 'em3space': (0x0aa3, u'\u2004'), + 'em4space': (0x0aa4, u'\u2005'), + 'emacron': (0x03ba, u'\u0113'), + 'emdash': (0x0aa9, u'\u2014'), + 'emptyset': (0x1002205, u'\u2205'), + 'emspace': (0x0aa1, u'\u2003'), + 'endash': (0x0aaa, u'\u2013'), + 'eng': (0x03bf, u'\u014B'), + 'enspace': (0x0aa2, u'\u2002'), + 'eogonek': (0x01ea, u'\u0119'), + 'equal': (0x003d, u'\u003D'), + 'eth': (0x00f0, u'\u00F0'), + 'etilde': (0x1001ebd, u'\u1EBD'), + 'exclam': (0x0021, u'\u0021'), + 'exclamdown': (0x00a1, u'\u00A1'), + 'ezh': (0x1000292, u'\u0292'), + 'f': (0x0066, u'\u0066'), + 'fabovedot': (0x1001e1f, u'\u1E1F'), + 'femalesymbol': (0x0af8, u'\u2640'), + 'ff': (0x09e3, u'\u240C'), + 'figdash': (0x0abb, u'\u2012'), + 'fiveeighths': (0x0ac5, u'\u215D'), + 'fivesixths': (0x0ab7, u'\u215A'), + 'fivesubscript': (0x1002085, u'\u2085'), + 'fivesuperior': (0x1002075, u'\u2075'), + 'fourfifths': (0x0ab5, u'\u2158'), + 'foursubscript': (0x1002084, u'\u2084'), + 'foursuperior': (0x1002074, u'\u2074'), + 'fourthroot': (0x100221C, u'\u221C'), + 'function': (0x08f6, u'\u0192'), + 'g': (0x0067, u'\u0067'), + 'gabovedot': (0x02f5, u'\u0121'), + 'gbreve': (0x02bb, u'\u011F'), + 'gcaron': (0x10001e7, u'\u01E7'), + 'gcedilla': (0x03bb, u'\u0123'), + 'gcircumflex': (0x02f8, u'\u011D'), + 'grave': (0x0060, u'\u0060'), + 'greater': (0x003e, u'\u003E'), + 'greaterthanequal': (0x08be, u'\u2265'), + 'guillemotleft': (0x00ab, u'\u00AB'), + 'guillemotright': (0x00bb, u'\u00BB'), + 'h': (0x0068, u'\u0068'), + 'hairspace': (0x0aa8, u'\u200A'), + 'hcircumflex': (0x02b6, u'\u0125'), + 'heart': (0x0aee, u'\u2665'), + 'hebrew_aleph': (0x0ce0, u'\u05D0'), + 'hebrew_ayin': (0x0cf2, u'\u05E2'), + 'hebrew_bet': (0x0ce1, u'\u05D1'), + 'hebrew_chet': (0x0ce7, u'\u05D7'), + 'hebrew_dalet': (0x0ce3, u'\u05D3'), + 'hebrew_doublelowline': (0x0cdf, u'\u2017'), + 'hebrew_finalkaph': (0x0cea, u'\u05DA'), + 'hebrew_finalmem': (0x0ced, u'\u05DD'), + 'hebrew_finalnun': (0x0cef, u'\u05DF'), + 'hebrew_finalpe': (0x0cf3, u'\u05E3'), + 'hebrew_finalzade': (0x0cf5, u'\u05E5'), + 'hebrew_gimel': (0x0ce2, u'\u05D2'), + 'hebrew_he': (0x0ce4, u'\u05D4'), + 'hebrew_kaph': (0x0ceb, u'\u05DB'), + 'hebrew_lamed': (0x0cec, u'\u05DC'), + 'hebrew_mem': (0x0cee, u'\u05DE'), + 'hebrew_nun': (0x0cf0, u'\u05E0'), + 'hebrew_pe': (0x0cf4, u'\u05E4'), + 'hebrew_qoph': (0x0cf7, u'\u05E7'), + 'hebrew_resh': (0x0cf8, u'\u05E8'), + 'hebrew_samech': (0x0cf1, u'\u05E1'), + 'hebrew_shin': (0x0cf9, u'\u05E9'), + 'hebrew_taw': (0x0cfa, u'\u05EA'), + 'hebrew_tet': (0x0ce8, u'\u05D8'), + 'hebrew_waw': (0x0ce5, u'\u05D5'), + 'hebrew_yod': (0x0ce9, u'\u05D9'), + 'hebrew_zade': (0x0cf6, u'\u05E6'), + 'hebrew_zain': (0x0ce6, u'\u05D6'), + 'horizlinescan1': (0x09ef, u'\u23BA'), + 'horizlinescan3': (0x09f0, u'\u23BB'), + 'horizlinescan5': (0x09f1, u'\u2500'), + 'horizlinescan7': (0x09f2, u'\u23BC'), + 'horizlinescan9': (0x09f3, u'\u23BD'), + 'hstroke': (0x02b1, u'\u0127'), + 'ht': (0x09e2, u'\u2409'), + 'hyphen': (0x00ad, u'\u00AD'), + 'i': (0x0069, u'\u0069'), + 'iacute': (0x00ed, u'\u00ED'), + 'ibelowdot': (0x1001ecb, u'\u1ECB'), + 'ibreve': (0x100012d, u'\u012D'), + 'icircumflex': (0x00ee, u'\u00EE'), + 'identical': (0x08cf, u'\u2261'), + 'idiaeresis': (0x00ef, u'\u00EF'), + 'idotless': (0x02b9, u'\u0131'), + 'ifonlyif': (0x08cd, u'\u21D4'), + 'igrave': (0x00ec, u'\u00EC'), + 'ihook': (0x1001ec9, u'\u1EC9'), + 'imacron': (0x03ef, u'\u012B'), + 'implies': (0x08ce, u'\u21D2'), + 'includedin': (0x08da, u'\u2282'), + 'includes': (0x08db, u'\u2283'), + 'infinity': (0x08c2, u'\u221E'), + 'integral': (0x08bf, u'\u222B'), + 'intersection': (0x08dc, u'\u2229'), + 'iogonek': (0x03e7, u'\u012F'), + 'itilde': (0x03b5, u'\u0129'), + 'j': (0x006a, u'\u006A'), + 'jcircumflex': (0x02bc, u'\u0135'), + 'jot': (0x0bca, u'\u2218'), + 'k': (0x006b, u'\u006B'), + 'kana_A': (0x04b1, u'\u30A2'), + 'kana_CHI': (0x04c1, u'\u30C1'), + 'kana_E': (0x04b4, u'\u30A8'), + 'kana_FU': (0x04cc, u'\u30D5'), + 'kana_HA': (0x04ca, u'\u30CF'), + 'kana_HE': (0x04cd, u'\u30D8'), + 'kana_HI': (0x04cb, u'\u30D2'), + 'kana_HO': (0x04ce, u'\u30DB'), + 'kana_I': (0x04b2, u'\u30A4'), + 'kana_KA': (0x04b6, u'\u30AB'), + 'kana_KE': (0x04b9, u'\u30B1'), + 'kana_KI': (0x04b7, u'\u30AD'), + 'kana_KO': (0x04ba, u'\u30B3'), + 'kana_KU': (0x04b8, u'\u30AF'), + 'kana_MA': (0x04cf, u'\u30DE'), + 'kana_ME': (0x04d2, u'\u30E1'), + 'kana_MI': (0x04d0, u'\u30DF'), + 'kana_MO': (0x04d3, u'\u30E2'), + 'kana_MU': (0x04d1, u'\u30E0'), + 'kana_N': (0x04dd, u'\u30F3'), + 'kana_NA': (0x04c5, u'\u30CA'), + 'kana_NE': (0x04c8, u'\u30CD'), + 'kana_NI': (0x04c6, u'\u30CB'), + 'kana_NO': (0x04c9, u'\u30CE'), + 'kana_NU': (0x04c7, u'\u30CC'), + 'kana_O': (0x04b5, u'\u30AA'), + 'kana_RA': (0x04d7, u'\u30E9'), + 'kana_RE': (0x04da, u'\u30EC'), + 'kana_RI': (0x04d8, u'\u30EA'), + 'kana_RO': (0x04db, u'\u30ED'), + 'kana_RU': (0x04d9, u'\u30EB'), + 'kana_SA': (0x04bb, u'\u30B5'), + 'kana_SE': (0x04be, u'\u30BB'), + 'kana_SHI': (0x04bc, u'\u30B7'), + 'kana_SO': (0x04bf, u'\u30BD'), + 'kana_SU': (0x04bd, u'\u30B9'), + 'kana_TA': (0x04c0, u'\u30BF'), + 'kana_TE': (0x04c3, u'\u30C6'), + 'kana_TO': (0x04c4, u'\u30C8'), + 'kana_TSU': (0x04c2, u'\u30C4'), + 'kana_U': (0x04b3, u'\u30A6'), + 'kana_WA': (0x04dc, u'\u30EF'), + 'kana_WO': (0x04a6, u'\u30F2'), + 'kana_YA': (0x04d4, u'\u30E4'), + 'kana_YO': (0x04d6, u'\u30E8'), + 'kana_YU': (0x04d5, u'\u30E6'), + 'kana_a': (0x04a7, u'\u30A1'), + 'kana_closingbracket': (0x04a3, u'\u300D'), + 'kana_comma': (0x04a4, u'\u3001'), + 'kana_conjunctive': (0x04a5, u'\u30FB'), + 'kana_e': (0x04aa, u'\u30A7'), + 'kana_fullstop': (0x04a1, u'\u3002'), + 'kana_i': (0x04a8, u'\u30A3'), + 'kana_o': (0x04ab, u'\u30A9'), + 'kana_openingbracket': (0x04a2, u'\u300C'), + 'kana_tsu': (0x04af, u'\u30C3'), + 'kana_u': (0x04a9, u'\u30A5'), + 'kana_ya': (0x04ac, u'\u30E3'), + 'kana_yo': (0x04ae, u'\u30E7'), + 'kana_yu': (0x04ad, u'\u30E5'), + 'kcedilla': (0x03f3, u'\u0137'), + 'kra': (0x03a2, u'\u0138'), + 'l': (0x006c, u'\u006C'), + 'lacute': (0x01e5, u'\u013A'), + 'latincross': (0x0ad9, u'\u271D'), + 'lbelowdot': (0x1001e37, u'\u1E37'), + 'lcaron': (0x01b5, u'\u013E'), + 'lcedilla': (0x03b6, u'\u013C'), + 'leftarrow': (0x08fb, u'\u2190'), + 'leftdoublequotemark': (0x0ad2, u'\u201C'), + 'leftmiddlecurlybrace': (0x08af, u'\u23A8'), + 'leftradical': (0x08a1, u'\u23B7'), + 'leftsinglequotemark': (0x0ad0, u'\u2018'), + 'leftt': (0x09f4, u'\u251C'), + 'lefttack': (0x0bdc, u'\u22A3'), + 'less': (0x003c, u'\u003C'), + 'lessthanequal': (0x08bc, u'\u2264'), + 'lf': (0x09e5, u'\u240A'), + 'logicaland': (0x08de, u'\u2227'), + 'logicalor': (0x08df, u'\u2228'), + 'lowleftcorner': (0x09ed, u'\u2514'), + 'lowrightcorner': (0x09ea, u'\u2518'), + 'lstroke': (0x01b3, u'\u0142'), + 'm': (0x006d, u'\u006D'), + 'mabovedot': (0x1001e41, u'\u1E41'), + 'macron': (0x00af, u'\u00AF'), + 'malesymbol': (0x0af7, u'\u2642'), + 'maltesecross': (0x0af0, u'\u2720'), + 'masculine': (0x00ba, u'\u00BA'), + 'minus': (0x002d, u'\u002D'), + 'minutes': (0x0ad6, u'\u2032'), + 'mu': (0x00b5, u'\u00B5'), + 'multiply': (0x00d7, u'\u00D7'), + 'musicalflat': (0x0af6, u'\u266D'), + 'musicalsharp': (0x0af5, u'\u266F'), + 'n': (0x006e, u'\u006E'), + 'nabla': (0x08c5, u'\u2207'), + 'nacute': (0x01f1, u'\u0144'), + 'ncaron': (0x01f2, u'\u0148'), + 'ncedilla': (0x03f1, u'\u0146'), + 'ninesubscript': (0x1002089, u'\u2089'), + 'ninesuperior': (0x1002079, u'\u2079'), + 'nl': (0x09e8, u'\u2424'), + 'nobreakspace': (0x00a0, u'\u00A0'), + 'notapproxeq': (0x1002247, u'\u2247'), + 'notelementof': (0x1002209, u'\u2209'), + 'notequal': (0x08bd, u'\u2260'), + 'notidentical': (0x1002262, u'\u2262'), + 'notsign': (0x00ac, u'\u00AC'), + 'ntilde': (0x00f1, u'\u00F1'), + 'numbersign': (0x0023, u'\u0023'), + 'numerosign': (0x06b0, u'\u2116'), + 'o': (0x006f, u'\u006F'), + 'oacute': (0x00f3, u'\u00F3'), + 'obarred': (0x1000275, u'\u0275'), + 'obelowdot': (0x1001ecd, u'\u1ECD'), + 'ocaron': (0x10001d2, u'\u01D2'), + 'ocircumflex': (0x00f4, u'\u00F4'), + 'ocircumflexacute': (0x1001ed1, u'\u1ED1'), + 'ocircumflexbelowdot': (0x1001ed9, u'\u1ED9'), + 'ocircumflexgrave': (0x1001ed3, u'\u1ED3'), + 'ocircumflexhook': (0x1001ed5, u'\u1ED5'), + 'ocircumflextilde': (0x1001ed7, u'\u1ED7'), + 'odiaeresis': (0x00f6, u'\u00F6'), + 'odoubleacute': (0x01f5, u'\u0151'), + 'oe': (0x13bd, u'\u0153'), + 'ogonek': (0x01b2, u'\u02DB'), + 'ograve': (0x00f2, u'\u00F2'), + 'ohook': (0x1001ecf, u'\u1ECF'), + 'ohorn': (0x10001a1, u'\u01A1'), + 'ohornacute': (0x1001edb, u'\u1EDB'), + 'ohornbelowdot': (0x1001ee3, u'\u1EE3'), + 'ohorngrave': (0x1001edd, u'\u1EDD'), + 'ohornhook': (0x1001edf, u'\u1EDF'), + 'ohorntilde': (0x1001ee1, u'\u1EE1'), + 'omacron': (0x03f2, u'\u014D'), + 'oneeighth': (0x0ac3, u'\u215B'), + 'onefifth': (0x0ab2, u'\u2155'), + 'onehalf': (0x00bd, u'\u00BD'), + 'onequarter': (0x00bc, u'\u00BC'), + 'onesixth': (0x0ab6, u'\u2159'), + 'onesubscript': (0x1002081, u'\u2081'), + 'onesuperior': (0x00b9, u'\u00B9'), + 'onethird': (0x0ab0, u'\u2153'), + 'ooblique': (0x00f8, u'\u00F8'), + 'ordfeminine': (0x00aa, u'\u00AA'), + 'oslash': (0x00f8, u'\u00F8'), + 'otilde': (0x00f5, u'\u00F5'), + 'overline': (0x047e, u'\u203E'), + 'p': (0x0070, u'\u0070'), + 'pabovedot': (0x1001e57, u'\u1E57'), + 'paragraph': (0x00b6, u'\u00B6'), + 'parenleft': (0x0028, u'\u0028'), + 'parenright': (0x0029, u'\u0029'), + 'partdifferential': (0x1002202, u'\u2202'), + 'partialderivative': (0x08ef, u'\u2202'), + 'percent': (0x0025, u'\u0025'), + 'period': (0x002e, u'\u002E'), + 'periodcentered': (0x00b7, u'\u00B7'), + 'permille': (0x0ad5, u'\u2030'), + 'phonographcopyright': (0x0afb, u'\u2117'), + 'plus': (0x002b, u'\u002B'), + 'plusminus': (0x00b1, u'\u00B1'), + 'prescription': (0x0ad4, u'\u211E'), + 'prolongedsound': (0x04b0, u'\u30FC'), + 'punctspace': (0x0aa6, u'\u2008'), + 'q': (0x0071, u'\u0071'), + 'quad': (0x0bcc, u'\u2395'), + 'question': (0x003f, u'\u003F'), + 'questiondown': (0x00bf, u'\u00BF'), + 'quotedbl': (0x0022, u'\u0022'), + 'r': (0x0072, u'\u0072'), + 'racute': (0x01e0, u'\u0155'), + 'radical': (0x08d6, u'\u221A'), + 'rcaron': (0x01f8, u'\u0159'), + 'rcedilla': (0x03b3, u'\u0157'), + 'registered': (0x00ae, u'\u00AE'), + 'rightarrow': (0x08fd, u'\u2192'), + 'rightdoublequotemark': (0x0ad3, u'\u201D'), + 'rightmiddlecurlybrace': (0x08b0, u'\u23AC'), + 'rightsinglequotemark': (0x0ad1, u'\u2019'), + 'rightt': (0x09f5, u'\u2524'), + 'righttack': (0x0bfc, u'\u22A2'), + 's': (0x0073, u'\u0073'), + 'sabovedot': (0x1001e61, u'\u1E61'), + 'sacute': (0x01b6, u'\u015B'), + 'scaron': (0x01b9, u'\u0161'), + 'scedilla': (0x01ba, u'\u015F'), + 'schwa': (0x1000259, u'\u0259'), + 'scircumflex': (0x02fe, u'\u015D'), + 'seconds': (0x0ad7, u'\u2033'), + 'section': (0x00a7, u'\u00A7'), + 'semicolon': (0x003b, u'\u003B'), + 'semivoicedsound': (0x04df, u'\u309C'), + 'seveneighths': (0x0ac6, u'\u215E'), + 'sevensubscript': (0x1002087, u'\u2087'), + 'sevensuperior': (0x1002077, u'\u2077'), + 'similarequal': (0x08c9, u'\u2243'), + 'singlelowquotemark': (0x0afd, u'\u201A'), + 'sixsubscript': (0x1002086, u'\u2086'), + 'sixsuperior': (0x1002076, u'\u2076'), + 'slash': (0x002f, u'\u002F'), + 'soliddiamond': (0x09e0, u'\u25C6'), + 'space': (0x0020, u'\u0020'), + 'squareroot': (0x100221A, u'\u221A'), + 'ssharp': (0x00df, u'\u00DF'), + 'sterling': (0x00a3, u'\u00A3'), + 'stricteq': (0x1002263, u'\u2263'), + 't': (0x0074, u'\u0074'), + 'tabovedot': (0x1001e6b, u'\u1E6B'), + 'tcaron': (0x01bb, u'\u0165'), + 'tcedilla': (0x01fe, u'\u0163'), + 'telephone': (0x0af9, u'\u260E'), + 'telephonerecorder': (0x0afa, u'\u2315'), + 'therefore': (0x08c0, u'\u2234'), + 'thinspace': (0x0aa7, u'\u2009'), + 'thorn': (0x00fe, u'\u00FE'), + 'threeeighths': (0x0ac4, u'\u215C'), + 'threefifths': (0x0ab4, u'\u2157'), + 'threequarters': (0x00be, u'\u00BE'), + 'threesubscript': (0x1002083, u'\u2083'), + 'threesuperior': (0x00b3, u'\u00B3'), + 'tintegral': (0x100222D, u'\u222D'), + 'topintegral': (0x08a4, u'\u2320'), + 'topleftparens': (0x08ab, u'\u239B'), + 'topleftsqbracket': (0x08a7, u'\u23A1'), + 'toprightparens': (0x08ad, u'\u239E'), + 'toprightsqbracket': (0x08a9, u'\u23A4'), + 'topt': (0x09f7, u'\u252C'), + 'trademark': (0x0ac9, u'\u2122'), + 'tslash': (0x03bc, u'\u0167'), + 'twofifths': (0x0ab3, u'\u2156'), + 'twosubscript': (0x1002082, u'\u2082'), + 'twosuperior': (0x00b2, u'\u00B2'), + 'twothirds': (0x0ab1, u'\u2154'), + 'u': (0x0075, u'\u0075'), + 'uacute': (0x00fa, u'\u00FA'), + 'ubelowdot': (0x1001ee5, u'\u1EE5'), + 'ubreve': (0x02fd, u'\u016D'), + 'ucircumflex': (0x00fb, u'\u00FB'), + 'udiaeresis': (0x00fc, u'\u00FC'), + 'udoubleacute': (0x01fb, u'\u0171'), + 'ugrave': (0x00f9, u'\u00F9'), + 'uhook': (0x1001ee7, u'\u1EE7'), + 'uhorn': (0x10001b0, u'\u01B0'), + 'uhornacute': (0x1001ee9, u'\u1EE9'), + 'uhornbelowdot': (0x1001ef1, u'\u1EF1'), + 'uhorngrave': (0x1001eeb, u'\u1EEB'), + 'uhornhook': (0x1001eed, u'\u1EED'), + 'uhorntilde': (0x1001eef, u'\u1EEF'), + 'umacron': (0x03fe, u'\u016B'), + 'underscore': (0x005f, u'\u005F'), + 'union': (0x08dd, u'\u222A'), + 'uogonek': (0x03f9, u'\u0173'), + 'uparrow': (0x08fc, u'\u2191'), + 'upleftcorner': (0x09ec, u'\u250C'), + 'uprightcorner': (0x09eb, u'\u2510'), + 'upstile': (0x0bd3, u'\u2308'), + 'uptack': (0x0bce, u'\u22A5'), + 'uring': (0x01f9, u'\u016F'), + 'utilde': (0x03fd, u'\u0169'), + 'v': (0x0076, u'\u0076'), + 'variation': (0x08c1, u'\u221D'), + 'vertbar': (0x09f8, u'\u2502'), + 'voicedsound': (0x04de, u'\u309B'), + 'vt': (0x09e9, u'\u240B'), + 'w': (0x0077, u'\u0077'), + 'wacute': (0x1001e83, u'\u1E83'), + 'wcircumflex': (0x1000175, u'\u0175'), + 'wdiaeresis': (0x1001e85, u'\u1E85'), + 'wgrave': (0x1001e81, u'\u1E81'), + 'x': (0x0078, u'\u0078'), + 'xabovedot': (0x1001e8b, u'\u1E8B'), + 'y': (0x0079, u'\u0079'), + 'yacute': (0x00fd, u'\u00FD'), + 'ybelowdot': (0x1001ef5, u'\u1EF5'), + 'ycircumflex': (0x1000177, u'\u0177'), + 'ydiaeresis': (0x00ff, u'\u00FF'), + 'yen': (0x00a5, u'\u00A5'), + 'ygrave': (0x1001ef3, u'\u1EF3'), + 'yhook': (0x1001ef7, u'\u1EF7'), + 'ytilde': (0x1001ef9, u'\u1EF9'), + 'z': (0x007a, u'\u007A'), + 'zabovedot': (0x01bf, u'\u017C'), + 'zacute': (0x01bc, u'\u017A'), + 'zcaron': (0x01be, u'\u017E'), + 'zerosubscript': (0x1002080, u'\u2080'), + 'zerosuperior': (0x1002070, u'\u2070'), + 'zstroke': (0x10001b6, u'\u01B6')} + +DEAD_KEYS = { + u'\u0307': u'\u02D9', + u'\u030A': u'\u02DA', + u'\u0301': u'\u00B4', + u'\u0306': u'\u02D8', + u'\u030C': u'\u02C7', + u'\u0327': u'\u00B8', + u'\u0302': u'\u005E', + u'\u0308': u'\u00A8', + u'\u030B': u'\u02DD', + u'\u0300': u'\u0060', + u'\u0345': u'\u037A', + u'\u0332': u'\u005F', + u'\u0304': u'\u00AF', + u'\u0328': u'\u02DB', + u'\u0303': u'\u007E'} + +KEYPAD_KEYS = { + 'KP_0': 0xffb0, + 'KP_1': 0xffb1, + 'KP_2': 0xffb2, + 'KP_3': 0xffb3, + 'KP_4': 0xffb4, + 'KP_5': 0xffb5, + 'KP_6': 0xffb6, + 'KP_7': 0xffb7, + 'KP_8': 0xffb8, + 'KP_9': 0xffb9, + 'KP_Add': 0xffab, + 'KP_Begin': 0xff9d, + 'KP_Decimal': 0xffae, + 'KP_Delete': 0xff9f, + 'KP_Divide': 0xffaf, + 'KP_Down': 0xff99, + 'KP_End': 0xff9c, + 'KP_Enter': 0xff8d, + 'KP_Equal': 0xffbd, + 'KP_F1': 0xff91, + 'KP_F2': 0xff92, + 'KP_F3': 0xff93, + 'KP_F4': 0xff94, + 'KP_Home': 0xff95, + 'KP_Insert': 0xff9e, + 'KP_Left': 0xff96, + 'KP_Multiply': 0xffaa, + 'KP_Next': 0xff9b, + 'KP_Page_Down': 0xff9b, + 'KP_Page_Up': 0xff9a, + 'KP_Prior': 0xff9a, + 'KP_Right': 0xff98, + 'KP_Separator': 0xffac, + 'KP_Space': 0xff80, + 'KP_Subtract': 0xffad, + 'KP_Tab': 0xff89, + 'KP_Up': 0xff97} + +CHARS = { + codepoint: name + for name, (keysym, codepoint) in SYMBOLS.items() + if codepoint} + +KEYSYMS = { + keysym: name + for name, (keysym, codepoint) in SYMBOLS.items() + if codepoint} diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__init__.py b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__init__.py new file mode 100644 index 0000000..34a1921 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__init__.py @@ -0,0 +1,249 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The module containing keyboard classes. + +See the documentation for more information. +""" + +# pylint: disable=C0103 +# KeyCode, Key, Controller and Listener are not constants + +import itertools + +from pynput._util import backend, Events + + +backend = backend(__name__) +KeyCode = backend.KeyCode +Key = backend.Key +Controller = backend.Controller +Listener = backend.Listener +del backend + + +# pylint: disable=C0326; it is easier to read column aligned keys +#: The keys used as modifiers; the first value in each tuple is the +#: base modifier to use for subsequent modifiers. +_MODIFIER_KEYS = ( + (Key.alt_gr, (Key.alt_gr.value,)), + (Key.alt, (Key.alt.value, Key.alt_l.value, Key.alt_r.value)), + (Key.cmd, (Key.cmd.value, Key.cmd_l.value, Key.cmd_r.value)), + (Key.ctrl, (Key.ctrl.value, Key.ctrl_l.value, Key.ctrl_r.value)), + (Key.shift, (Key.shift.value, Key.shift_l.value, Key.shift_r.value))) + +#: Normalised modifiers as a mapping from virtual key code to basic modifier. +_NORMAL_MODIFIERS = { + value: key + for combination in _MODIFIER_KEYS + for key, value in zip( + itertools.cycle((combination[0],)), + combination[1])} + +#: Control codes to transform into key codes when typing +_CONTROL_CODES = { + '\n': Key.enter, + '\r': Key.enter, + '\t': Key.tab} +# pylint: enable=C0326 + + +class Events(Events): + """A keyboard event listener supporting synchronous iteration over the + events. + + Possible events are: + + :class:`Events.Press` + A key was pressed. + + :class:`Events.Release` + A key was released. + """ + _Listener = Listener + + class Press(Events.Event): + """A key press event. + """ + def __init__(self, key, injected): + #: The key. + self.key = key + + #: Whether this event is synthetic. + self.injected = injected + + class Release(Events.Event): + """A key release event. + """ + def __init__(self, key, injected): + #: The key. + self.key = key + + #: Whether this event is synthetic. + self.injected = injected + + def __init__(self): + super(Events, self).__init__( + on_press=self.Press, + on_release=self.Release) + + +class HotKey(object): + """A combination of keys acting as a hotkey. + + This class acts as a container of hotkey state for a keyboard listener. + + :param set keys: The collection of keys that must be pressed for this + hotkey to activate. Please note that a common limitation of the + hardware is that at most three simultaneously pressed keys are + supported, so using more keys may not work. + + :param callable on_activate: The activation callback. + """ + def __init__(self, keys, on_activate): + self._state = set() + self._keys = set(keys) + self._on_activate = on_activate + + @staticmethod + def parse(keys): + """Parses a key combination string. + + Key combination strings are sequences of key identifiers separated by + ``'+'``. Key identifiers are either single characters representing a + keyboard key, such as ``'a'``, or special key names identified by names + enclosed by brackets, such as ``''``. + + Keyboard keys are case-insensitive. + + :raises ValueError: if a part of the keys string is invalid, or if it + contains multiple equal parts + """ + def parts(): + start = 0 + for i, c in enumerate(keys): + if c == '+' and i != start: + yield keys[start:i] + start = i + 1 + if start == len(keys): + raise ValueError(keys) + else: + yield keys[start:] + + def parse(s): + if len(s) == 1: + return KeyCode.from_char(s.lower()) + elif len(s) > 2 and (s[0], s[-1]) == ('<', '>'): + p = s[1:-1] + try: + # We want to represent modifiers as Key instances, and all + # other keys as KeyCodes + key = Key[p.lower()] + if key in _NORMAL_MODIFIERS.values(): + return key + else: + return KeyCode.from_vk(key.value.vk) + except KeyError: + try: + return KeyCode.from_vk(int(p)) + except ValueError: + raise ValueError(s) + else: + raise ValueError(s) + + # Split the string and parse the individual parts + raw_parts = list(parts()) + parsed_parts = [ + parse(s) + for s in raw_parts] + + # Ensure no duplicate parts + if len(parsed_parts) != len(set(parsed_parts)): + raise ValueError(keys) + else: + return parsed_parts + + def press(self, key): + """Updates the hotkey state for a pressed key. + + If the key is not currently pressed, but is the last key for the full + combination, the activation callback will be invoked. + + Please note that the callback will only be invoked once. + + :param key: The key being pressed. + :type key: Key or KeyCode + """ + if key in self._keys and key not in self._state: + self._state.add(key) + if self._state == self._keys: + self._on_activate() + + def release(self, key): + """Updates the hotkey state for a released key. + + :param key: The key being released. + :type key: Key or KeyCode + """ + if key in self._state: + self._state.remove(key) + + +class GlobalHotKeys(Listener): + """A keyboard listener supporting a number of global hotkeys. + + This is a convenience wrapper to simplify registering a number of global + hotkeys. + + :param dict hotkeys: A mapping from hotkey description to hotkey action. + Keys are strings passed to :meth:`HotKey.parse`. + + :raises ValueError: if any hotkey description is invalid + """ + def __init__(self, hotkeys, *args, **kwargs): + self._hotkeys = [ + HotKey(HotKey.parse(key), value) + for key, value in hotkeys.items()] + super(GlobalHotKeys, self).__init__( + on_press=self._on_press, + on_release=self._on_release, + *args, + **kwargs) + + def _on_press(self, key, injected): + """The press callback. + + This is automatically registered upon creation. + + :param key: The key provided by the base class. + :param injected: Whether the event was injected. + """ + if not injected: + for hotkey in self._hotkeys: + hotkey.press(self.canonical(key)) + + def _on_release(self, key, injected): + """The release callback. + + This is automatically registered upon creation. + + :param key: The key provided by the base class. + :param injected: Whether the event was injected. + """ + if not injected: + for hotkey in self._hotkeys: + hotkey.release(self.canonical(key)) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..34af5f0 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_base.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_base.cpython-312.pyc new file mode 100644 index 0000000..184f219 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_base.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_darwin.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_darwin.cpython-312.pyc new file mode 100644 index 0000000..f3f2906 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_darwin.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_dummy.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_dummy.cpython-312.pyc new file mode 100644 index 0000000..34cbd51 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_dummy.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_uinput.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_uinput.cpython-312.pyc new file mode 100644 index 0000000..aa1b6b3 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_uinput.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_win32.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_win32.cpython-312.pyc new file mode 100644 index 0000000..427c0fd Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_win32.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_xorg.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_xorg.cpython-312.pyc new file mode 100644 index 0000000..4740831 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/__pycache__/_xorg.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_base.py b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_base.py new file mode 100644 index 0000000..6035743 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_base.py @@ -0,0 +1,754 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +This module contains the base implementation. + +The actual interface to keyboard classes is defined here, but the +implementation is located in a platform dependent module. +""" + +# pylint: disable=R0903 +# We implement stubs + +import contextlib +import enum +import threading +import unicodedata + +import six + +from pynput._util import AbstractListener, prefix +from pynput import _logger + + +class KeyCode(object): + """ + A :class:`KeyCode` represents the description of a key code used by the + operating system. + """ + #: The names of attributes used as platform extensions. + _PLATFORM_EXTENSIONS = [] + + def __init__(self, vk=None, char=None, is_dead=False, **kwargs): + self.vk = vk + self.char = six.text_type(char) if char is not None else None + self.is_dead = is_dead + + if self.is_dead: + try: + self.combining = unicodedata.lookup( + 'COMBINING ' + unicodedata.name(self.char)) + except KeyError: + self.is_dead = False + self.combining = None + if self.is_dead and not self.combining: + raise KeyError(char) + else: + self.combining = None + + for key in self._PLATFORM_EXTENSIONS: + setattr(self, key, kwargs.pop(key, None)) + if kwargs: + raise ValueError(kwargs) + + + def __repr__(self): + if self.is_dead: + return '[%s]' % repr(self.char) + if self.char is not None: + return repr(self.char) + else: + return '<%d>' % self.vk + + def __str__(self): + return repr(self) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + if self.char is not None and other.char is not None: + return self.char == other.char and self.is_dead == other.is_dead + else: + return self.vk == other.vk and all( + getattr(self, f) == getattr(other, f) + for f in self._PLATFORM_EXTENSIONS) + + def __hash__(self): + return hash(repr(self)) + + def join(self, key): + """Applies this dead key to another key and returns the result. + + Joining a dead key with space (``' '``) or itself yields the non-dead + version of this key, if one exists; for example, + ``KeyCode.from_dead('~').join(KeyCode.from_char(' '))`` equals + ``KeyCode.from_char('~')`` and + ``KeyCode.from_dead('~').join(KeyCode.from_dead('~'))``. + + :param KeyCode key: The key to join with this key. + + :return: a key code + + :raises ValueError: if the keys cannot be joined + """ + # A non-dead key cannot be joined + if not self.is_dead: + raise ValueError(self) + + # Joining two of the same keycodes, or joining with space, yields the + # non-dead version of the key + if key.char == ' ' or self == key: + return self.from_char(self.char) + + # Otherwise we combine the characters + if key.char is not None: + combined = unicodedata.normalize( + 'NFC', + key.char + self.combining) + if combined: + return self.from_char(combined) + + raise ValueError(key) + + @classmethod + def from_vk(cls, vk, **kwargs): + """Creates a key from a virtual key code. + + :param vk: The virtual key code. + + :param kwargs: Any other parameters to pass. + + :return: a key code + """ + return cls(vk=vk, **kwargs) + + @classmethod + def from_char(cls, char, **kwargs): + """Creates a key from a character. + + :param str char: The character. + + :return: a key code + """ + return cls(char=char, **kwargs) + + @classmethod + def from_dead(cls, char, **kwargs): + """Creates a dead key. + + :param char: The dead key. This should be the unicode character + representing the stand alone character, such as ``'~'`` for + *COMBINING TILDE*. + + :return: a key code + """ + return cls(char=char, is_dead=True, **kwargs) + + +class Key(enum.Enum): + """A class representing various buttons that may not correspond to + letters. This includes modifier keys and function keys. + + The actual values for these items differ between platforms. Some platforms + may have additional buttons, but these are guaranteed to be present + everywhere. + """ + #: A generic Alt key. This is a modifier. + alt = KeyCode.from_vk(0) + + #: The left Alt key. This is a modifier. + alt_l = KeyCode.from_vk(0) + + #: The right Alt key. This is a modifier. + alt_r = KeyCode.from_vk(0) + + #: The AltGr key. This is a modifier. + alt_gr = KeyCode.from_vk(0) + + #: The Backspace key. + backspace = KeyCode.from_vk(0) + + #: The CapsLock key. + caps_lock = KeyCode.from_vk(0) + + #: A generic command button. On *PC* platforms, this corresponds to the + #: Super key or Windows key, and on *Mac* it corresponds to the Command + #: key. This may be a modifier. + cmd = KeyCode.from_vk(0) + + #: The left command button. On *PC* platforms, this corresponds to the + #: Super key or Windows key, and on *Mac* it corresponds to the Command + #: key. This may be a modifier. + cmd_l = KeyCode.from_vk(0) + + #: The right command button. On *PC* platforms, this corresponds to the + #: Super key or Windows key, and on *Mac* it corresponds to the Command + #: key. This may be a modifier. + cmd_r = KeyCode.from_vk(0) + + #: A generic Ctrl key. This is a modifier. + ctrl = KeyCode.from_vk(0) + + #: The left Ctrl key. This is a modifier. + ctrl_l = KeyCode.from_vk(0) + + #: The right Ctrl key. This is a modifier. + ctrl_r = KeyCode.from_vk(0) + + #: The Delete key. + delete = KeyCode.from_vk(0) + + #: A down arrow key. + down = KeyCode.from_vk(0) + + #: The End key. + end = KeyCode.from_vk(0) + + #: The Enter or Return key. + enter = KeyCode.from_vk(0) + + #: The Esc key. + esc = KeyCode.from_vk(0) + + #: The function keys. F1 to F20 are defined. + f1 = KeyCode.from_vk(0) + f2 = KeyCode.from_vk(0) + f3 = KeyCode.from_vk(0) + f4 = KeyCode.from_vk(0) + f5 = KeyCode.from_vk(0) + f6 = KeyCode.from_vk(0) + f7 = KeyCode.from_vk(0) + f8 = KeyCode.from_vk(0) + f9 = KeyCode.from_vk(0) + f10 = KeyCode.from_vk(0) + f11 = KeyCode.from_vk(0) + f12 = KeyCode.from_vk(0) + f13 = KeyCode.from_vk(0) + f14 = KeyCode.from_vk(0) + f15 = KeyCode.from_vk(0) + f16 = KeyCode.from_vk(0) + f17 = KeyCode.from_vk(0) + f18 = KeyCode.from_vk(0) + f19 = KeyCode.from_vk(0) + f20 = KeyCode.from_vk(0) + + #: The Home key. + home = KeyCode.from_vk(0) + + #: A left arrow key. + left = KeyCode.from_vk(0) + + #: The PageDown key. + page_down = KeyCode.from_vk(0) + + #: The PageUp key. + page_up = KeyCode.from_vk(0) + + #: A right arrow key. + right = KeyCode.from_vk(0) + + #: A generic Shift key. This is a modifier. + shift = KeyCode.from_vk(0) + + #: The left Shift key. This is a modifier. + shift_l = KeyCode.from_vk(0) + + #: The right Shift key. This is a modifier. + shift_r = KeyCode.from_vk(0) + + #: The Space key. + space = KeyCode.from_vk(0) + + #: The Tab key. + tab = KeyCode.from_vk(0) + + #: An up arrow key. + up = KeyCode.from_vk(0) + + #: The play/pause toggle. + media_play_pause = KeyCode.from_vk(0) + + #: The volume mute button. + media_volume_mute = KeyCode.from_vk(0) + + #: The volume down button. + media_volume_down = KeyCode.from_vk(0) + + #: The volume up button. + media_volume_up = KeyCode.from_vk(0) + + #: The previous track button. + media_previous = KeyCode.from_vk(0) + + #: The next track button. + media_next = KeyCode.from_vk(0) + + #: The Insert key. This may be undefined for some platforms. + insert = KeyCode.from_vk(0) + + #: The Menu key. This may be undefined for some platforms. + menu = KeyCode.from_vk(0) + + #: The NumLock key. This may be undefined for some platforms. + num_lock = KeyCode.from_vk(0) + + #: The Pause/Break key. This may be undefined for some platforms. + pause = KeyCode.from_vk(0) + + #: The PrintScreen key. This may be undefined for some platforms. + print_screen = KeyCode.from_vk(0) + + #: The ScrollLock key. This may be undefined for some platforms. + scroll_lock = KeyCode.from_vk(0) + + +class Controller(object): + """A controller for sending virtual keyboard events to the system. + """ + #: The virtual key codes + _KeyCode = KeyCode + + #: The various keys. + _Key = Key + + class InvalidKeyException(Exception): + """The exception raised when an invalid ``key`` parameter is passed to + either :meth:`Controller.press` or :meth:`Controller.release`. + + Its first argument is the ``key`` parameter. + """ + pass + + class InvalidCharacterException(Exception): + """The exception raised when an invalid character is encountered in + the string passed to :meth:`Controller.type`. + + Its first argument is the index of the character in the string, and the + second the character. + """ + pass + + def __init__(self): + self._log = _logger(self.__class__) + self._modifiers_lock = threading.RLock() + self._modifiers = set() + self._caps_lock = False + self._dead_key = None + + def press(self, key): + """Presses a key. + + A key may be either a string of length 1, one of the :class:`Key` + members or a :class:`KeyCode`. + + Strings will be transformed to :class:`KeyCode` using + :meth:`KeyCode.char`. Members of :class:`Key` will be translated to + their :meth:`~Key.value`. + + :param key: The key to press. + + :raises InvalidKeyException: if the key is invalid + + :raises ValueError: if ``key`` is a string, but its length is not ``1`` + """ + resolved = self._resolve(key) + if resolved is None: + raise self.InvalidKeyException(key) + self._update_modifiers(resolved, True) + + # Update caps lock state + if resolved == self._Key.caps_lock.value: + self._caps_lock = not self._caps_lock + + # If we currently have a dead key pressed, join it with this key + original = resolved + if self._dead_key: + try: + resolved = self._dead_key.join(resolved) + except ValueError: + self._handle(self._dead_key, True) + self._handle(self._dead_key, False) + + # If the key is a dead key, keep it for later + if resolved.is_dead: + self._dead_key = resolved + return + + try: + self._handle(resolved, True) + except self.InvalidKeyException: + if resolved != original: + self._handle(self._dead_key, True) + self._handle(self._dead_key, False) + self._handle(original, True) + + self._dead_key = None + + def release(self, key): + """Releases a key. + + A key may be either a string of length 1, one of the :class:`Key` + members or a :class:`KeyCode`. + + Strings will be transformed to :class:`KeyCode` using + :meth:`KeyCode.char`. Members of :class:`Key` will be translated to + their :meth:`~Key.value`. + + :param key: The key to release. If this is a string, it is passed to + :meth:`touches` and the returned releases are used. + + :raises InvalidKeyException: if the key is invalid + + :raises ValueError: if ``key`` is a string, but its length is not ``1`` + """ + resolved = self._resolve(key) + if resolved is None: + raise self.InvalidKeyException(key) + self._update_modifiers(resolved, False) + + # Ignore released dead keys + if resolved.is_dead: + return + + self._handle(resolved, False) + + def tap(self, key): + """Presses and releases a key. + + This is equivalent to the following code:: + + controller.press(key) + controller.release(key) + + :param key: The key to press. + + :raises InvalidKeyException: if the key is invalid + + :raises ValueError: if ``key`` is a string, but its length is not ``1`` + """ + self.press(key) + self.release(key) + + def touch(self, key, is_press): + """Calls either :meth:`press` or :meth:`release` depending on the value + of ``is_press``. + + :param key: The key to press or release. + + :param bool is_press: Whether to press the key. + + :raises InvalidKeyException: if the key is invalid + """ + if is_press: + self.press(key) + else: + self.release(key) + + @contextlib.contextmanager + def pressed(self, *args): + """Executes a block with some keys pressed. + + :param keys: The keys to keep pressed. + """ + for key in args: + self.press(key) + + try: + yield + finally: + for key in reversed(args): + self.release(key) + + def type(self, string): + """Types a string. + + This method will send all key presses and releases necessary to type + all characters in the string. + + :param str string: The string to type. + + :raises InvalidCharacterException: if an untypable character is + encountered + """ + from . import _CONTROL_CODES + for i, character in enumerate(string): + key = _CONTROL_CODES.get(character, character) + try: + self.press(key) + self.release(key) + + except (ValueError, self.InvalidKeyException): + raise self.InvalidCharacterException(i, character) + + @property + @contextlib.contextmanager + def modifiers(self): + """The currently pressed modifier keys. + + Please note that this reflects only the internal state of this + controller, and not the state of the operating system keyboard buffer. + This property cannot be used to determine whether a key is physically + pressed. + + Only the generic modifiers will be set; when pressing either + :attr:`Key.shift_l`, :attr:`Key.shift_r` or :attr:`Key.shift`, only + :attr:`Key.shift` will be present. + + Use this property within a context block thus:: + + with controller.modifiers as modifiers: + with_block() + + This ensures that the modifiers cannot be modified by another thread. + """ + with self._modifiers_lock: + yield set( + self._as_modifier(modifier) + for modifier in self._modifiers) + + @property + def alt_pressed(self): + """Whether any *alt* key is pressed. + + Please note that this reflects only the internal state of this + controller. See :attr:`modifiers` for more information. + """ + with self.modifiers as modifiers: + return self._Key.alt in modifiers + + @property + def alt_gr_pressed(self): + """Whether *altgr* is pressed. + + Please note that this reflects only the internal state of this + controller. See :attr:`modifiers` for more information. + """ + with self.modifiers as modifiers: + return self._Key.alt_gr in modifiers + + @property + def ctrl_pressed(self): + """Whether any *ctrl* key is pressed. + + Please note that this reflects only the internal state of this + controller. See :attr:`modifiers` for more information. + """ + with self.modifiers as modifiers: + return self._Key.ctrl in modifiers + + @property + def shift_pressed(self): + """Whether any *shift* key is pressed, or *caps lock* is toggled. + + Please note that this reflects only the internal state of this + controller. See :attr:`modifiers` for more information. + """ + if self._caps_lock: + return True + + with self.modifiers as modifiers: + return self._Key.shift in modifiers + + def _resolve(self, key): + """Resolves a key to a :class:`KeyCode` instance. + + This method will convert any key representing a character to uppercase + if a shift modifier is active. + + :param key: The key to resolve. + + :return: a key code, or ``None`` if it cannot be resolved + """ + # Use the value for the key constants + if key in (k for k in self._Key): + return key.value + + # Convert strings to key codes + if isinstance(key, six.string_types): + if len(key) != 1: + raise ValueError(key) + return self._KeyCode.from_char(key) + + # Assume this is a proper key + if isinstance(key, self._KeyCode): + if key.char is not None and self.shift_pressed: + return self._KeyCode(vk=key.vk, char=key.char.upper()) + else: + return key + + def _update_modifiers(self, key, is_press): + """Updates the current modifier list. + + If ``key`` is not a modifier, no action is taken. + + :param key: The key being pressed or released. + """ + # Check whether the key is a modifier + if self._as_modifier(key): + with self._modifiers_lock: + if is_press: + self._modifiers.add(key) + else: + try: + self._modifiers.remove(key) + except KeyError: + pass + + def _as_modifier(self, key): + """Returns a key as the modifier used internally if defined. + + This method will convert values like :attr:`Key.alt_r.value` and + :attr:`Key.shift_l.value` to :attr:`Key.alt` and :attr:`Key.shift`. + + :param key: The possible modifier key. + + :return: the base modifier key, or ``None`` if ``key`` is not a + modifier + """ + from . import _NORMAL_MODIFIERS + return _NORMAL_MODIFIERS.get(key, None) + + def _handle(self, key, is_press): + """The platform implementation of the actual emitting of keyboard + events. + + This is a platform dependent implementation. + + :param Key key: The key to handle. + + :param bool is_press: Whether this is a key press event. + """ + raise NotImplementedError() + + +# pylint: disable=W0223; This is also an abstract class +class Listener(AbstractListener): + """A listener for keyboard events. + + Instances of this class can be used as context managers. This is equivalent + to the following code:: + + listener.start() + try: + listener.wait() + with_statements() + finally: + listener.stop() + + This class inherits from :class:`threading.Thread` and supports all its + methods. It will set :attr:`daemon` to ``True`` when created. + + All callback arguments are optional; a callback may take less arguments + than actually passed, but not more, unless they are optional. + + :param callable on_press: The callback to call when a button is pressed. + + It will be called with the arguments ``(key, injected)``, where ``key`` + is a :class:`KeyCode`, a :class:`Key` or ``None`` if the key is + unknown, and ``injected`` whether the event was injected and thus not + generated by an actual input device. + + Please note that not all backends support ``injected`` and will always + set it to ``False``. + + :param callable on_release: The callback to call when a button is released. + + It will be called with the arguments ``(key, injected)``, where ``key`` + is a :class:`KeyCode`, a :class:`Key` or ``None`` if the key is + unknown, and ``injected`` whether the event was injected and thus not + generated by an actual input device. + + Please note that not all backends support ``injected`` and will always + set it to ``False``. + + :param bool suppress: Whether to suppress events. Setting this to ``True`` + will prevent the input events from being passed to the rest of the + system. + + :param kwargs: Any non-standard platform dependent options. These should be + prefixed with the platform name thus: ``darwin_``, ``uinput_``, + ``xorg_`` or ``win32_``. + + Supported values are: + + ``darwin_intercept`` + A callable taking the arguments ``(event_type, event)``, where + ``event_type`` is ``Quartz.kCGEventKeyDown`` or + ``Quartz.kCGEventKeyUp``, and ``event`` is a ``CGEventRef``. + + This callable can freely modify the event using functions like + ``Quartz.CGEventSetIntegerValueField``. If this callable does not + return the event, the event is suppressed system wide. + + ``uinput_device_paths`` + A list of device paths. + + If this is specified, *pynput* will limit the number of devices + checked for the capabilities needed to those passed, otherwise all + system devices will be used. Passing this might be required if an + incorrect device is chosen. + + ``win32_event_filter`` + A callable taking the arguments ``(msg, data)``, where ``msg`` is + the current message, and ``data`` associated data as a + `KBDLLHOOKSTRUCT `_. + + If this callback returns ``False``, the event will not be + propagated to the listener callback. + + If ``self.suppress_event()`` is called, the event is suppressed + system wide. + """ + def __init__(self, on_press=None, on_release=None, suppress=False, + **kwargs): + self._log = _logger(self.__class__) + option_prefix = prefix(Listener, self.__class__) + self._options = { + key[len(option_prefix):]: value + for key, value in kwargs.items() + if key.startswith(option_prefix)} + super(Listener, self).__init__( + on_press=self._wrap(on_press, 2), + on_release=self._wrap(on_release, 2), + suppress=suppress) +# pylint: enable=W0223 + + def canonical(self, key): + """Performs normalisation of a key. + + This method attempts to convert key events to their canonical form, so + that events will equal regardless of modifier state. + + This method will convert upper case keys to lower case keys, convert + any modifiers with a right and left version to the same value, and may + slow perform additional platform dependent normalisation. + + :param key: The key to normalise. + :type key: Key or KeyCode + + :return: a key + :rtype: Key or KeyCode + """ + from pynput.keyboard import Key, KeyCode, _NORMAL_MODIFIERS + if isinstance(key, KeyCode) and key.char is not None: + return KeyCode.from_char(key.char.lower()) + elif isinstance(key, Key) and key.value in _NORMAL_MODIFIERS: + return _NORMAL_MODIFIERS[key.value] + elif isinstance(key, Key) and key.value.vk is not None: + return KeyCode.from_vk(key.value.vk) + else: + return key diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_darwin.py b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_darwin.py new file mode 100644 index 0000000..4065164 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_darwin.py @@ -0,0 +1,367 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The keyboard implementation for *macOS*. +""" + +# pylint: disable=C0111 +# The documentation is extracted from the base classes + +# pylint: disable=R0903 +# We implement stubs + +import enum + +from Quartz import ( + CGEventCreateKeyboardEvent, + CGEventGetFlags, + CGEventGetIntegerValueField, + CGEventGetType, + CGEventKeyboardGetUnicodeString, + CGEventKeyboardSetUnicodeString, + CGEventMaskBit, + CGEventPost, + CGEventSetFlags, + kCGEventFlagMaskAlternate, + kCGEventFlagMaskCommand, + kCGEventFlagMaskControl, + kCGEventFlagMaskShift, + kCGEventFlagsChanged, + kCGEventKeyDown, + kCGEventKeyUp, + kCGHIDEventTap, + kCGKeyboardEventKeycode, + NSEvent, + NSSystemDefined) + +from pynput._util.darwin import ( + get_unicode_to_keycode_map, + keycode_context, + ListenerMixin) +from pynput._util.darwin_vks import SYMBOLS +from . import _base + + +# From hidsystem/ev_keymap.h +NX_KEYTYPE_PLAY = 16 +NX_KEYTYPE_MUTE = 7 +NX_KEYTYPE_SOUND_DOWN = 1 +NX_KEYTYPE_SOUND_UP = 0 +NX_KEYTYPE_NEXT = 17 +NX_KEYTYPE_PREVIOUS = 18 +NX_KEYTYPE_EJECT = 14 + +# pylint: disable=C0103; We want to use the names from the C API +# This is undocumented, but still widely known +kSystemDefinedEventMediaKeysSubtype = 8 + +# We extract this here since the name is very long +otherEventWithType = getattr( + NSEvent, + 'otherEventWithType_' + 'location_' + 'modifierFlags_' + 'timestamp_' + 'windowNumber_' + 'context_' + 'subtype_' + 'data1_' + 'data2_') +# pylint: enable=C0103 + + +class KeyCode(_base.KeyCode): + _PLATFORM_EXTENSIONS = ( + # Whether this is a media key + '_is_media', + ) + + # Be explicit about fields + _is_media = None + + @classmethod + def _from_media(cls, vk, **kwargs): + """Creates a media key from a key code. + + :param int vk: The key code. + + :return: a key code + """ + return cls.from_vk(vk, _is_media=True, **kwargs) + + def _event(self, modifiers, mapping, is_pressed): + """This key as a *Quartz* event. + + :param set modifiers: The currently active modifiers. + + :param mapping: The current keyboard mapping. + + :param bool is_press: Whether to generate a press event. + + :return: a *Quartz* event + """ + vk = self.vk or mapping.get(self.char) + if self._is_media: + result = otherEventWithType( + NSSystemDefined, + (0, 0), + 0xa00 if is_pressed else 0xb00, + 0, + 0, + 0, + 8, + (self.vk << 16) | ((0xa if is_pressed else 0xb) << 8), + -1).CGEvent() + else: + result = CGEventCreateKeyboardEvent( + None, 0 if vk is None else vk, is_pressed) + + CGEventSetFlags( + result, + 0 + | (kCGEventFlagMaskAlternate + if Key.alt in modifiers else 0) + + | (kCGEventFlagMaskCommand + if Key.cmd in modifiers else 0) + + | (kCGEventFlagMaskControl + if Key.ctrl in modifiers else 0) + + | (kCGEventFlagMaskShift + if Key.shift in modifiers else 0)) + + if vk is None and self.char is not None: + CGEventKeyboardSetUnicodeString( + result, len(self.char), self.char) + + return result + + +# pylint: disable=W0212 +class Key(enum.Enum): + # Default keys + alt = KeyCode.from_vk(0x3A) + alt_l = KeyCode.from_vk(0x3A) + alt_r = KeyCode.from_vk(0x3D) + alt_gr = KeyCode.from_vk(0x3D) + backspace = KeyCode.from_vk(0x33) + caps_lock = KeyCode.from_vk(0x39) + cmd = KeyCode.from_vk(0x37) + cmd_l = KeyCode.from_vk(0x37) + cmd_r = KeyCode.from_vk(0x36) + ctrl = KeyCode.from_vk(0x3B) + ctrl_l = KeyCode.from_vk(0x3B) + ctrl_r = KeyCode.from_vk(0x3E) + delete = KeyCode.from_vk(0x75) + down = KeyCode.from_vk(0x7D) + end = KeyCode.from_vk(0x77) + enter = KeyCode.from_vk(0x24) + esc = KeyCode.from_vk(0x35) + f1 = KeyCode.from_vk(0x7A) + f2 = KeyCode.from_vk(0x78) + f3 = KeyCode.from_vk(0x63) + f4 = KeyCode.from_vk(0x76) + f5 = KeyCode.from_vk(0x60) + f6 = KeyCode.from_vk(0x61) + f7 = KeyCode.from_vk(0x62) + f8 = KeyCode.from_vk(0x64) + f9 = KeyCode.from_vk(0x65) + f10 = KeyCode.from_vk(0x6D) + f11 = KeyCode.from_vk(0x67) + f12 = KeyCode.from_vk(0x6F) + f13 = KeyCode.from_vk(0x69) + f14 = KeyCode.from_vk(0x6B) + f15 = KeyCode.from_vk(0x71) + f16 = KeyCode.from_vk(0x6A) + f17 = KeyCode.from_vk(0x40) + f18 = KeyCode.from_vk(0x4F) + f19 = KeyCode.from_vk(0x50) + f20 = KeyCode.from_vk(0x5A) + home = KeyCode.from_vk(0x73) + left = KeyCode.from_vk(0x7B) + page_down = KeyCode.from_vk(0x79) + page_up = KeyCode.from_vk(0x74) + right = KeyCode.from_vk(0x7C) + shift = KeyCode.from_vk(0x38) + shift_l = KeyCode.from_vk(0x38) + shift_r = KeyCode.from_vk(0x3C) + space = KeyCode.from_vk(0x31, char=' ') + tab = KeyCode.from_vk(0x30) + up = KeyCode.from_vk(0x7E) + + media_play_pause = KeyCode._from_media(NX_KEYTYPE_PLAY) + media_volume_mute = KeyCode._from_media(NX_KEYTYPE_MUTE) + media_volume_down = KeyCode._from_media(NX_KEYTYPE_SOUND_DOWN) + media_volume_up = KeyCode._from_media(NX_KEYTYPE_SOUND_UP) + media_previous = KeyCode._from_media(NX_KEYTYPE_PREVIOUS) + media_next = KeyCode._from_media(NX_KEYTYPE_NEXT) + media_eject = KeyCode._from_media(NX_KEYTYPE_EJECT) +# pylint: enable=W0212 + + +class Controller(_base.Controller): + _KeyCode = KeyCode + _Key = Key + + def __init__(self): + super(Controller, self).__init__() + self._mapping = get_unicode_to_keycode_map() + + def _handle(self, key, is_press): + with self.modifiers as modifiers: + CGEventPost( + kCGHIDEventTap, + (key if key not in (k for k in Key) else key.value)._event( + modifiers, self._mapping, is_press)) + + +class Listener(ListenerMixin, _base.Listener): + #: The events that we listen to + _EVENTS = ( + CGEventMaskBit(kCGEventKeyDown) | + CGEventMaskBit(kCGEventKeyUp) | + CGEventMaskBit(kCGEventFlagsChanged) | + CGEventMaskBit(NSSystemDefined) + ) + + # pylint: disable=W0212 + #: A mapping from keysym to special key + _SPECIAL_KEYS = { + (key.value.vk, key.value._is_media): key + for key in Key} + # pylint: enable=W0212 + + #: The event flags set for the various modifier keys + _MODIFIER_FLAGS = { + Key.alt: kCGEventFlagMaskAlternate, + Key.alt_l: kCGEventFlagMaskAlternate, + Key.alt_r: kCGEventFlagMaskAlternate, + Key.cmd: kCGEventFlagMaskCommand, + Key.cmd_l: kCGEventFlagMaskCommand, + Key.cmd_r: kCGEventFlagMaskCommand, + Key.ctrl: kCGEventFlagMaskControl, + Key.ctrl_l: kCGEventFlagMaskControl, + Key.ctrl_r: kCGEventFlagMaskControl, + Key.shift: kCGEventFlagMaskShift, + Key.shift_l: kCGEventFlagMaskShift, + Key.shift_r: kCGEventFlagMaskShift} + + def __init__(self, *args, **kwargs): + super(Listener, self).__init__(*args, **kwargs) + self._flags = 0 + self._context = None + self._intercept = self._options.get( + 'intercept', + None) + + def _run(self): + with keycode_context() as context: + self._context = context + try: + super(Listener, self)._run() + finally: + self._context = None + + def _handle_message(self, _proxy, event_type, event, _refcon, injected): + # Convert the event to a KeyCode; this may fail, and in that case we + # pass None + try: + key = self._event_to_key(event) + except IndexError: + key = None + + try: + if event_type == kCGEventKeyDown: + # This is a normal key press + self.on_press(key, injected) + + elif event_type == kCGEventKeyUp: + # This is a normal key release + self.on_release(key, injected) + + elif key == Key.caps_lock: + # We only get an event when caps lock is toggled, so we fake + # press and release + self.on_press(key, injected) + self.on_release(key, injected) + + elif event_type == NSSystemDefined: + sys_event = NSEvent.eventWithCGEvent_(event) + if sys_event.subtype() == kSystemDefinedEventMediaKeysSubtype: + # The key in the special key dict; True since it is a media + # key + key = ((sys_event.data1() & 0xffff0000) >> 16, True) + if key in self._SPECIAL_KEYS: + flags = sys_event.data1() & 0x0000ffff + is_press = ((flags & 0xff00) >> 8) == 0x0a + if is_press: + self.on_press(self._SPECIAL_KEYS[key]) + else: + self.on_release(self._SPECIAL_KEYS[key]) + + else: + # This is a modifier event---excluding caps lock---for which we + # must check the current modifier state to determine whether + # the key was pressed or released + flags = CGEventGetFlags(event) + is_press = flags & self._MODIFIER_FLAGS.get(key, 0) + if is_press: + self.on_press(key, injected) + else: + self.on_release(key, injected) + + finally: + # Store the current flag mask to be able to detect modifier state + # changes + self._flags = CGEventGetFlags(event) + + def _event_to_key(self, event): + """Converts a *Quartz* event to a :class:`KeyCode`. + + :param event: The event to convert. + + :return: a :class:`pynput.keyboard.KeyCode` + + :raises IndexError: if the key code is invalid + """ + vk = CGEventGetIntegerValueField( + event, kCGKeyboardEventKeycode) + event_type = CGEventGetType(event) + is_media = True if event_type == NSSystemDefined else None + + # First try special keys... + key = (vk, is_media) + if key in self._SPECIAL_KEYS: + return self._SPECIAL_KEYS[key] + + # ...then try characters... + length, chars = CGEventKeyboardGetUnicodeString( + event, 100, None, None) + try: + printable = chars.isprintable() + except AttributeError: + printable = chars.isalnum() + if not printable and vk in SYMBOLS \ + and CGEventGetFlags(event) \ + & kCGEventFlagMaskControl: + return KeyCode.from_char(SYMBOLS[vk], vk=vk) + elif length > 0: + return KeyCode.from_char(chars, vk=vk) + + # ...and fall back on a virtual key code + return KeyCode.from_vk(vk) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_dummy.py b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_dummy.py new file mode 100644 index 0000000..10727f6 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_dummy.py @@ -0,0 +1,23 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +This module contains a dummy implementation. + +It cannot be used, but importing it will not raise any exceptions. +""" + +from ._base import Controller, Key, KeyCode, Listener diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_uinput.py b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_uinput.py new file mode 100644 index 0000000..2f63dd3 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_uinput.py @@ -0,0 +1,446 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The keyboard implementation for *uinput*. +""" + +# pylint: disable=C0111 +# The documentation is extracted from the base classes + +# pylint: disable=R0903 +# We implement stubs + +import enum +import errno +import functools +import os +import re +import subprocess + +import evdev + +from evdev.events import KeyEvent + +from pynput._util import xorg_keysyms +from pynput._util.uinput import ListenerMixin +from . import _base + + +class KeyCode(_base.KeyCode): + _PLATFORM_EXTENSIONS = ( + # The name for this key + '_x_name', + '_kernel_name', + ) + + # Be explicit about fields + _x_name = None + _kernel_name = None +# pylint: enable=W0212 + + @classmethod + def _from_name(cls, x_name, kernel_name, **kwargs): + """Creates a key from a name. + + :param str x_name: The X name. + + :param str kernel_name: The kernel name. + + :return: a key code + """ + try: + vk = getattr(evdev.ecodes, kernel_name) + except AttributeError: + vk = None + return cls.from_vk( + vk, _x_name=x_name, _kernel_name=kernel_name, **kwargs) + + +# pylint: disable=W0212 +class Key(enum.Enum): + alt = KeyCode._from_name('Alt_L', 'KEY_LEFTALT') + alt_l = KeyCode._from_name('Alt_L', 'KEY_LEFTALT') + alt_r = KeyCode._from_name('Alt_R', 'KEY_RIGHTALT') + alt_gr = KeyCode._from_name('Mode_switch', 'KEY_RIGHTALT') + backspace = KeyCode._from_name('BackSpace', 'KEY_BACKSPACE') + caps_lock = KeyCode._from_name('Caps_Lock', 'KEY_CAPSLOCK') + cmd = KeyCode._from_name('Super_L', 'KEY_LEFTMETA') + cmd_l = KeyCode._from_name('Super_L', 'KEY_LEFTMETA') + cmd_r = KeyCode._from_name('Super_R', 'KEY_RIGHTMETA') + ctrl = KeyCode._from_name('Control_L', 'KEY_LEFTCTRL') + ctrl_l = KeyCode._from_name('Control_L', 'KEY_LEFTCTRL') + ctrl_r = KeyCode._from_name('Control_R', 'KEY_RIGHTCTRL') + delete = KeyCode._from_name('Delete', 'KEY_DELETE') + down = KeyCode._from_name('Down', 'KEY_DOWN') + end = KeyCode._from_name('End', 'KEY_END') + enter = KeyCode._from_name('Return', 'KEY_ENTER') + esc = KeyCode._from_name('Escape', 'KEY_ESC') + f1 = KeyCode._from_name('F1', 'KEY_F1') + f2 = KeyCode._from_name('F2', 'KEY_F2') + f3 = KeyCode._from_name('F3', 'KEY_F3') + f4 = KeyCode._from_name('F4', 'KEY_F4') + f5 = KeyCode._from_name('F5', 'KEY_F5') + f6 = KeyCode._from_name('F6', 'KEY_F6') + f7 = KeyCode._from_name('F7', 'KEY_F7') + f8 = KeyCode._from_name('F8', 'KEY_F8') + f9 = KeyCode._from_name('F9', 'KEY_F9') + f10 = KeyCode._from_name('F10', 'KEY_F10') + f11 = KeyCode._from_name('F11', 'KEY_F11') + f12 = KeyCode._from_name('F12', 'KEY_F12') + f13 = KeyCode._from_name('F13', 'KEY_F13') + f14 = KeyCode._from_name('F14', 'KEY_F14') + f15 = KeyCode._from_name('F15', 'KEY_F15') + f16 = KeyCode._from_name('F16', 'KEY_F16') + f17 = KeyCode._from_name('F17', 'KEY_F17') + f18 = KeyCode._from_name('F18', 'KEY_F18') + f19 = KeyCode._from_name('F19', 'KEY_F19') + f20 = KeyCode._from_name('F20', 'KEY_F20') + home = KeyCode._from_name('Home', 'KEY_HOME') + left = KeyCode._from_name('Left', 'KEY_LEFT') + page_down = KeyCode._from_name('Page_Down', 'KEY_PAGEDOWN') + page_up = KeyCode._from_name('Page_Up', 'KEY_PAGEUP') + right = KeyCode._from_name('Right', 'KEY_RIGHT') + shift = KeyCode._from_name('Shift_L', 'KEY_LEFTSHIFT') + shift_l = KeyCode._from_name('Shift_L', 'KEY_LEFTSHIFT') + shift_r = KeyCode._from_name('Shift_R', 'KEY_RIGHTSHIFT') + space = KeyCode._from_name('space', 'KEY_SPACE', char=' ') + tab = KeyCode._from_name('Tab', 'KEY_TAB', char='\t') + up = KeyCode._from_name('Up', 'KEY_UP') + + media_play_pause = KeyCode._from_name('Play', 'KEY_PLAYPAUSE') + media_volume_mute = KeyCode._from_name('Mute', 'KEY_MUTE') + media_volume_down = KeyCode._from_name('LowerVolume', 'KEY_VOLUMEDOWN') + media_volume_up = KeyCode._from_name('RaiseVolume', 'KEY_VOLUMEUP') + media_previous = KeyCode._from_name('Prev', 'KEY_PREVIOUSSONG') + media_next = KeyCode._from_name('Next', 'KEY_NEXTSONG') + + insert = KeyCode._from_name('Insert', 'KEY_INSERT') + menu = KeyCode._from_name('Menu', 'KEY_MENU') + num_lock = KeyCode._from_name('Num_Lock', 'KEY_NUMLOCK') + pause = KeyCode._from_name('Pause', 'KEY_PAUSE') + print_screen = KeyCode._from_name('Print', 'KEY_SYSRQ') + scroll_lock = KeyCode._from_name('Scroll_Lock', 'KEY_SCROLLLOCK') +# pylint: enable=W0212 + + +class Layout(object): + """A description of the keyboard layout. + """ + #: A regular expression to parse keycodes in the dumpkeys output + #: + #: The groups are: keycode number, key names. + KEYCODE_RE = re.compile( + r'keycode\s+(\d+)\s+=(.*)') + + class Key(object): + """A key in a keyboard layout. + """ + def __init__(self, normal, shifted, alt, alt_shifted): + self._values = ( + normal, + shifted, + alt, + alt_shifted) + + def __str__(self): + return ('<' + 'normal: {}, ' + 'shifted: {}, ' + 'alternative: {}, ' + 'shifted alternative: {}>').format( + self.normal, self.shifted, self.alt, self.alt_shifted) + + __repr__ = __str__ + + def __iter__(self): + return iter(self._values) + + def __getitem__(self, i): + return self._values[i] + + @property + def normal(self): + """The normal key. + """ + return self._values[0] + + @property + def shifted(self): + """The shifted key. + """ + return self._values[1] + + @property + def alt(self): + """The alternative key. + """ + return self._values[2] + + @property + def alt_shifted(self): + """The shifted alternative key. + """ + return self._values[3] + + def __init__(self): + def as_char(k): + return k.value.char if isinstance(k, Key) else k.char + self._vk_table = self._load() + self._char_table = { + as_char(key): ( + vk, + set() + | {Key.shift} if i & 1 else set() + | {Key.alt_gr} if i & 2 else set()) + for vk, keys in self._vk_table.items() + for i, key in enumerate(keys) + if key is not None and as_char(key) is not None} + + def for_vk(self, vk, modifiers): + """Reads a key for a virtual key code and modifier state. + + :param int vk: The virtual key code. + + :param set modifiers: A set of modifiers. + + :return: a mapped key + + :raises KeyError: if ``vk`` is an unknown key + """ + return self._vk_table[vk][ + 0 + | (1 if Key.shift in modifiers else 0) + | (2 if Key.alt_gr in modifiers else 0)] + + def for_char(self, char): + """Reads a virtual key code and modifier state for a character. + + :param str char: The character. + + :return: the tuple ``(vk, modifiers)`` + + :raises KeyError: if ``vk`` is an unknown key + """ + return self._char_table[char] + + @functools.lru_cache() + def _load(self): + """Loads the keyboard layout. + + For simplicity, we call out to the ``dumpkeys`` binary. In the future, + we may want to implement this ourselves. + """ + result = {} + for keycode, names in self.KEYCODE_RE.findall( + subprocess.check_output( + ['dumpkeys', '--full-table', '--keys-only']).decode('utf-8')): + vk = int(keycode) + keys = tuple( + self._parse(vk, name) + for name in names.split()[:4]) + if any(key is not None for key in keys): + result[vk] = self.Key(*keys) + return result + + def _parse(self, vk, name): + """Parses a single key from the ``dumpkeys`` output. + + :param int vk: The key code. + + :param str name: The key name. + + :return: a key representation + """ + try: + # First try special keys... + return next( + key + for key in Key + if key.value._x_name == name) + except StopIteration: + # ...then characters... + try: + _, char = xorg_keysyms.SYMBOLS[name.lstrip('+')] + if char: + return KeyCode.from_char(char, vk=vk) + except KeyError: + pass + + # ...and finally special dumpkeys names + try: + return KeyCode.from_char({ + 'one': '1', + 'two': '2', + 'three': '3', + 'four': '4', + 'five': '5', + 'six': '6', + 'seven': '7', + 'eight': '8', + 'nine': '9', + 'zero': '0'}[name]) + except KeyError: + pass + + +class Controller(_base.Controller): + _KeyCode = KeyCode + _Key = Key + + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + self._layout = LAYOUT + self._dev = evdev.UInput() + + def __del__(self): + if hasattr(self, '_dev'): + self._dev.close() + + def _handle(self, key, is_press): + # Resolve the key to a virtual key code and a possible set of required + # modifiers + try: + vk, required_modifiers = self._to_vk_and_modifiers(key) + except ValueError: + raise self.InvalidKeyException(key) + + # Determine how we need to modify the modifier state + if is_press and required_modifiers is not None: + with self.modifiers as modifiers: + vk, required_modifiers = self._layout.for_char(key.char) + to_press = { + getattr(evdev.ecodes, key.value._kernel_name) + for key in (required_modifiers - modifiers)} + to_release = { + getattr(evdev.ecodes, key.value._kernel_name) + for key in (modifiers - required_modifiers)} + else: + to_release = set() + to_press = set() + + # Update the modifier state, send the key, and finally release any + # modifiers + cleanup = [] + try: + for k in to_release: + self._send(k, False) + cleanup.append((k, True)) + for k in to_press: + self._send(k, True) + cleanup.append((k, False)) + + self._send(vk, is_press) + + finally: + for e in reversed(cleanup): + # pylint: disable E722; we want to suppress exceptions + try: + self._send(*e) + except: + pass + # pylint: enable E722 + + self._dev.syn() + + def _to_vk_and_modifiers(self, key): + """Resolves a key to a virtual key code and a modifier set. + + :param key: The key to resolve. + :type key: Key or KeyCode + + :return: a virtual key code and possible required modifiers + """ + if hasattr(key, 'vk') and key.vk is not None: + return (key.vk, None) + elif hasattr(key, 'char') and key.char is not None: + return self._layout.for_char(key.char) + else: + raise ValueError(key) + + def _send(self, vk, is_press): + """Sends a virtual key event. + + This method does not perform ``SYN``. + + :param int vk: The virtual key. + + :param bool is_press: Whether this is a press event. + """ + self._dev.write(evdev.ecodes.EV_KEY, vk, int(is_press)) + + +class Listener(ListenerMixin, _base.Listener): + _EVENTS = ( + evdev.ecodes.EV_KEY,) + + #: A + _MODIFIERS = { + Key.alt.value.vk: Key.alt, + Key.alt_l.value.vk: Key.alt, + Key.alt_r.value.vk: Key.alt, + Key.alt_gr.value.vk: Key.alt_gr, + Key.shift.value.vk: Key.shift, + Key.shift_l.value.vk: Key.shift, + Key.shift_r.value.vk: Key.shift} + + def __init__(self, *args, **kwargs): + super(Listener, self).__init__(*args, **kwargs) + self._layout = LAYOUT + self._modifiers = set() + + def _handle_message(self, event): + is_press = event.value in (KeyEvent.key_down, KeyEvent.key_hold) + vk = event.code + + # Update the modifier state + if vk in self._MODIFIERS: + modifier = self._MODIFIERS[vk] + if is_press: + self._modifiers.add(modifier) + elif modifier in self._modifiers: + self._modifiers.remove(modifier) + + # Attempt to map the virtual key code to a key + try: + key = self._layout.for_vk(vk, self._modifiers) + except KeyError: + try: + key = next( + key + for key in Key + if key.value.vk == vk) + except StopIteration: + key = KeyCode.from_vk(vk) + + # We do not know whether these events are injected + if is_press: + self.on_press(key, False) + else: + self.on_release(key, False) + + +try: + #: The keyboard layout. + LAYOUT = Layout() +except subprocess.CalledProcessError as e: + raise ImportError('failed to load keyboard layout: "' + str(e) + ( + '"; please make sure you are root' if os.getuid() != 1 else '"')) +except OSError as e: + raise ImportError({ + errno.ENOENT: 'the binary dumpkeys is not installed'}.get( + e.args[0], + str(e))) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_win32.py b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_win32.py new file mode 100644 index 0000000..fbbcc98 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_win32.py @@ -0,0 +1,389 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The keyboard implementation for *Windows*. +""" + +# pylint: disable=C0111 +# The documentation is extracted from the base classes + +# pylint: disable=R0903 +# We implement stubs + +import contextlib +import ctypes +import enum +import six + +from ctypes import wintypes + +import pynput._util.win32_vks as VK + +from pynput._util import AbstractListener +from pynput._util.win32 import ( + INPUT, + INPUT_union, + KEYBDINPUT, + KeyTranslator, + ListenerMixin, + MapVirtualKey, + SendInput, + SystemHook, + VkKeyScan) +from . import _base + + +class KeyCode(_base.KeyCode): + _PLATFORM_EXTENSIONS = ( + # Any extra flags. + '_flags', + + #: The scan code. + '_scan', + ) + + # Be explicit about fields + _flags = None + _scan = None + + def _parameters(self, is_press): + """The parameters to pass to ``SendInput`` to generate this key. + + :param bool is_press: Whether to generate a press event. + + :return: all arguments to pass to ``SendInput`` for this key + + :rtype: dict + + :raise ValueError: if this key is a unicode character that cannot be + represented by a single UTF-16 value + """ + if self.vk: + vk = self.vk + scan = self._scan \ + or MapVirtualKey(vk, MapVirtualKey.MAPVK_VK_TO_VSC) + flags = 0 + elif ord(self.char) > 0xFFFF: + raise ValueError + else: + res = VkKeyScan(self.char) + if (res >> 8) & 0xFF == 0: + vk = res & 0xFF + scan = self._scan \ + or MapVirtualKey(vk, MapVirtualKey.MAPVK_VK_TO_VSC) + flags = 0 + else: + vk = 0 + scan = ord(self.char) + flags = KEYBDINPUT.UNICODE + state_flags = (KEYBDINPUT.KEYUP if not is_press else 0) + return dict( + dwFlags=(self._flags or 0) | flags | state_flags, + wVk=vk, + wScan=scan) + + @classmethod + def _from_ext(cls, vk, **kwargs): + """Creates an extended key code. + + :param vk: The virtual key code. + + :param kwargs: Any other parameters to pass. + + :return: a key code + """ + return cls.from_vk(vk, _flags=KEYBDINPUT.EXTENDEDKEY, **kwargs) + + +# pylint: disable=W0212 +class Key(enum.Enum): + alt = KeyCode.from_vk(VK.MENU) + alt_l = KeyCode.from_vk(VK.LMENU) + alt_r = KeyCode._from_ext(VK.RMENU) + alt_gr = KeyCode.from_vk(VK.RMENU) + backspace = KeyCode.from_vk(VK.BACK) + caps_lock = KeyCode.from_vk(VK.CAPITAL) + cmd = KeyCode.from_vk(VK.LWIN) + cmd_l = KeyCode.from_vk(VK.LWIN) + cmd_r = KeyCode.from_vk(VK.RWIN) + ctrl = KeyCode.from_vk(VK.CONTROL) + ctrl_l = KeyCode.from_vk(VK.LCONTROL) + ctrl_r = KeyCode._from_ext(VK.RCONTROL) + delete = KeyCode._from_ext(VK.DELETE) + down = KeyCode._from_ext(VK.DOWN) + end = KeyCode._from_ext(VK.END) + enter = KeyCode.from_vk(VK.RETURN) + esc = KeyCode.from_vk(VK.ESCAPE) + f1 = KeyCode.from_vk(VK.F1) + f2 = KeyCode.from_vk(VK.F2) + f3 = KeyCode.from_vk(VK.F3) + f4 = KeyCode.from_vk(VK.F4) + f5 = KeyCode.from_vk(VK.F5) + f6 = KeyCode.from_vk(VK.F6) + f7 = KeyCode.from_vk(VK.F7) + f8 = KeyCode.from_vk(VK.F8) + f9 = KeyCode.from_vk(VK.F9) + f10 = KeyCode.from_vk(VK.F10) + f11 = KeyCode.from_vk(VK.F11) + f12 = KeyCode.from_vk(VK.F12) + f13 = KeyCode.from_vk(VK.F13) + f14 = KeyCode.from_vk(VK.F14) + f15 = KeyCode.from_vk(VK.F15) + f16 = KeyCode.from_vk(VK.F16) + f17 = KeyCode.from_vk(VK.F17) + f18 = KeyCode.from_vk(VK.F18) + f19 = KeyCode.from_vk(VK.F19) + f20 = KeyCode.from_vk(VK.F20) + f21 = KeyCode.from_vk(VK.F21) + f22 = KeyCode.from_vk(VK.F22) + f23 = KeyCode.from_vk(VK.F23) + f24 = KeyCode.from_vk(VK.F24) + home = KeyCode._from_ext(VK.HOME) + left = KeyCode._from_ext(VK.LEFT) + page_down = KeyCode._from_ext(VK.NEXT) + page_up = KeyCode._from_ext(VK.PRIOR) + right = KeyCode._from_ext(VK.RIGHT) + shift = KeyCode.from_vk(VK.LSHIFT) + shift_l = KeyCode.from_vk(VK.LSHIFT) + shift_r = KeyCode.from_vk(VK.RSHIFT) + space = KeyCode.from_vk(VK.SPACE, char=' ') + tab = KeyCode.from_vk(VK.TAB) + up = KeyCode._from_ext(VK.UP) + + media_play_pause = KeyCode._from_ext(VK.MEDIA_PLAY_PAUSE) + media_stop = KeyCode._from_ext(VK.MEDIA_STOP) + media_volume_mute = KeyCode._from_ext(VK.VOLUME_MUTE) + media_volume_down = KeyCode._from_ext(VK.VOLUME_DOWN) + media_volume_up = KeyCode._from_ext(VK.VOLUME_UP) + media_previous = KeyCode._from_ext(VK.MEDIA_PREV_TRACK) + media_next = KeyCode._from_ext(VK.MEDIA_NEXT_TRACK) + + insert = KeyCode._from_ext(VK.INSERT) + menu = KeyCode.from_vk(VK.APPS) + num_lock = KeyCode._from_ext(VK.NUMLOCK) + pause = KeyCode.from_vk(VK.PAUSE) + print_screen = KeyCode._from_ext(VK.SNAPSHOT) + scroll_lock = KeyCode.from_vk(VK.SCROLL) +# pylint: enable=W0212 + + +class Controller(_base.Controller): + _KeyCode = KeyCode + _Key = Key + + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + + def _handle(self, key, is_press): + try: + SendInput( + 1, + ctypes.byref(INPUT( + type=INPUT.KEYBOARD, + value=INPUT_union( + ki=KEYBDINPUT(**key._parameters(is_press))))), + ctypes.sizeof(INPUT)) + except ValueError: + # If key._parameters raises ValueError, the key is a unicode + # characters outsice of the range of a single UTF-16 value, and we + # must break it up into its surrogates + byte_data = bytearray(key.char.encode('utf-16le')) + surrogates = [ + byte_data[i] | (byte_data[i + 1] << 8) + for i in range(0, len(byte_data), 2)] + + state_flags = KEYBDINPUT.UNICODE \ + | (KEYBDINPUT.KEYUP if not is_press else 0) + + SendInput( + len(surrogates), + (INPUT * len(surrogates))(*( + INPUT( + INPUT.KEYBOARD, + INPUT_union( + ki=KEYBDINPUT( + dwFlags=state_flags, + wScan=scan))) + for scan in surrogates)), + ctypes.sizeof(INPUT)) + + +class Listener(ListenerMixin, _base.Listener): + #: The Windows hook ID for low level keyboard events, ``WH_KEYBOARD_LL`` + _EVENTS = 13 + + _WM_INPUTLANGCHANGE = 0x0051 + _WM_KEYDOWN = 0x0100 + _WM_KEYUP = 0x0101 + _WM_SYSKEYDOWN = 0x0104 + _WM_SYSKEYUP = 0x0105 + + # A bit flag attached to messages indicating that the payload is an actual + # UTF-16 character code + _UTF16_FLAG = 0x1000 + + # A bit flag attached to messages indicating that the event was injected + _INJECTED_FLAG = 0x2000 + + # A special virtual key code designating unicode characters + _VK_PACKET = 0xE7 + + #: The messages that correspond to a key press + _PRESS_MESSAGES = (_WM_KEYDOWN, _WM_SYSKEYDOWN) + + #: The messages that correspond to a key release + _RELEASE_MESSAGES = (_WM_KEYUP, _WM_SYSKEYUP) + + #: Additional window messages to propagate to the subclass handler. + _WM_NOTIFICATIONS = ( + _WM_INPUTLANGCHANGE, + ) + + #: A mapping from keysym to special key + _SPECIAL_KEYS = { + key.value.vk: key + for key in Key} + + _HANDLED_EXCEPTIONS = ( + SystemHook.SuppressException,) + + class _KBDLLHOOKSTRUCT(ctypes.Structure): + """Contains information about a mouse event passed to a + ``WH_KEYBOARD_LL`` hook procedure, ``LowLevelKeyboardProc``. + """ + LLKHF_INJECTED = 0x00000010 + LLKHF_LOWER_IL_INJECTED = 0x00000002 + _fields_ = [ + ('vkCode', wintypes.DWORD), + ('scanCode', wintypes.DWORD), + ('flags', wintypes.DWORD), + ('time', wintypes.DWORD), + ('dwExtraInfo', ctypes.c_void_p)] + + #: A pointer to a :class:`KBDLLHOOKSTRUCT` + _LPKBDLLHOOKSTRUCT = ctypes.POINTER(_KBDLLHOOKSTRUCT) + + def __init__(self, *args, **kwargs): + super(Listener, self).__init__(*args, **kwargs) + self._translator = KeyTranslator() + self._event_filter = self._options.get( + 'event_filter', + lambda msg, data: True) + + def _convert(self, code, msg, lpdata): + if code != SystemHook.HC_ACTION: + return + + data = ctypes.cast(lpdata, self._LPKBDLLHOOKSTRUCT).contents + is_packet = data.vkCode == self._VK_PACKET + injected = (data.flags & (0 + | self._KBDLLHOOKSTRUCT.LLKHF_INJECTED + | self._KBDLLHOOKSTRUCT.LLKHF_LOWER_IL_INJECTED)) != 0 + message = (msg + | (self._UTF16_FLAG if is_packet else 0) + | (self._INJECTED_FLAG if injected else 0)) + + # Suppress further propagation of the event if it is filtered + if self._event_filter(msg, data) is False: + return None + elif is_packet: + return (message, data.scanCode) + else: + return (message, data.vkCode) + + @AbstractListener._emitter + def _process(self, wparam, lparam): + msg = wparam + vk = lparam + + # If the key has the UTF-16 flag, we treat it as a unicode character, + # otherwise convert the event to a KeyCode; this may fail, and in that + # case we pass None + is_utf16 = msg & self._UTF16_FLAG + injected = bool(msg & self._INJECTED_FLAG) + message = msg & ~(self._UTF16_FLAG | self._INJECTED_FLAG) + if is_utf16: + scan = vk + key = KeyCode.from_char(six.unichr(scan)) + else: + try: + key = self._event_to_key(msg, vk) + except OSError: + key = None + + if message in self._PRESS_MESSAGES: + self.on_press(key, injected) + + elif message in self._RELEASE_MESSAGES: + self.on_release(key, injected) + + # pylint: disable=R0201 + @contextlib.contextmanager + def _receive(self): + """An empty context manager; we do not need to fake keyboard events. + """ + yield + # pylint: enable=R0201 + + def _on_notification(self, code, wparam, lparam): + """Receives ``WM_INPUTLANGCHANGE`` and updates the cached layout. + """ + if code == self._WM_INPUTLANGCHANGE: + self._translator.update_layout() + + def _event_to_key(self, msg, vk): + """Converts an :class:`_KBDLLHOOKSTRUCT` to a :class:`KeyCode`. + + :param msg: The message received. + + :param vk: The virtual key code to convert. + + :return: a :class:`pynput.keyboard.KeyCode` + + :raises OSError: if the message and data could not be converted + """ + # If the virtual key code corresponds to a Key value, we prefer that + if vk in self._SPECIAL_KEYS: + return self._SPECIAL_KEYS[vk] + else: + return KeyCode(**self._translate( + vk, + msg in self._PRESS_MESSAGES)) + + def _translate(self, vk, is_press): + """Translates a virtual key code to a parameter list passable to + :class:`pynput.keyboard.KeyCode`. + + :param int vk: The virtual key code. + + :param bool is_press: Whether this is a press event. + + :return: a parameter list to the :class:`pynput.keyboard.KeyCode` + constructor + """ + return self._translator(vk, is_press) + + def canonical(self, key): + # If the key has a scan code, and we can find the character for it, + # return that, otherwise call the super class + scan = getattr(key, '_scan', None) + if scan is not None: + char = self._translator.char_from_scan(scan) + if char is not None: + return KeyCode.from_char(char) + + return super(Listener, self).canonical(key) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_xorg.py b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_xorg.py new file mode 100644 index 0000000..7011a5a --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/keyboard/_xorg.py @@ -0,0 +1,667 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The keyboard implementation for *Xorg*. +""" + +# pylint: disable=C0111 +# The documentation is extracted from the base classes + +# pylint: disable=R0903 +# We implement stubs + +# pylint: disable=W0611 +try: + import pynput._util.xorg +except Exception as e: + raise ImportError('failed to acquire X connection: {}'.format(str(e)), e) +# pylint: enable=W0611 + +import enum +import threading + +import Xlib.display +import Xlib.ext +import Xlib.ext.xtest +import Xlib.X +import Xlib.XK +import Xlib.protocol +import Xlib.keysymdef.xkb + +from pynput._util import NotifierMixin +from pynput._util.xorg import ( + alt_mask, + alt_gr_mask, + char_to_keysym, + display_manager, + index_to_shift, + keyboard_mapping, + ListenerMixin, + numlock_mask, + shift_to_index, + symbol_to_keysym) +from pynput._util.xorg_keysyms import ( + CHARS, + DEAD_KEYS, + KEYPAD_KEYS, + KEYSYMS, + SYMBOLS) +from . import _base + + +class KeyCode(_base.KeyCode): + _PLATFORM_EXTENSIONS = ( + # The symbol name for this key + '_symbol', + ) + + # Be explicit about fields + _symbol = None + + @classmethod + def _from_symbol(cls, symbol, **kwargs): + """Creates a key from a symbol. + + :param str symbol: The symbol name. + + :return: a key code + """ + # First try simple translation + keysym = Xlib.XK.string_to_keysym(symbol) + if keysym: + return cls.from_vk(keysym, _symbol=symbol, **kwargs) + + # If that fails, try checking a module attribute of Xlib.keysymdef.xkb + if not keysym: + # pylint: disable=W0702; we want to ignore errors + try: + symbol = 'XK_' + symbol + return cls.from_vk( + getattr(Xlib.keysymdef.xkb, symbol, 0), + _symbol=symbol, + **kwargs) + except: + return cls.from_vk( + SYMBOLS.get(symbol, (0,))[0], + _symbol=symbol, + **kwargs) + # pylint: enable=W0702 + + @classmethod + def _from_media(cls, name, **kwargs): + """Creates a media key from a partial name. + + :param str name: The name. The actual symbol name will be this string + with ``'XF86_Audio'`` prepended. + + :return: a key code + """ + return cls._from_symbol('XF86_Audio' + name, **kwargs) + + +# pylint: disable=W0212 +class Key(enum.Enum): + # Default keys + alt = KeyCode._from_symbol('Alt_L') + alt_l = KeyCode._from_symbol('Alt_L') + alt_r = KeyCode._from_symbol('Alt_R') + alt_gr = KeyCode._from_symbol('Mode_switch') + backspace = KeyCode._from_symbol('BackSpace') + caps_lock = KeyCode._from_symbol('Caps_Lock') + cmd = KeyCode._from_symbol('Super_L') + cmd_l = KeyCode._from_symbol('Super_L') + cmd_r = KeyCode._from_symbol('Super_R') + ctrl = KeyCode._from_symbol('Control_L') + ctrl_l = KeyCode._from_symbol('Control_L') + ctrl_r = KeyCode._from_symbol('Control_R') + delete = KeyCode._from_symbol('Delete') + down = KeyCode._from_symbol('Down') + end = KeyCode._from_symbol('End') + enter = KeyCode._from_symbol('Return') + esc = KeyCode._from_symbol('Escape') + f1 = KeyCode._from_symbol('F1') + f2 = KeyCode._from_symbol('F2') + f3 = KeyCode._from_symbol('F3') + f4 = KeyCode._from_symbol('F4') + f5 = KeyCode._from_symbol('F5') + f6 = KeyCode._from_symbol('F6') + f7 = KeyCode._from_symbol('F7') + f8 = KeyCode._from_symbol('F8') + f9 = KeyCode._from_symbol('F9') + f10 = KeyCode._from_symbol('F10') + f11 = KeyCode._from_symbol('F11') + f12 = KeyCode._from_symbol('F12') + f13 = KeyCode._from_symbol('F13') + f14 = KeyCode._from_symbol('F14') + f15 = KeyCode._from_symbol('F15') + f16 = KeyCode._from_symbol('F16') + f17 = KeyCode._from_symbol('F17') + f18 = KeyCode._from_symbol('F18') + f19 = KeyCode._from_symbol('F19') + f20 = KeyCode._from_symbol('F20') + home = KeyCode._from_symbol('Home') + left = KeyCode._from_symbol('Left') + page_down = KeyCode._from_symbol('Page_Down') + page_up = KeyCode._from_symbol('Page_Up') + right = KeyCode._from_symbol('Right') + shift = KeyCode._from_symbol('Shift_L') + shift_l = KeyCode._from_symbol('Shift_L') + shift_r = KeyCode._from_symbol('Shift_R') + space = KeyCode._from_symbol('space', char=' ') + tab = KeyCode._from_symbol('Tab') + up = KeyCode._from_symbol('Up') + + media_play_pause = KeyCode._from_media('Play') + media_volume_mute = KeyCode._from_media('Mute') + media_volume_down = KeyCode._from_media('LowerVolume') + media_volume_up = KeyCode._from_media('RaiseVolume') + media_previous = KeyCode._from_media('Prev') + media_next = KeyCode._from_media('Next') + + insert = KeyCode._from_symbol('Insert') + menu = KeyCode._from_symbol('Menu') + num_lock = KeyCode._from_symbol('Num_Lock') + pause = KeyCode._from_symbol('Pause') + print_screen = KeyCode._from_symbol('Print') + scroll_lock = KeyCode._from_symbol('Scroll_Lock') +# pylint: enable=W0212 + + +class Controller(NotifierMixin, _base.Controller): + _KeyCode = KeyCode + _Key = Key + + #: The shift mask for :attr:`Key.ctrl` + CTRL_MASK = Xlib.X.ControlMask + + #: The shift mask for :attr:`Key.shift` + SHIFT_MASK = Xlib.X.ShiftMask + + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + self._display = Xlib.display.Display() + self._keyboard_mapping = None + self._borrows = {} + self._borrow_lock = threading.RLock() + + # pylint: disable=C0103; this is treated as a class scope constant, but + # we cannot set it in the class scope, as it requires a Display instance + self.ALT_MASK = alt_mask(self._display) + self.ALT_GR_MASK = alt_gr_mask(self._display) + # pylint: enable=C0103 + + def __del__(self): + if hasattr(self, '_display'): + self._display.close() + + @property + def keyboard_mapping(self): + """A mapping from *keysyms* to *key codes*. + + Each value is the tuple ``(key_code, shift_state)``. By sending an + event with the specified *key code* and shift state, the specified + *keysym* will be touched. + """ + if not self._keyboard_mapping: + self._update_keyboard_mapping() + return self._keyboard_mapping + + def _handle(self, key, is_press): + """Resolves a key identifier and sends a keyboard event. + + :param int key: The key to handle. + :param bool is_press: Whether this is a press. + """ + event = Xlib.display.event.KeyPress if is_press \ + else Xlib.display.event.KeyRelease + keysym = self._keysym(key) + + # Make sure to verify that the key was resolved + if keysym is None: + raise self.InvalidKeyException(key) + + # If the key has a virtual key code, use that immediately with + # fake_input; fake input,being an X server extension, has access to + # more internal state that we do + if key.vk is not None: + with display_manager(self._display) as dm: + Xlib.ext.xtest.fake_input( + dm, + Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease, + dm.keysym_to_keycode(key.vk)) + + # Otherwise use XSendEvent; we need to use this in the general case to + # work around problems with keyboard layouts + else: + try: + keycode, shift_state = self.keyboard_mapping[keysym] + self._send_key(event, keycode, shift_state) + + except KeyError: + with self._borrow_lock: + keycode, index, count = self._borrows[keysym] + self._send_key( + event, + keycode, + index_to_shift(self._display, index)) + count += 1 if is_press else -1 + self._borrows[keysym] = (keycode, index, count) + + # Notify any running listeners + self._emit('_on_fake_event', key, is_press) + + def _keysym(self, key): + """Converts a key to a *keysym*. + + :param KeyCode key: The key code to convert. + """ + return self._resolve_dead(key) if key.is_dead else None \ + or self._resolve_special(key) \ + or self._resolve_normal(key) \ + or self._resolve_borrowed(key) \ + or self._resolve_borrowing(key) + + def _send_key(self, event, keycode, shift_state): + """Sends a single keyboard event. + + :param event: The *X* keyboard event. + + :param int keycode: The calculated keycode. + + :param int shift_state: The shift state. The actual value used is + :attr:`shift_state` or'd with this value. + """ + with display_manager(self._display) as dm, self.modifiers as modifiers: + # Under certain cimcumstances, such as when running under Xephyr, + # the value returned by dm.get_input_focus is an int + window = dm.get_input_focus().focus + send_event = getattr( + window, + 'send_event', + lambda event: dm.send_event(window, event)) + send_event(event( + detail=keycode, + state=shift_state | self._shift_mask(modifiers), + time=0, + root=dm.screen().root, + window=window, + same_screen=0, + child=Xlib.X.NONE, + root_x=0, root_y=0, event_x=0, event_y=0)) + + def _resolve_dead(self, key): + """Tries to resolve a dead key. + + :param str identifier: The identifier to resolve. + """ + # pylint: disable=W0702; we want to ignore errors + try: + keysym, _ = SYMBOLS[CHARS[key.combining]] + except: + return None + # pylint: enable=W0702 + + if keysym not in self.keyboard_mapping: + return None + + return keysym + + def _resolve_special(self, key): + """Tries to resolve a special key. + + A special key has the :attr:`~KeyCode.vk` attribute set. + + :param KeyCode key: The key to resolve. + """ + if not key.vk: + return None + + return key.vk + + def _resolve_normal(self, key): + """Tries to resolve a normal key. + + A normal key exists on the keyboard, and is typed by pressing + and releasing a simple key, possibly in combination with a modifier. + + :param KeyCode key: The key to resolve. + """ + keysym = self._key_to_keysym(key) + if keysym is None: + return None + + if keysym not in self.keyboard_mapping: + return None + + return keysym + + def _resolve_borrowed(self, key): + """Tries to resolve a key by looking up the already borrowed *keysyms*. + + A borrowed *keysym* does not exist on the keyboard, but has been + temporarily added to the layout. + + :param KeyCode key: The key to resolve. + """ + keysym = self._key_to_keysym(key) + if keysym is None: + return None + + with self._borrow_lock: + if keysym not in self._borrows: + return None + + return keysym + + def _resolve_borrowing(self, key): + """Tries to resolve a key by modifying the layout temporarily. + + A borrowed *keysym* does not exist on the keyboard, but is temporarily + added to the layout. + + :param KeyCode key: The key to resolve. + """ + keysym = self._key_to_keysym(key) + if keysym is None: + return None + + mapping = self._display.get_keyboard_mapping(8, 255 - 8) + + def i2kc(index): + return index + 8 + + def kc2i(keycode): + return keycode - 8 + + #: Finds a keycode and index by looking at already used keycodes + def reuse(): + for _, (keycode, _, _) in self._borrows.items(): + keycodes = mapping[kc2i(keycode)] + + # Only the first four items are addressable by X + for index in range(4): + if not keycodes[index]: + return keycode, index + + #: Finds a keycode and index by using a new keycode + def borrow(): + for i, keycodes in enumerate(mapping): + if not any(keycodes): + return i2kc(i), 0 + + #: Finds a keycode and index by reusing an old, unused one + def overwrite(): + for keysym, (keycode, index, count) in self._borrows.items(): + if count < 1: + del self._borrows[keysym] + return keycode, index + + #: Registers a keycode for a specific key and modifier state + def register(dm, keycode, index): + i = kc2i(keycode) + + # Check for use of empty mapping with a character that has upper + # and lower forms + lower = key.char.lower() + upper = key.char.upper() + if lower != upper and len(lower) == 1 and len(upper) == 1 and all( + m == Xlib.XK.NoSymbol + for m in mapping[i]): + lower = self._key_to_keysym(KeyCode.from_char(lower)) + upper = self._key_to_keysym(KeyCode.from_char(upper)) + if lower: + mapping[i][0] = lower + self._borrows[lower] = (keycode, 0, 0) + if upper: + mapping[i][1] = upper + self._borrows[upper] = (keycode, 1, 0) + else: + mapping[i][index] = keysym + self._borrows[keysym] = (keycode, index, 0) + dm.change_keyboard_mapping(keycode, mapping[i:i + 1]) + + try: + with display_manager(self._display) as dm, self._borrow_lock as _: + # First try an already used keycode, then try a new one, and + # fall back on reusing one that is not currently pressed + register(dm, *( + reuse() or + borrow() or + overwrite())) + return keysym + + except TypeError: + return None + + def _key_to_keysym(self, key): + """Converts a character key code to a *keysym*. + + :param KeyCode key: The key code. + + :return: a keysym if found + :rtype: int or None + """ + # If the key code already has a VK, simply return it + if key.vk is not None: + return key.vk + + # If the character has no associated symbol, we try to map the + # character to a keysym + symbol = CHARS.get(key.char, None) + if symbol is None: + return char_to_keysym(key.char) + + # Otherwise we attempt to convert the symbol to a keysym + # pylint: disable=W0702; we want to ignore errors + try: + return symbol_to_keysym(symbol) + except: + try: + return SYMBOLS[symbol][0] + except: + return None + # pylint: enable=W0702 + + def _shift_mask(self, modifiers): + """The *X* modifier mask to apply for a set of modifiers. + + :param set modifiers: A set of active modifiers for which to get the + shift mask. + """ + return ( + 0 + | (self.ALT_MASK + if Key.alt in modifiers else 0) + + | (self.ALT_GR_MASK + if Key.alt_gr in modifiers else 0) + + | (self.CTRL_MASK + if Key.ctrl in modifiers else 0) + + | (self.SHIFT_MASK + if Key.shift in modifiers else 0)) + + def _update_keyboard_mapping(self): + """Updates the keyboard mapping. + """ + with display_manager(self._display) as dm: + self._keyboard_mapping = keyboard_mapping(dm) + + +@Controller._receiver +class Listener(ListenerMixin, _base.Listener): + _EVENTS = ( + Xlib.X.KeyPress, + Xlib.X.KeyRelease) + + #: A mapping from keysym to special key + _SPECIAL_KEYS = { + key.value.vk: key + for key in Key} + + #: A mapping from numeric keypad keys to keys + _KEYPAD_KEYS = { + KEYPAD_KEYS['KP_0']: KeyCode.from_char('0'), + KEYPAD_KEYS['KP_1']: KeyCode.from_char('1'), + KEYPAD_KEYS['KP_2']: KeyCode.from_char('2'), + KEYPAD_KEYS['KP_3']: KeyCode.from_char('3'), + KEYPAD_KEYS['KP_4']: KeyCode.from_char('4'), + KEYPAD_KEYS['KP_5']: KeyCode.from_char('5'), + KEYPAD_KEYS['KP_6']: KeyCode.from_char('6'), + KEYPAD_KEYS['KP_7']: KeyCode.from_char('7'), + KEYPAD_KEYS['KP_8']: KeyCode.from_char('8'), + KEYPAD_KEYS['KP_9']: KeyCode.from_char('9'), + KEYPAD_KEYS['KP_Add']: KeyCode.from_char('+'), + KEYPAD_KEYS['KP_Decimal']: KeyCode.from_char(','), + KEYPAD_KEYS['KP_Delete']: Key.delete, + KEYPAD_KEYS['KP_Divide']: KeyCode.from_char('/'), + KEYPAD_KEYS['KP_Down']: Key.down, + KEYPAD_KEYS['KP_End']: Key.end, + KEYPAD_KEYS['KP_Enter']: Key.enter, + KEYPAD_KEYS['KP_Equal']: KeyCode.from_char('='), + KEYPAD_KEYS['KP_F1']: Key.f1, + KEYPAD_KEYS['KP_F2']: Key.f2, + KEYPAD_KEYS['KP_F3']: Key.f3, + KEYPAD_KEYS['KP_F4']: Key.f4, + KEYPAD_KEYS['KP_Home']: Key.home, + KEYPAD_KEYS['KP_Insert']: Key.insert, + KEYPAD_KEYS['KP_Left']: Key.left, + KEYPAD_KEYS['KP_Multiply']: KeyCode.from_char('*'), + KEYPAD_KEYS['KP_Page_Down']: Key.page_down, + KEYPAD_KEYS['KP_Page_Up']: Key.page_up, + KEYPAD_KEYS['KP_Right']: Key.right, + KEYPAD_KEYS['KP_Space']: Key.space, + KEYPAD_KEYS['KP_Subtract']: KeyCode.from_char('-'), + KEYPAD_KEYS['KP_Tab']: Key.tab, + KEYPAD_KEYS['KP_Up']: Key.up} + + def __init__(self, *args, **kwargs): + super(Listener, self).__init__(*args, **kwargs) + self._keyboard_mapping = None + + def _run(self): + with self._receive(): + super(Listener, self)._run() + + def _initialize(self, display): + # Get the keyboard mapping to be able to translate event details to + # key codes + min_keycode = display.display.info.min_keycode + keycode_count = display.display.info.max_keycode - min_keycode + 1 + self._keyboard_mapping = display.get_keyboard_mapping( + min_keycode, keycode_count) + + def _handle_message(self, display, event, injected): + # Convert the event to a KeyCode; this may fail, and in that case we + # pass None + try: + key = self._event_to_key(display, event) + except IndexError: + key = None + + if event.type == Xlib.X.KeyPress: + self.on_press(key, injected) + + elif event.type == Xlib.X.KeyRelease: + self.on_release(key, injected) + + def _suppress_start(self, display): + display.screen().root.grab_keyboard( + self._event_mask, Xlib.X.GrabModeAsync, Xlib.X.GrabModeAsync, + Xlib.X.CurrentTime) + + def _suppress_stop(self, display): + display.ungrab_keyboard(Xlib.X.CurrentTime) + + def _on_fake_event(self, key, is_press): + """The handler for fake press events sent by the controllers. + + :param KeyCode key: The key pressed. + + :param bool is_press: Whether this is a press event. + """ + (self.on_press if is_press else self.on_release)( + self._SPECIAL_KEYS.get(key.vk, key), True) + + def _keycode_to_keysym(self, display, keycode, index): + """Converts a keycode and shift state index to a keysym. + + This method uses a simplified version of the *X* convention to locate + the correct keysym in the display table: since this method is only used + to locate special keys, alphanumeric keys are not treated specially. + + :param display: The current *X* display. + + :param keycode: The keycode. + + :param index: The shift state index. + + :return: a keysym + """ + keysym = display.keycode_to_keysym(keycode, index) + if keysym: + return keysym + elif index & 0x2: + return self._keycode_to_keysym(display, keycode, index & ~0x2) + elif index & 0x1: + return self._keycode_to_keysym(display, keycode, index & ~0x1) + else: + return 0 + + def _event_to_key(self, display, event): + """Converts an *X* event to a :class:`KeyCode`. + + :param display: The current *X* display. + + :param event: The event to convert. + + :return: a :class:`pynput.keyboard.KeyCode` + + :raises IndexError: if the key code is invalid + """ + keycode = event.detail + index = shift_to_index(display, event.state) + + # First try special keys... + keysym = self._keycode_to_keysym(display, keycode, index) + if keysym in self._SPECIAL_KEYS: + return self._SPECIAL_KEYS[keysym] + elif keysym in self._KEYPAD_KEYS: + # We must recalculate the index if numlock is active; index 1 is the + # one to use + try: + return self._KEYPAD_KEYS[ + self._keycode_to_keysym( + display, + keycode, + bool(event.state & numlock_mask(display)))] + except KeyError: + # Since we recalculated the key, this may happen + pass + + # ...then try characters... + name = KEYSYMS.get(keysym, None) + if name is not None and name in SYMBOLS: + char = SYMBOLS[name][1].upper() if index & 1 else SYMBOLS[name][1] + if char in DEAD_KEYS: + return KeyCode.from_dead(DEAD_KEYS[char], vk=keysym) + else: + return KeyCode.from_char(char, vk=keysym) + + # ...and fall back on a virtual key code + return KeyCode.from_vk(keysym) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__init__.py b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__init__.py new file mode 100644 index 0000000..3456629 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__init__.py @@ -0,0 +1,107 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The module containing mouse classes. + +See the documentation for more information. +""" + +# pylint: disable=C0103 +# Button, Controller and Listener are not constants + +from pynput._util import backend, Events + + +backend = backend(__name__) +Button = backend.Button +Controller = backend.Controller +Listener = backend.Listener +del backend + + +class Events(Events): + """A mouse event listener supporting synchronous iteration over the events. + + Possible events are: + + :class:`Events.Move` + The mouse was moved. + + :class:`Events.Click` + A mouse button was pressed or released. + + :class:`Events.Scroll` + The device was scrolled. + """ + _Listener = Listener + + class Move(Events.Event): + """A move event. + """ + def __init__(self, x, y, injected): + #: The X screen coordinate. + self.x = x + + #: The Y screen coordinate. + self.y = y + + #: Whether this event is synthetic. + self.injected = injected + + class Click(Events.Event): + """A click event. + """ + def __init__(self, x, y, button, pressed, injected): + #: The X screen coordinate. + self.x = x + + #: The Y screen coordinate. + self.y = y + + #: The button. + self.button = button + + #: Whether the button was pressed. + self.pressed = pressed + + #: Whether this event is synthetic. + self.injected = injected + + class Scroll(Events.Event): + """A scroll event. + """ + def __init__(self, x, y, dx, dy, injected): + #: The X screen coordinate. + self.x = x + + #: The Y screen coordinate. + self.y = y + + #: The number of horisontal steps. + self.dx = dx + + #: The number of vertical steps. + self.dy = dy + + #: Whether this event is synthetic. + self.injected = injected + + def __init__(self): + super(Events, self).__init__( + on_move=self.Move, + on_click=self.Click, + on_scroll=self.Scroll) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/__init__.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..b96e477 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/__init__.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_base.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_base.cpython-312.pyc new file mode 100644 index 0000000..c4bbd39 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_base.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_darwin.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_darwin.cpython-312.pyc new file mode 100644 index 0000000..be6d042 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_darwin.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_dummy.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_dummy.cpython-312.pyc new file mode 100644 index 0000000..5e8aba4 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_dummy.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_win32.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_win32.cpython-312.pyc new file mode 100644 index 0000000..b11ac73 Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_win32.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_xorg.cpython-312.pyc b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_xorg.cpython-312.pyc new file mode 100644 index 0000000..527bade Binary files /dev/null and b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/__pycache__/_xorg.cpython-312.pyc differ diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_base.py b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_base.py new file mode 100644 index 0000000..186a7d7 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_base.py @@ -0,0 +1,281 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +This module contains the base implementation. + +The actual interface to mouse classes is defined here, but the implementation +is located in a platform dependent module. +""" + +# pylint: disable=R0903 +# We implement stubs + +import enum + +from pynput._util import AbstractListener, prefix +from pynput import _logger + + +class Button(enum.Enum): + """The various buttons. + + The actual values for these items differ between platforms. Some + platforms may have additional buttons, but these are guaranteed to be + present everywhere. + """ + #: An unknown button was pressed + unknown = 0 + + #: The left button + left = 1 + + #: The middle button + middle = 2 + + #: The right button + right = 3 + + +class Controller(object): + """A controller for sending virtual mouse events to the system. + """ + def __init__(self): + self._log = _logger(self.__class__) + + @property + def position(self): + """The current position of the mouse pointer. + + This is the tuple ``(x, y)``, and setting it will move the pointer. + """ + return self._position_get() + + @position.setter + def position(self, pos): + self._position_set(pos) + + def scroll(self, dx, dy): + """Sends scroll events. + + :param int dx: The horizontal scroll. The units of scrolling is + undefined. + + :param int dy: The vertical scroll. The units of scrolling is + undefined. + + :raises ValueError: if the values are invalid, for example out of + bounds + """ + self._scroll(dx, dy) + + def press(self, button): + """Emits a button press event at the current position. + + :param Button button: The button to press. + """ + self._press(button) + + def release(self, button): + """Emits a button release event at the current position. + + :param Button button: The button to release. + """ + self._release(button) + + def move(self, dx, dy): + """Moves the mouse pointer a number of pixels from its current + position. + + :param int dx: The horizontal offset. + + :param int dy: The vertical offset. + + :raises ValueError: if the values are invalid, for example out of + bounds + """ + self.position = tuple(sum(i) for i in zip(self.position, (dx, dy))) + + def click(self, button, count=1): + """Emits a button click event at the current position. + + The default implementation sends a series of press and release events. + + :param Button button: The button to click. + + :param int count: The number of clicks to send. + """ + with self as controller: + for _ in range(count): + controller.press(button) + controller.release(button) + + def __enter__(self): + """Begins a series of clicks. + + In the default :meth:`click` implementation, the return value of this + method is used for the calls to :meth:`press` and :meth:`release` + instead of ``self``. + + The default implementation is a no-op. + """ + return self + + def __exit__(self, exc_type, value, traceback): + """Ends a series of clicks. + """ + pass + + def _position_get(self): + """The implementation of the getter for :attr:`position`. + + This is a platform dependent implementation. + """ + raise NotImplementedError() + + def _position_set(self, pos): + """The implementation of the setter for :attr:`position`. + + This is a platform dependent implementation. + """ + raise NotImplementedError() + + def _scroll(self, dx, dy): + """The implementation of the :meth:`scroll` method. + + This is a platform dependent implementation. + """ + raise NotImplementedError() + + def _press(self, button): + """The implementation of the :meth:`press` method. + + This is a platform dependent implementation. + """ + raise NotImplementedError() + + def _release(self, button): + """The implementation of the :meth:`release` method. + + This is a platform dependent implementation. + """ + raise NotImplementedError() + + +# pylint: disable=W0223; This is also an abstract class +class Listener(AbstractListener): + """A listener for mouse events. + + Instances of this class can be used as context managers. This is equivalent + to the following code:: + + listener.start() + try: + listener.wait() + with_statements() + finally: + listener.stop() + + This class inherits from :class:`threading.Thread` and supports all its + methods. It will set :attr:`daemon` to ``True`` when created. + + All callback arguments are optional; a callback may take less arguments + than actually passed, but not more, unless they are optional. + + :param callable on_move: The callback to call when mouse move events occur. + + It will be called with the arguments ``(x, y, injected)``, where ``(x, + y)`` is the new pointer position and ``injected`` whether the event was + injected and thus not generated by an actual input device. If this + callback raises :class:`StopException` or returns ``False``, the + listener is stopped. + + Please note that not all backends support ``injected`` and will always + set it to ``False``. + + :param callable on_click: The callback to call when a mouse button is + clicked. + + It will be called with the arguments ``(x, y, button, pressed, + injected)``, where ``(x, y)`` is the new pointer position, ``button`` + is one of the :class:`Button`, ``pressed`` is whether the button was + pressed and ``injected`` whether the event was injected and thus not + generated by an actual input device. + + If this callback raises :class:`StopException` or returns ``False``, + the listener is stopped. + + Please note that not all backends support ``injected`` and will always + set it to ``False``. + + :param callable on_scroll: The callback to call when mouse scroll + events occur. + + It will be called with the arguments ``(x, y, dx, dy, injected)``, + where ``(x, y)`` is the new pointer position, and ``(dx, dy)`` is the + scroll vector and ``injected`` whether the event was injected and thus + not generated by an actual input device. + + If this callback raises :class:`StopException` or returns ``False``, + the listener is stopped. + + Please note that not all backends support ``injected`` and will always + set it to ``False``. + + :param bool suppress: Whether to suppress events. Setting this to ``True`` + will prevent the input events from being passed to the rest of the + system. + + :param kwargs: Any non-standard platform dependent options. These should be + prefixed with the platform name thus: ``darwin_``, ``xorg_`` or + ``win32_``. + + Supported values are: + + ``darwin_intercept`` + A callable taking the arguments ``(event_type, event)``, where + ``event_type`` is any mouse related event type constant, and + ``event`` is a ``CGEventRef``. + + This callable can freely modify the event using functions like + ``Quartz.CGEventSetIntegerValueField``. If this callable does not + return the event, the event is suppressed system wide. + + ``win32_event_filter`` + A callable taking the arguments ``(msg, data)``, where ``msg`` is + the current message, and ``data`` associated data as a + `MSLLHOOKSTRUCT `_. + + If this callback returns ``False``, the event will not + be propagated to the listener callback. + + If ``self.suppress_event()`` is called, the event is suppressed + system wide. + """ + def __init__(self, on_move=None, on_click=None, on_scroll=None, + suppress=False, **kwargs): + self._log = _logger(self.__class__) + option_prefix = prefix(Listener, self.__class__) + self._options = { + key[len(option_prefix):]: value + for key, value in kwargs.items() + if key.startswith(option_prefix)} + super(Listener, self).__init__( + on_move=self._wrap(on_move, 3), + on_click=self._wrap(on_click, 5), + on_scroll=self._wrap(on_scroll, 5), + suppress=suppress) +# pylint: enable=W0223 diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_darwin.py b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_darwin.py new file mode 100644 index 0000000..b5dbe3c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_darwin.py @@ -0,0 +1,212 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The mouse implementation for *macOS*. +""" + +# pylint: disable=C0111 +# The documentation is extracted from the base classes + +# pylint: disable=R0903 +# We implement stubs + +import enum +import Quartz + +from AppKit import NSEvent + +from pynput._util.darwin import ( + ListenerMixin) +from . import _base + + +def _button_value(base_name, mouse_button): + """Generates the value tuple for a :class:`Button` value. + + :param str base_name: The base name for the button. This should be a string + like ``'kCGEventLeftMouse'``. + + :param int mouse_button: The mouse button ID. + + :return: a value tuple + """ + return ( + tuple( + getattr(Quartz, '%sMouse%s' % (base_name, name)) + for name in ('Down', 'Up', 'Dragged')), + mouse_button) + + +class Button(enum.Enum): + """The various buttons. + """ + unknown = None + left = _button_value('kCGEventLeft', 0) + middle = _button_value('kCGEventOther', 2) + right = _button_value('kCGEventRight', 1) + + +class Controller(_base.Controller): + #: The scroll speed + _SCROLL_SPEED = 10 + + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + self._click = None + self._drag_button = None + + def _position_get(self): + pos = NSEvent.mouseLocation() + + return pos.x, Quartz.CGDisplayPixelsHigh(0) - pos.y + + def _position_set(self, pos): + try: + (_, _, mouse_type), mouse_button = self._drag_button.value + except AttributeError: + mouse_type = Quartz.kCGEventMouseMoved + mouse_button = 0 + + Quartz.CGEventPost( + Quartz.kCGHIDEventTap, + Quartz.CGEventCreateMouseEvent( + None, + mouse_type, + pos, + mouse_button)) + + def _scroll(self, dx, dy): + dx = int(dx) + dy = int(dy) + + Quartz.CGEventPost( + Quartz.kCGHIDEventTap, + Quartz.CGEventCreateScrollWheelEvent( + None, + Quartz.kCGScrollEventUnitPixel, + 2, + dy * self._SCROLL_SPEED, + dx * self._SCROLL_SPEED)) + + def _press(self, button): + (press, _, _), mouse_button = button.value + event = Quartz.CGEventCreateMouseEvent( + None, + press, + self.position, + mouse_button) + + # If we are performing a click, we need to set this state flag + if self._click is not None: + self._click += 1 + Quartz.CGEventSetIntegerValueField( + event, + Quartz.kCGMouseEventClickState, + self._click) + + Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) + + # Store the button to enable dragging + self._drag_button = button + + def _release(self, button): + (_, release, _), mouse_button = button.value + event = Quartz.CGEventCreateMouseEvent( + None, + release, + self.position, + mouse_button) + + # If we are performing a click, we need to set this state flag + if self._click is not None: + Quartz.CGEventSetIntegerValueField( + event, + Quartz.kCGMouseEventClickState, + self._click) + + Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) + + if button == self._drag_button: + self._drag_button = None + + def __enter__(self): + self._click = 0 + return self + + def __exit__(self, exc_type, value, traceback): + self._click = None + + +class Listener(ListenerMixin, _base.Listener): + #: The events that we listen to + _EVENTS = ( + Quartz.CGEventMaskBit(Quartz.kCGEventMouseMoved) | + Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDown) | + Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseUp) | + Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDragged) | + Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseDown) | + Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseUp) | + Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseDragged) | + Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseDown) | + Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseUp) | + Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseDragged) | + Quartz.CGEventMaskBit(Quartz.kCGEventScrollWheel)) + + def __init__(self, *args, **kwargs): + super(Listener, self).__init__(*args, **kwargs) + self._intercept = self._options.get( + 'intercept', + None) + + def _handle_message(self, _proxy, event_type, event, _refcon, injected): + """The callback registered with *macOS* for mouse events. + + This method will call the callbacks registered on initialisation. + """ + try: + (px, py) = Quartz.CGEventGetLocation(event) + except AttributeError: + # This happens during teardown of the virtual machine + return + + # Quickly detect the most common event type + if event_type == Quartz.kCGEventMouseMoved: + self.on_move(px, py, injected) + + elif event_type == Quartz.kCGEventScrollWheel: + dx = Quartz.CGEventGetIntegerValueField( + event, + Quartz.kCGScrollWheelEventDeltaAxis2) + dy = Quartz.CGEventGetIntegerValueField( + event, + Quartz.kCGScrollWheelEventDeltaAxis1) + self.on_scroll(px, py, dx, dy, injected) + + else: + for button in Button: + try: + (press, release, drag), _ = button.value + except TypeError: + # Button.unknown cannot be enumerated + continue + + # Press and release generate click events, and drag + # generates move events + if event_type in (press, release): + self.on_click(px, py, button, event_type == press, injected) + elif event_type == drag: + self.on_move(px, py, injected) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_dummy.py b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_dummy.py new file mode 100644 index 0000000..c0a8a74 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_dummy.py @@ -0,0 +1,22 @@ +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +This module contains a dummy implementation. + +It cannot be used, but importing it will not raise any exceptions. +""" + +from ._base import Button, Controller, Listener diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_win32.py b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_win32.py new file mode 100644 index 0000000..1c0dbb5 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_win32.py @@ -0,0 +1,226 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The mouse implementation for *Windows*. +""" + +# pylint: disable=C0111 +# The documentation is extracted from the base classes + +# pylint: disable=R0903 +# We implement stubs + +import ctypes +import enum + +from ctypes import ( + windll, + wintypes) + +from pynput._util import NotifierMixin +from pynput._util.win32 import ( + INPUT, + INPUT_union, + ListenerMixin, + MOUSEINPUT, + SendInput, + SystemHook) +from . import _base + +#: A constant used as a factor when constructing mouse scroll data. +WHEEL_DELTA = 120 + + +class Button(enum.Enum): + """The various buttons. + """ + unknown = None + left = (MOUSEINPUT.LEFTUP, MOUSEINPUT.LEFTDOWN, 0) + middle = (MOUSEINPUT.MIDDLEUP, MOUSEINPUT.MIDDLEDOWN, 0) + right = (MOUSEINPUT.RIGHTUP, MOUSEINPUT.RIGHTDOWN, 0) + x1 = (MOUSEINPUT.XUP, MOUSEINPUT.XDOWN, MOUSEINPUT.XBUTTON1) + x2 = (MOUSEINPUT.XUP, MOUSEINPUT.XDOWN, MOUSEINPUT.XBUTTON2) + + +class Controller(NotifierMixin, _base.Controller): + __GetCursorPos = windll.user32.GetCursorPos + __SetCursorPos = windll.user32.SetCursorPos + + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + + def _position_get(self): + point = wintypes.POINT() + if self.__GetCursorPos(ctypes.byref(point)): + return (point.x, point.y) + else: + return None + + def _position_set(self, pos): + pos = int(pos[0]), int(pos[1]) + self.__SetCursorPos(*pos) + self._emit('on_move', *pos, True) + + def _scroll(self, dx, dy): + if dy: + SendInput( + 1, + ctypes.byref(INPUT( + type=INPUT.MOUSE, + value=INPUT_union( + mi=MOUSEINPUT( + dwFlags=MOUSEINPUT.WHEEL, + mouseData=int(dy * WHEEL_DELTA))))), + ctypes.sizeof(INPUT)) + + if dx: + SendInput( + 1, + ctypes.byref(INPUT( + type=INPUT.MOUSE, + value=INPUT_union( + mi=MOUSEINPUT( + dwFlags=MOUSEINPUT.HWHEEL, + mouseData=int(dx * WHEEL_DELTA))))), + ctypes.sizeof(INPUT)) + + if dx or dy: + px, py = self._position_get() + self._emit('on_scroll', px, py, dx, dy, True) + + def _press(self, button): + SendInput( + 1, + ctypes.byref(INPUT( + type=INPUT.MOUSE, + value=INPUT_union( + mi=MOUSEINPUT( + dwFlags=button.value[1], + mouseData=button.value[2])))), + ctypes.sizeof(INPUT)) + + def _release(self, button): + SendInput( + 1, + ctypes.byref(INPUT( + type=INPUT.MOUSE, + value=INPUT_union( + mi=MOUSEINPUT( + dwFlags=button.value[0], + mouseData=button.value[2])))), + ctypes.sizeof(INPUT)) + + +@Controller._receiver +class Listener(ListenerMixin, _base.Listener): + #: The Windows hook ID for low level mouse events, ``WH_MOUSE_LL`` + _EVENTS = 14 + + WM_LBUTTONDOWN = 0x0201 + WM_LBUTTONUP = 0x0202 + WM_MBUTTONDOWN = 0x0207 + WM_MBUTTONUP = 0x0208 + WM_MOUSEMOVE = 0x0200 + WM_MOUSEWHEEL = 0x020A + WM_MOUSEHWHEEL = 0x020E + WM_RBUTTONDOWN = 0x0204 + WM_RBUTTONUP = 0x0205 + WM_XBUTTONDOWN = 0x20B + WM_XBUTTONUP = 0x20C + + MK_XBUTTON1 = 0x0020 + MK_XBUTTON2 = 0x0040 + + XBUTTON1 = 1 + XBUTTON2 = 2 + + #: A mapping from messages to button events + CLICK_BUTTONS = { + WM_LBUTTONDOWN: (Button.left, True), + WM_LBUTTONUP: (Button.left, False), + WM_MBUTTONDOWN: (Button.middle, True), + WM_MBUTTONUP: (Button.middle, False), + WM_RBUTTONDOWN: (Button.right, True), + WM_RBUTTONUP: (Button.right, False)} + + #: A mapping from message to X button events. + X_BUTTONS = { + WM_XBUTTONDOWN: { + XBUTTON1: (Button.x1, True), + XBUTTON2: (Button.x2, True)}, + WM_XBUTTONUP: { + XBUTTON1: (Button.x1, False), + XBUTTON2: (Button.x2, False)}} + + #: A mapping from messages to scroll vectors + SCROLL_BUTTONS = { + WM_MOUSEWHEEL: (0, 1), + WM_MOUSEHWHEEL: (1, 0)} + + _HANDLED_EXCEPTIONS = ( + SystemHook.SuppressException,) + + class _MSLLHOOKSTRUCT(ctypes.Structure): + """Contains information about a mouse event passed to a ``WH_MOUSE_LL`` + hook procedure, ``MouseProc``. + """ + LLMHF_INJECTED = 0x00000001 + LLMHF_LOWER_IL_INJECTED = 0x00000002 + _fields_ = [ + ('pt', wintypes.POINT), + ('mouseData', wintypes.DWORD), + ('flags', wintypes.DWORD), + ('time', wintypes.DWORD), + ('dwExtraInfo', ctypes.c_void_p)] + + #: A pointer to a :class:`_MSLLHOOKSTRUCT` + _LPMSLLHOOKSTRUCT = ctypes.POINTER(_MSLLHOOKSTRUCT) + + def __init__(self, *args, **kwargs): + super(Listener, self).__init__(*args, **kwargs) + self._event_filter = self._options.get( + 'event_filter', + lambda msg, data: True) + + def _handle_message(self, code, msg, lpdata): + if code != SystemHook.HC_ACTION: + return + + data = ctypes.cast(lpdata, self._LPMSLLHOOKSTRUCT).contents + injected = data.flags & (0 + | self._MSLLHOOKSTRUCT.LLMHF_INJECTED + | self._MSLLHOOKSTRUCT.LLMHF_LOWER_IL_INJECTED) != 0 + + # Suppress further propagation of the event if it is filtered + if self._event_filter(msg, data) is False: + return + + if msg == self.WM_MOUSEMOVE: + self.on_move(data.pt.x, data.pt.y,injected) + + elif msg in self.CLICK_BUTTONS: + button, pressed = self.CLICK_BUTTONS[msg] + self.on_click(data.pt.x, data.pt.y, button, pressed, injected) + + elif msg in self.X_BUTTONS: + button, pressed = self.X_BUTTONS[msg][data.mouseData >> 16] + self.on_click(data.pt.x, data.pt.y, button, pressed, injected) + + elif msg in self.SCROLL_BUTTONS: + mx, my = self.SCROLL_BUTTONS[msg] + dd = wintypes.SHORT(data.mouseData >> 16).value // WHEEL_DELTA + self.on_scroll(data.pt.x, data.pt.y, dd * mx, dd * my, injected) diff --git a/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_xorg.py b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_xorg.py new file mode 100644 index 0000000..93b0a98 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/pynput/mouse/_xorg.py @@ -0,0 +1,184 @@ +# coding=utf-8 +# pynput +# Copyright (C) 2015-2024 Moses Palmér +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +""" +The keyboard implementation for *Xorg*. +""" + +# pylint: disable=C0111 +# The documentation is extracted from the base classes + + +# pylint: disable=E1101,E1102 +# We dynamically generate the Button class + +# pylint: disable=R0903 +# We implement stubs + +# pylint: disable=W0611 +try: + import pynput._util.xorg +except Exception as e: + raise ImportError('failed to acquire X connection: {}'.format(str(e)), e) +# pylint: enable=W0611 + +import enum +import Xlib.display +import Xlib.ext +import Xlib.ext.xtest +import Xlib.X +import Xlib.protocol + +from pynput._util.xorg import ( + display_manager, + ListenerMixin) +from . import _base + + +# pylint: disable=C0103 +Button = enum.Enum( + 'Button', + module=__name__, + names=[ + ('unknown', None), + ('left', 1), + ('middle', 2), + ('right', 3), + ('scroll_up', 4), + ('scroll_down', 5), + ('scroll_left', 6), + ('scroll_right', 7)] + [ + ('button%d' % i, i) + for i in range(8, 31)]) +# pylint: enable=C0103 + + +class Controller(_base.Controller): + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + self._display = Xlib.display.Display() + + def __del__(self): + if hasattr(self, '_display'): + self._display.close() + + def _position_get(self): + with display_manager(self._display) as dm: + qp = dm.screen().root.query_pointer() + return (qp.root_x, qp.root_y) + + def _position_set(self, pos): + px, py = self._check_bounds(*pos) + with display_manager(self._display) as dm: + Xlib.ext.xtest.fake_input(dm, Xlib.X.MotionNotify, x=px, y=py) + + def _scroll(self, dx, dy): + dx, dy = self._check_bounds(dx, dy) + if dy: + self.click( + button=Button.scroll_up if dy > 0 else Button.scroll_down, + count=abs(dy)) + + if dx: + self.click( + button=Button.scroll_right if dx > 0 else Button.scroll_left, + count=abs(dx)) + + def _press(self, button): + with display_manager(self._display) as dm: + Xlib.ext.xtest.fake_input(dm, Xlib.X.ButtonPress, button.value) + + def _release(self, button): + with display_manager(self._display) as dm: + Xlib.ext.xtest.fake_input(dm, Xlib.X.ButtonRelease, button.value) + + def _check_bounds(self, *args): + """Checks the arguments and makes sure they are within the bounds of a + short integer. + + :param args: The values to verify. + """ + if not all( + (-0x7fff - 1) <= number <= 0x7fff + for number in args): + raise ValueError(args) + else: + return tuple(int(p) for p in args) + + +class Listener(ListenerMixin, _base.Listener): + #: A mapping from button values to scroll directions + _SCROLL_BUTTONS = { + Button.scroll_up.value: (0, 1), + Button.scroll_down.value: (0, -1), + Button.scroll_right.value: (1, 0), + Button.scroll_left.value: (-1, 0)} + + _EVENTS = ( + Xlib.X.ButtonPressMask, + Xlib.X.ButtonReleaseMask) + + def __init__(self, *args, **kwargs): + super(Listener, self).__init__(*args, **kwargs) + + def _handle_message(self, dummy_display, event, injected): + px = event.root_x + py = event.root_y + + if event.type == Xlib.X.ButtonPress: + # Scroll events are sent as button presses with the scroll + # button codes + scroll = self._SCROLL_BUTTONS.get(event.detail, None) + if scroll: + self.on_scroll( + px, py, scroll[0], scroll[1], injected) + else: + self.on_click( + px, py, self._button(event.detail), True, injected) + + elif event.type == Xlib.X.ButtonRelease: + # Send an event only if this was not a scroll event + if event.detail not in self._SCROLL_BUTTONS: + self.on_click( + px, py, self._button(event.detail), False, injected) + + else: + self.on_move(px, py, injected) + + + def _suppress_start(self, display): + display.screen().root.grab_pointer( + True, self._event_mask, Xlib.X.GrabModeAsync, Xlib.X.GrabModeAsync, + 0, 0, Xlib.X.CurrentTime) + + def _suppress_stop(self, display): + display.ungrab_pointer(Xlib.X.CurrentTime) + + # pylint: disable=R0201 + def _button(self, detail): + """Creates a mouse button from an event detail. + + If the button is unknown, :attr:`Button.unknown` is returned. + + :param detail: The event detail. + + :return: a button + """ + try: + return Button(detail) + except ValueError: + return Button.unknown + # pylint: enable=R0201 diff --git a/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/INSTALLER b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/LICENSE b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/LICENSE new file mode 100644 index 0000000..20b7285 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random + Hacker. + + {signature of Ty Coon}, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/METADATA b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/METADATA new file mode 100644 index 0000000..1521f50 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/METADATA @@ -0,0 +1,158 @@ +Metadata-Version: 2.1 +Name: python-xlib +Version: 0.33 +Summary: Python X Library +Home-page: https://github.com/python-xlib/python-xlib +Author: Peter Liljenberg +Author-email: petli@ctrl-c.liu.se +License: LGPLv2+ +Download-URL: https://github.com/python-xlib/python-xlib/releases +Keywords: windows,x,x11,xlib +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: X11 Applications +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Software Development :: User Interfaces +Requires-Dist: six (>=1.10.0) + +The Python X Library +==================== + +|Build Status| |codecov.io| |Code Health| + +`Homepage`_ | `Releases`_ | `Changelog`_ + +Copyright +~~~~~~~~~ + +The main part of the code is + +:: + + Copyright (C) 2000-2002 Peter Liljenberg + +Some contributed code is copyrighted by `the contributors `_, +in these cases that is indicated in the source files in question. + +The Python X Library is released under LGPL v2.1 or later (since 2016), +see the file LICENSE for details. 0.15rc1 and before were released under +GPL v2. + +Requirements +~~~~~~~~~~~~ + +The Python X Library requires Python 2.7 or newer. It has been tested to +various extents with Python 2.7 and 3.3 through 3.6. + +The Python X Library will only work on systems that have an X server installed, +such as most Linux distros, but will not work on Windows or MacOS. + +Installation +~~~~~~~~~~~~ + +The Python Xlib uses the standard setuptools package, to install run +this command: + +:: + + python setup.py install + +See the command help for details: ``python setup.py install -h``. + +Alternatively, you can run programs from the distribution directory, or +change the module path in programs. + +There's a simple example program, implemented twice using both the +high-level interface and the low-level protocol. + +Introduction +~~~~~~~~~~~~ + +The Python X Library is intended to be a fully functional X client +library for Python programs. It is written entirely in Python, in +contrast to earlier X libraries for Python (the ancient X extension and +the newer plxlib) which were interfaces to the C Xlib. + +This is possible to do since X client programs communicate with the X +server via the X protocol. The communication takes place over TCP/IP, +Unix sockets, DECnet or any other streaming network protocol. The C Xlib +is merely an interface to this protocol, providing functions suitable +for a C environment. + +There are three advantages of implementing a pure Python library: + +- Integration: The library can make use of the wonderful object system + in Python, providing an easy-to-use class hierarchy. + +- Portability: The library will be usable on (almost) any computer + which have Python installed. A C interface could be problematic to + port to non-Unix systems, such as MS Windows or OpenVMS. + +- Maintainability: It is much easier to develop and debug native Python + modules than modules written in C. + +Documentation +~~~~~~~~~~~~~ + +The reference manual is not finished by far, but is probably still useful. It +can be `browsed online `__. + +There are also some `example programs `_ and, of course, +`the standard X11 documentation `__ applies. + + +Project status +~~~~~~~~~~~~~~ + +The low-level protocol is complete, implementing client-side X11R6. The +high-level object oriented interface is also fully functional. It is +possible to write client applications with the library. Currently, the +only real application using Python Xlib is the window manager PLWM, +starting with version 2.0. + +There is a resource database implementation, ICCCM support and a +framework for adding X extension code. Several extensions have been +implemented (RECORD, SHAPE, Xinerama, Composite, RANDR, DAMAGE, +Generic Event, SECURITY, XFIXES, XInput, XTEST, NV-CONTROL, DPMS and XRes); +patches for additions are very welcome. + +There are most likely still bugs, but the library is at least stable +enough to run PLWM. A continuously bigger part of the library is covered +by regression tests, improving stability. + +The documentation is still quite rudimentary, but should be of some help +for people programming with the Xlib. X beginners should first find some +general texts on X. A very good starting point is +http://www.rahul.net/kenton/xsites.html + +See the file TODO for a detailed list of what is missing, approximately +ordered by importance. + +.. _Homepage: https://github.com/python-xlib/python-xlib +.. _Releases: https://github.com/python-xlib/python-xlib/releases +.. _Changelog: https://github.com/python-xlib/python-xlib/tree/master/CHANGELOG.md +.. _Contributors: https://github.com/python-xlib/python-xlib/graphs/contributors +.. _Examples: https://github.com/python-xlib/python-xlib/tree/master/examples + +.. |Build Status| image:: https://travis-ci.org/python-xlib/python-xlib.svg?branch=master + :target: https://travis-ci.org/python-xlib/python-xlib +.. |codecov.io| image:: https://codecov.io/github/python-xlib/python-xlib/coverage.svg?branch=master + :target: https://codecov.io/github/python-xlib/python-xlib?branch=master +.. |Code Health| image:: https://landscape.io/github/python-xlib/python-xlib/master/landscape.svg?style=flat + :target: https://landscape.io/github/python-xlib/python-xlib/master + + diff --git a/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/RECORD b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/RECORD new file mode 100644 index 0000000..519ddae --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/RECORD @@ -0,0 +1,136 @@ +Xlib/X.py,sha256=hKIUvoQzliEgTA8CXcfhWDEvxKmY6CvhtBOsaAQjHAs,10687 +Xlib/XK.py,sha256=1kme6XPruQ5X-_rl6t76oTUOfjXNw7vGDZ5XXIlarVs,3299 +Xlib/Xatom.py,sha256=VRI0u8KV-L-DSuUHSexoFh8EBb0In2A_krkomOYCtoA,2047 +Xlib/Xcursorfont.py,sha256=n-AMIqTBZhuNVSlU4FF79e7pgwYW_nX9qQ4JFjzfVrw,2128 +Xlib/Xutil.py,sha256=65DIrIENhiSz_Vfuo12Hf7dBWJNKjtW9wdBXu4fwcsk,2298 +Xlib/__init__.py,sha256=9YXlGXmObCiLlfRLRA4U2HsaMgpptWf1YyLsc3mCOLg,1223 +Xlib/__pycache__/X.cpython-312.pyc,, +Xlib/__pycache__/XK.cpython-312.pyc,, +Xlib/__pycache__/Xatom.cpython-312.pyc,, +Xlib/__pycache__/Xcursorfont.cpython-312.pyc,, +Xlib/__pycache__/Xutil.cpython-312.pyc,, +Xlib/__pycache__/__init__.cpython-312.pyc,, +Xlib/__pycache__/display.cpython-312.pyc,, +Xlib/__pycache__/error.cpython-312.pyc,, +Xlib/__pycache__/rdb.cpython-312.pyc,, +Xlib/__pycache__/threaded.cpython-312.pyc,, +Xlib/__pycache__/xauth.cpython-312.pyc,, +Xlib/display.py,sha256=Nighif4Hj5pncOZ9U_dMi5Ij-VZ-etqkDbmV9vR2DUs,38048 +Xlib/error.py,sha256=i0lByUYdgXfvuisx-2hqjec2_O3jwanqklzOhOCZ_Ms,4911 +Xlib/ext/__init__.py,sha256=mIuX-L5zxbgGjgdnNldxEtOMG76O1zWkExwQq7jDx4U,1679 +Xlib/ext/__pycache__/__init__.cpython-312.pyc,, +Xlib/ext/__pycache__/composite.cpython-312.pyc,, +Xlib/ext/__pycache__/damage.cpython-312.pyc,, +Xlib/ext/__pycache__/dpms.cpython-312.pyc,, +Xlib/ext/__pycache__/ge.cpython-312.pyc,, +Xlib/ext/__pycache__/nvcontrol.cpython-312.pyc,, +Xlib/ext/__pycache__/randr.cpython-312.pyc,, +Xlib/ext/__pycache__/record.cpython-312.pyc,, +Xlib/ext/__pycache__/res.cpython-312.pyc,, +Xlib/ext/__pycache__/screensaver.cpython-312.pyc,, +Xlib/ext/__pycache__/security.cpython-312.pyc,, +Xlib/ext/__pycache__/shape.cpython-312.pyc,, +Xlib/ext/__pycache__/xfixes.cpython-312.pyc,, +Xlib/ext/__pycache__/xinerama.cpython-312.pyc,, +Xlib/ext/__pycache__/xinput.cpython-312.pyc,, +Xlib/ext/__pycache__/xtest.cpython-312.pyc,, +Xlib/ext/composite.py,sha256=s1mbl2gtc5nrgI_yhOW_0Y7St8TAUcUesZT62huYqUs,8861 +Xlib/ext/damage.py,sha256=bLq-S6izGvcHm9sl3Bkb1MuQINDC0DNZWT2AQov5Fm4,5898 +Xlib/ext/dpms.py,sha256=oSTu-B1Sk0VRFSJUyUNm4Tdra4DiPND2MCGnddI-gvg,6948 +Xlib/ext/ge.py,sha256=_8mYdzZyaJAeTV5LKxtZQSO-1AHzhOJqqmzRcrWmzWA,3481 +Xlib/ext/nvcontrol.py,sha256=uyhYMr2JsGEb-1v4dNDA63LGEqL9Ck9wq-al-mux7Us,191917 +Xlib/ext/randr.py,sha256=HM1dCEwUQ1aXtVSpRDAvT4dAzFTx_POxGZJd36KF_T0,38563 +Xlib/ext/record.py,sha256=7qR9VR6kNKNR_co0ltGHk7iKOQW75L5nyNq6DnABGPQ,9664 +Xlib/ext/res.py,sha256=NGTIbq_IZk_Xa0Ow6AchuJdP6oogOFJHWyafCl5HCpQ,9244 +Xlib/ext/screensaver.py,sha256=A-7IdrmPY5Wj-zm6P-DnTk7oix9C0BrnR7KPyexjxJs,6451 +Xlib/ext/security.py,sha256=kdyWhdyd5Kg8RJhr7RaAvlE7Ml-0sFwBWqvKZ7QzW2g,5180 +Xlib/ext/shape.py,sha256=4XhB7wZbdBrtVUbW1NpTp49uJRtF-txwd-jMpW5ESbE,8147 +Xlib/ext/xfixes.py,sha256=DnXGk3RNGqRwgRC0Rr41T8-vT6URmm3iJ5eR-3Nmgeo,7673 +Xlib/ext/xinerama.py,sha256=qf2D7mGOCCN7TXhW6mCIIZm25MiqkT29xBudIxc6yGU,7134 +Xlib/ext/xinput.py,sha256=8P2ELKK0w92QVV6SFXi-yiYyHVfG50asFA0NnNP6cQY,21369 +Xlib/ext/xtest.py,sha256=dr-mSbd6Pd4Z8eWe506BonkuMqkd2KzZr-_EwUzwhhE,4686 +Xlib/keysymdef/__init__.py,sha256=v6-37-D4AOWUFMVoV5qaGYLJ2PGsZuca61cgp9ZLCPY,1171 +Xlib/keysymdef/__pycache__/__init__.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/apl.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/arabic.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/cyrillic.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/greek.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/hebrew.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/katakana.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/korean.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/latin1.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/latin2.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/latin3.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/latin4.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/miscellany.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/publishing.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/special.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/technical.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/thai.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/xf86.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/xk3270.cpython-312.pyc,, +Xlib/keysymdef/__pycache__/xkb.cpython-312.pyc,, +Xlib/keysymdef/apl.py,sha256=YnXHuO_cuiskmvzmJVvAavqu9rzkln1cqhT2e4GaPdA,388 +Xlib/keysymdef/arabic.py,sha256=BvtYlu66CnM0_TtmGqQ-2oyEgcljocRwRqnLyZpSusw,1271 +Xlib/keysymdef/cyrillic.py,sha256=d0jbvIq5khW9_jXTymLfOjeyuntlArr2nFhnBe69Us8,2647 +Xlib/keysymdef/greek.py,sha256=8MMrtk3omP6yVOMENTOR6GfU9dDiE9H8nXAr5tqaVW4,1914 +Xlib/keysymdef/hebrew.py,sha256=6ZCcrJ_NPykfq2icxmtc0mDn9Yy7VfSM0qTgkokRjVs,997 +Xlib/keysymdef/katakana.py,sha256=O3Tii7VAwKlbPKKGbbH1p3JsYe6YqXyX5TlKi85TTWw,1467 +Xlib/keysymdef/korean.py,sha256=cmkjs9BDOH64v6j-ThpWLlHhLc3nqs5PoVJ82JoEGlY,2967 +Xlib/keysymdef/latin1.py,sha256=tdsB2tt4A4IGlHqVyl9vbX61Hg8v5KSvTPwhRnE8CmY,3621 +Xlib/keysymdef/latin2.py,sha256=byugoPe9yk3rm3-Xn_vh05AYwsRo_VNIWMX69b4cDDw,1132 +Xlib/keysymdef/latin3.py,sha256=dAbFBTKV4UdKVA_XQEmJygjMR_j08uL7twEJAMsIJuM,487 +Xlib/keysymdef/latin4.py,sha256=c7UOJkBlSX7Uq4I3oXSBS5jZ3Ae7xyVEyk5XvafcV1U,714 +Xlib/keysymdef/miscellany.py,sha256=9J6QpQaCWHFEqzymFXQ8cjqiv-egvp22U2hW2GjKtZo,3302 +Xlib/keysymdef/publishing.py,sha256=NbJoa_50kpVIq3FcKt2dX-mqCWf7HB7xasJsAh2TUgM,2060 +Xlib/keysymdef/special.py,sha256=FzeeTfs8p9GAmALjjnCREa3jxLZGaLu83rnRMKLBpJE,514 +Xlib/keysymdef/technical.py,sha256=qLOeqtfRJc5T8TkU079fiMz5WlrCtcw2GAFJ8xIyvaY,1252 +Xlib/keysymdef/thai.py,sha256=BpbxEZRUb2Z3mKONqUzOf1EDjRizSFTJMeCFrsKEKhw,2088 +Xlib/keysymdef/xf86.py,sha256=nuHUmUggywSlTDH842p-983vC_wJ8OKkCYzD0jTozro,7051 +Xlib/keysymdef/xk3270.py,sha256=qBs78MPixilvU33hsTU9IWcCSwCqYZM5hK2xWJewsQA,768 +Xlib/keysymdef/xkb.py,sha256=QXj1RlwNMHhDnlQYfmnKwkdQqPx4M123AyvMuYLGEnc,3022 +Xlib/protocol/__init__.py,sha256=ofD15n8WA_iSRWhs3riBFES_YH4_3MrgP7tBOyqjHv8,979 +Xlib/protocol/__pycache__/__init__.cpython-312.pyc,, +Xlib/protocol/__pycache__/display.cpython-312.pyc,, +Xlib/protocol/__pycache__/event.cpython-312.pyc,, +Xlib/protocol/__pycache__/request.cpython-312.pyc,, +Xlib/protocol/__pycache__/rq.cpython-312.pyc,, +Xlib/protocol/__pycache__/structs.cpython-312.pyc,, +Xlib/protocol/display.py,sha256=vb1QPx9SPNoSRL6tHCDFpL_oJmaeHh7kH9HzyNMr2xM,37415 +Xlib/protocol/event.py,sha256=lSPPv-PTtNY1ygTlQUcD7JR75uehTce4jwrPlSrM2d4,15816 +Xlib/protocol/request.py,sha256=47OcW2F4Aakvwce_g4tkwyrPE0F1T9QYCxZdpvMIzgg,49468 +Xlib/protocol/rq.py,sha256=UNwDN6GM6mfI9d6YJ8h-Iw19A35d44aH_E_wU2WrT1E,45036 +Xlib/protocol/structs.py,sha256=V0xfHOEB_ZY75DPEzEFD7zOD2285yFIbjDYUp2BQdTY,5489 +Xlib/rdb.py,sha256=WjT8Kem-WXqXPv1oHz0D6lVAnpu_MsB_xxF4Fo9tuks,20673 +Xlib/support/__init__.py,sha256=xPe4wHamik3vA3qopzosJSTLaqf9joOzlBmIVv0SZQM,986 +Xlib/support/__pycache__/__init__.cpython-312.pyc,, +Xlib/support/__pycache__/connect.cpython-312.pyc,, +Xlib/support/__pycache__/lock.cpython-312.pyc,, +Xlib/support/__pycache__/unix_connect.cpython-312.pyc,, +Xlib/support/__pycache__/vms_connect.cpython-312.pyc,, +Xlib/support/connect.py,sha256=AX5KJNiCCYtBjsgNwN6ZzIF-sDTAtDAcuUdbdJYq-zE,3194 +Xlib/support/lock.py,sha256=VGzvzPJUS-dt_WwWI4sZqdMTMRucRQ__ttHZGnOeM_Y,1591 +Xlib/support/unix_connect.py,sha256=NTomjognC9rAfphiQqXUiUe6gb03cTJZwzGb4c_yM5c,7357 +Xlib/support/vms_connect.py,sha256=go5lxSTjjpHh2fSi-ys8j3Z-VHRKTkRuQk80TYQzoWY,2161 +Xlib/threaded.py,sha256=D5gC7xcYJ6Khr5OKcMZdeWnD9d2hBNR13lRgWiJFwV4,1124 +Xlib/xauth.py,sha256=OoHZIaJMcTP1VJ3h2j2ryh-LIOqNOp5Wc6jE3eYl0uI,4483 +Xlib/xobject/__init__.py,sha256=klyPCdKFavDcq4Lr9-Hhrnforg38Hs8C4ZBWFjmD9hM,1001 +Xlib/xobject/__pycache__/__init__.cpython-312.pyc,, +Xlib/xobject/__pycache__/colormap.cpython-312.pyc,, +Xlib/xobject/__pycache__/cursor.cpython-312.pyc,, +Xlib/xobject/__pycache__/drawable.cpython-312.pyc,, +Xlib/xobject/__pycache__/fontable.cpython-312.pyc,, +Xlib/xobject/__pycache__/icccm.cpython-312.pyc,, +Xlib/xobject/__pycache__/resource.cpython-312.pyc,, +Xlib/xobject/colormap.py,sha256=tuOdt5pImB_rD428kp63nsDWeX-5HuN1S4UGmMGIMUA,5866 +Xlib/xobject/cursor.py,sha256=WF8-ssyDdbej5qU6NlrRAFkYr-GYQbvHTi6gomlWcL4,1896 +Xlib/xobject/drawable.py,sha256=3rBrHPl-fbZq_Oz2Ibo3U4pFk-19QQawojKivfwoErQ,35256 +Xlib/xobject/fontable.py,sha256=54w1rMYIkacTev8_Cw-effrnUI2WAziu9Qj5EI_J4DY,4349 +Xlib/xobject/icccm.py,sha256=RozK-gRBsTiTbHTMVbufNdZbpfAk2UtCZnislFGZ__U,3441 +Xlib/xobject/resource.py,sha256=ciFnK_zPttUbmDktJJIUFDte0Jev6PcS5KSseWOjkAc,1791 +python_xlib-0.33.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +python_xlib-0.33.dist-info/LICENSE,sha256=O7b2vslLmeKSeoiAv0nEAfXo9Iog3eqWMQhgJkyuILA,26965 +python_xlib-0.33.dist-info/METADATA,sha256=4YBseoNGoVlht9F-9eAxN9e5OLRnE5x6yDKqRNn3r5k,6249 +python_xlib-0.33.dist-info/RECORD,, +python_xlib-0.33.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110 +python_xlib-0.33.dist-info/top_level.txt,sha256=KYaqxIvc7od8tCuJgS1v_nr9T4OjWVfsI4lGa38I5uU,5 diff --git a/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/WHEEL b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/WHEEL new file mode 100644 index 0000000..0b18a28 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/top_level.txt b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/top_level.txt new file mode 100644 index 0000000..7997334 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/python_xlib-0.33.dist-info/top_level.txt @@ -0,0 +1 @@ +Xlib diff --git a/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/INSTALLER b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/LICENSE b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/LICENSE new file mode 100644 index 0000000..1cc22a5 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2010-2024 Benjamin Peterson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA new file mode 100644 index 0000000..cfde03c --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA @@ -0,0 +1,43 @@ +Metadata-Version: 2.1 +Name: six +Version: 1.17.0 +Summary: Python 2 and 3 compatibility utilities +Home-page: https://github.com/benjaminp/six +Author: Benjamin Peterson +Author-email: benjamin@python.org +License: MIT +Classifier: Development Status :: 5 - Production/Stable +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Utilities +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.* +License-File: LICENSE + +.. image:: https://img.shields.io/pypi/v/six.svg + :target: https://pypi.org/project/six/ + :alt: six on PyPI + +.. image:: https://readthedocs.org/projects/six/badge/?version=latest + :target: https://six.readthedocs.io/ + :alt: six's documentation on Read the Docs + +.. image:: https://img.shields.io/badge/license-MIT-green.svg + :target: https://github.com/benjaminp/six/blob/master/LICENSE + :alt: MIT License badge + +Six is a Python 2 and 3 compatibility library. It provides utility functions +for smoothing over the differences between the Python versions with the goal of +writing Python code that is compatible on both Python versions. See the +documentation for more information on what is provided. + +Six supports Python 2.7 and 3.3+. It is contained in only one Python +file, so it can be easily copied into your project. (The copyright and license +notice must be retained.) + +Online documentation is at https://six.readthedocs.io/. + +Bugs can be reported to https://github.com/benjaminp/six. The code can also +be found there. diff --git a/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/RECORD b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/RECORD new file mode 100644 index 0000000..bb90c1a --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/RECORD @@ -0,0 +1,8 @@ +__pycache__/six.cpython-312.pyc,, +six-1.17.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +six-1.17.0.dist-info/LICENSE,sha256=Q3W6IOK5xsTnytKUCmKP2Q6VzD1Q7pKq51VxXYuh-9A,1066 +six-1.17.0.dist-info/METADATA,sha256=ViBCB4wnUlSfbYp8htvF3XCAiKe-bYBnLsewcQC3JGg,1658 +six-1.17.0.dist-info/RECORD,, +six-1.17.0.dist-info/WHEEL,sha256=pxeNX5JdtCe58PUSYP9upmc7jdRPgvT0Gm9kb1SHlVw,109 +six-1.17.0.dist-info/top_level.txt,sha256=_iVH_iYEtEXnD8nYGQYpYFUvkUW9sEO1GYbkeKSAais,4 +six.py,sha256=xRyR9wPT1LNpbJI8tf7CE-BeddkhU5O--sfy-mo5BN8,34703 diff --git a/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/WHEEL b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/WHEEL new file mode 100644 index 0000000..104f387 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: setuptools (75.6.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/top_level.txt b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/top_level.txt new file mode 100644 index 0000000..ffe2fce --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/top_level.txt @@ -0,0 +1 @@ +six diff --git a/CLI/venv/lib/python3.12/site-packages/six.py b/CLI/venv/lib/python3.12/site-packages/six.py new file mode 100644 index 0000000..3de5969 --- /dev/null +++ b/CLI/venv/lib/python3.12/site-packages/six.py @@ -0,0 +1,1003 @@ +# Copyright (c) 2010-2024 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Utilities for writing code that runs on Python 2 and 3""" + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.17.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + +if PY34: + from importlib.util import spec_from_loader +else: + spec_from_loader = None + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def find_spec(self, fullname, path, target=None): + if fullname in self.known_modules: + return spec_from_loader(fullname, self) + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + + def create_module(self, spec): + return self.load_module(spec.name) + + def exec_module(self, module): + pass + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections", "IterableUserDict", "UserDict"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), +] +if sys.version_info[:2] < (3, 14): + _urllib_request_moved_attributes.extend( + [ + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + ] + ) +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + del io + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + _assertNotRegex = "assertNotRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" + _assertNotRegex = "assertNotRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + _assertNotRegex = "assertNotRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +def assertNotRegex(self, *args, **kwargs): + return getattr(self, _assertNotRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""") + + +if sys.version_info[:2] > (3,): + exec_("""def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + # This does exactly the same what the :func:`py3:functools.update_wrapper` + # function does on Python versions after 3.2. It sets the ``__wrapped__`` + # attribute on ``wrapper`` object and it doesn't raise an error if any of + # the attributes mentioned in ``assigned`` and ``updated`` are missing on + # ``wrapped`` object. + def _update_wrapper(wrapper, wrapped, + assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + for attr in assigned: + try: + value = getattr(wrapped, attr) + except AttributeError: + continue + else: + setattr(wrapper, attr, value) + for attr in updated: + getattr(wrapper, attr).update(getattr(wrapped, attr, {})) + wrapper.__wrapped__ = wrapped + return wrapper + _update_wrapper.__doc__ = functools.update_wrapper.__doc__ + + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + return functools.partial(_update_wrapper, wrapped=wrapped, + assigned=assigned, updated=updated) + wraps.__doc__ = functools.wraps.__doc__ + +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + if sys.version_info[:2] >= (3, 7): + # This version introduced PEP 560 that requires a bit + # of extra care (we mimic what is done by __build_class__). + resolved_bases = types.resolve_bases(bases) + if resolved_bases is not bases: + d['__orig_bases__'] = bases + else: + resolved_bases = bases + return meta(name, resolved_bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + if hasattr(cls, '__qualname__'): + orig_vars['__qualname__'] = cls.__qualname__ + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def ensure_binary(s, encoding='utf-8', errors='strict'): + """Coerce **s** to six.binary_type. + + For Python 2: + - `unicode` -> encoded to `str` + - `str` -> `str` + + For Python 3: + - `str` -> encoded to `bytes` + - `bytes` -> `bytes` + """ + if isinstance(s, binary_type): + return s + if isinstance(s, text_type): + return s.encode(encoding, errors) + raise TypeError("not expecting type '%s'" % type(s)) + + +def ensure_str(s, encoding='utf-8', errors='strict'): + """Coerce *s* to `str`. + + For Python 2: + - `unicode` -> encoded to `str` + - `str` -> `str` + + For Python 3: + - `str` -> `str` + - `bytes` -> decoded to `str` + """ + # Optimization: Fast return for the common case. + if type(s) is str: + return s + if PY2 and isinstance(s, text_type): + return s.encode(encoding, errors) + elif PY3 and isinstance(s, binary_type): + return s.decode(encoding, errors) + elif not isinstance(s, (text_type, binary_type)): + raise TypeError("not expecting type '%s'" % type(s)) + return s + + +def ensure_text(s, encoding='utf-8', errors='strict'): + """Coerce *s* to six.text_type. + + For Python 2: + - `unicode` -> `unicode` + - `str` -> `unicode` + + For Python 3: + - `str` -> `str` + - `bytes` -> decoded to `str` + """ + if isinstance(s, binary_type): + return s.decode(encoding, errors) + elif isinstance(s, text_type): + return s + else: + raise TypeError("not expecting type '%s'" % type(s)) + + +def python_2_unicode_compatible(klass): + """ + A class decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer)