I've been figuring out how to parse tkinter events via event.state to reduce the number of times that I have to call root.bind() (e.g., I can avoid binding both "<ButtonPress-1>" and "<Shift-ButtonPress-1>" by finding if shift was pressed via event.state). Of course, I've relied heavily on the tkinter source code (specifically the definition for __repr__, starting on line 234) to convert the integer of event.state to something I can understand:
def getStatefromInt(state_int):
# from https://github.com/python/cpython/blob/3.8/Lib/tkinter/__init__.py
if isinstance(state_int, int):
state = state_int
mods = ('Shift', 'Lock', 'Control',
'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5',
'Button1', 'Button2', 'Button3', 'Button4', 'Button5')
s = []
for i, n in enumerate(mods):
if state & (1 << i):
s.append(n)
state = state & ~((1<< len(mods)) - 1)
if state or not s:
s.append(hex(state))
return s
One of the things that keeps coming up out of state when events occur is Mod1. What do Mod1 and the other ModX states represent? I thought the number might correspond to the type of button press, but all types of mouse clicks cause only Mod1. I have not been able to find information on what this means online, and I'm having a hard time seeing from the source code what it might mean.
ModX represents a modification, a Modifier Key.
In computing, a modifier key is a special key (or combination) on a
computer keyboard that temporarily modifies the normal action of
another key when pressed together. By themselves, modifier keys
usually do nothing; that is, pressing any of the ⇧ Shift, Alt, or Ctrl
keys alone does not (generally) trigger any action from the computer.
Tkinter is a crossplatform GUI-Toolkit and uses system specific facilities. Different OS using different methods, for example a PC that runs Linux signals Alt Gr as Mod 5 while a PC running Windows signals the same keystroke as Control-Alt. You can look at the Modifier Keys on tcl-lang.ord.
Event.state is a bit mask indicating which of certain modifier keys and mouse buttons were down or active when the event triggered and is not reliable because of the system specific facilities as pointed out here.
As a side-note the NMT claim that these bitmasks are valid to test during a event:
Mask Modifier
0x0001 Shift.
0x0002 Caps Lock.
0x0004 Control.
0x0008 Left-hand Alt.
0x0010 Num Lock.
0x0080 Right-hand Alt.
0x0100 Mouse button 1.
0x0200 Mouse button 2.
0x0400 Mouse button 3.
Another StackOverflow answer that shows how you could use it.
Related
I wrote a simple python script that gives control over the cursor to a joystick. My way to find out how this works is documented here. Now that works flawlessly but, as soon as I start the script to use the joystick, the mouse is useless, because my python routine sets the value back to its original, whenever a new joystick event comes in.
Thus I want my joystick events to be ignored as long as a key of the keyboard is pressed. I came across the pygame.key.get_pressed() method but this seems to work only, if the pygame window is in focus. I want this script running in background. Should I start using non-pygame events to listen to the keyboard or are there ways to keep track of the keyboard events analogue to the joystick events, which are recognized in background, via pygame?
I expect pygame sets up its own "sandbox" so that it's hard to detect input from outside its window. Your previous question indicates that you are also using the win32api module. We can use that to detect global key presses.
The correct way to detect key presses at the global scope is to set up a keyboard hook using SetWindowsHookEx. Unfortunately, win32api does not expose that method, so we'll have to use a less efficient method.
The GetKeyState method can be used to determine whether a key is down or up. You can continuously check the state of a key to see if the user has pressed or released it lately.
import win32api
import time
def keyWasUnPressed():
print "enabling joystick..."
#enable joystick here
def keyWasPressed():
print "disabling joystick..."
#disable joystick here
def isKeyPressed(key):
#"if the high-order bit is 1, the key is down; otherwise, it is up."
return (win32api.GetKeyState(key) & (1 << 7)) != 0
key = ord('A')
wasKeyPressedTheLastTimeWeChecked = False
while True:
keyIsPressed = isKeyPressed(key)
if keyIsPressed and not wasKeyPressedTheLastTimeWeChecked:
keyWasPressed()
if not keyIsPressed and wasKeyPressedTheLastTimeWeChecked:
keyWasUnPressed()
wasKeyPressedTheLastTimeWeChecked = keyIsPressed
time.sleep(0.01)
Warning: as with any "while True sleep and then check" loop, this method may use more CPU cycles than the equivalent "set a callback and wait" method. You can extend the length of the sleep period to ameliorate this, but the key detection will take longer. For example, if you sleep for a full second, it may take up to one second between when you press a key and when the joystick is disabled.
when your window gains or looses focus you get an ACTIVEEVENT. It's gain and state attributes tell you which state you've gained or lost. The easisest solution would probably be to catch this events in your main event loop and use them to keep track weather you have focus or not. Then you can just ignore joystick events if you don't have the focus.
I trying to move my mouse inside an FPS game (like valorant/csgo) but doesn't work.
I used PyAutoGui, PyInput, Mouse, PyWin32, and many other libs but I just can simulate a click.
I see something about Interception (by oblitum) and years ago worked but this day doesn't. The game block this intercept.
So I guess I need to build some driver intercept to make moves in Mouse. Another trick is to use Arduino (this works these days) but for my project this isn't a solution. I need to only in python with any mouse.
This depends how you want to move your mouse. I'm assuming according to however you want to move it? If so, try the first code as the second code performs based on a series of commands
Have you tried this code by #flipeador?
#from interception import Interception, MouseFilter, KeyFilter, MouseFlags,\
# MouseState, KeyState, MapVk, Vk, map_virtual_key
RUNNING = True
TIMEOUT = 2500 # ms
interception = Interception()
interception.set_mouse_filter(MouseFilter.ButtonAll)
interception.set_keyboard_filter(KeyFilter.All)
while RUNNING:
device = interception.wait_receive(TIMEOUT)
if device:
print(f'{device.get_hardware_id()}:')
# Mouse
if device.is_mouse:
print('MouseStroke(flags={1},state={2},rolling={0.rolling},x={0.x},y={0.y},info={0.info})'
.format(device.stroke, MouseFlags(device.stroke.flags).name, MouseState(device.stroke.state).name))
# Keyboard
elif device.is_keyboard:
vk = map_virtual_key(device.stroke.code, MapVk.ScToVk)
print('KeyStroke(sc={0.code:03X},vk={2:03X},state={1},info={0.info})'
.format(device.stroke, KeyState(device.stroke.state).name, vk))
# escape = terminate
if vk == Vk.Escape:
RUNNING = False
# switch x and y
elif vk == Vk.X:
device.stroke.code = map_virtual_key(Vk.Y, MapVk.VkToSc)
elif vk == Vk.Y:
device.stroke.code = map_virtual_key(Vk.X, MapVk.VkToSc)
device.send()
print('-'*100)
Do note that you are not allowed to cheat in Valorant, as it blocks a lot of "hacking" and detect if your hacking even if the program your using is not on their block list.
I'm not here to question your morality.
Definitely go the arduino(s) route (you may need two. One to receive python commands and one to emulate the mouse events. Depends on the arduino) and be sure to use some randomization everywhere.
I do question why you'd want this.
I see no fun in cheating and I can't see what you are trying to achieve with this.
Although you said it did not work for you, the package you want to use is pynput. It is possible to simulate mouse movements and clicks as stated in the docs.
from pynput.mouse import Button, Controller
mouse = Controller()
# Move pointer relative to current position
mouse.move(5, -5)
This should give you the behaviour you want.
EDIT: with anti-cheat software in place, it may be very hard (not to say impossible) to simulate mouse movements in games. The game can distinguish organic mouse movement from simulated movement. Python alone might not be able to convince Valorant that your mouse movement is "real" ;)
I need to modify a script in psychopy. The thing I need is the subject to press and hold a buttom in the keyboard, but I'd like to have two responses: one when he/her presses it (and the windows with text has to change), and the second when he/her releases it (and the windows with text has to change again).
I am using event.getKeys function of psychopy, and then I'm using keyboard library.
after inizializing the window screen and the text and importing psychopy and the functions I need and keyboard library as key.
intro.draw()
win.flip() # reset the clock to record a response time and clear events
event.clearEvents('all')
event.globalKeys.clear() #to avoid problems with the keys you pressed before
intro_loop = True
while intro_loop:
intro_keys = kb.getKeys(["space"], waitRelease=True)
if key.is_pressed('space'):
intro.text = 'Hi, please follow these instructions :) '
intro.draw()
win.flip() # reset the clock to record a response time and clear events
if len(intro_keys):
win.close()
intro_loop = False
I did the same in another script (just to try) but instead of having a window text screen I printed two different things, and it worked. in this script, instead, it completely ignores the function "key.is_pressed".
do you have any ideas?
For amusement, I'm wring a python pygame program. I wanted to add keyboard shortcuts as an alternative to using the mouse to click the buttons. When investigating this I was looking at the event.mod types that can act as modifiers on the keys (i.e. alt, ctrl, shift, num lock, etc.). They are pretty straightforward except for one.
I cannot figure out what key the modifier pygame.KMOD_MODE is intended to indicate is being pressed. This is the list of modifiers, and it is the last one.
Constant Description
-------------------------
KMOD_NONE no modifier keys pressed
KMOD_LSHIFT left shift
KMOD_RSHIFT right shift
KMOD_SHIFT left shift or right shift or both
KMOD_LCTRL left control
KMOD_RCTRL right control
KMOD_CTRL left control or right control or both
KMOD_LALT left alt
KMOD_RALT right alt
KMOD_ALT left alt or right alt or both
KMOD_LMETA left meta
KMOD_RMETA right meta
KMOD_META left meta or right meta or both
KMOD_CAPS caps lock
KMOD_NUM num lock
KMOD_MODE mode
The numeric value of the flag is hex 0x4000, but that's just a mapping and doesn't indicate what triggers the modifier flag getting set.
I have been searching around but cannot find anything that uses or explains what this is intended to indicate. Of course I can just ignore it since this is just for fun and not a 'real' project, but I really would like to understand what this is.
Anyone know what key would trigger this modifier?
Not a definitive answer here, but Simple DirectMedia Layer maps KMOD_MODE to 'AltGr'. AltGr seems to be relevant to international\multi-locale keyboards, though it seems some operating systems have alternate keystrokes to achieve the same thing, e.g. AltGr key not working, instead i have to use Ctrl+AltGr
If you don't have a keyboard with the AltGr key handy, try some of the alternative key combos and see if PyGame responds accordingly.
I know this question is long but what I really want to know is in bold.
I would prefer to use python on Linux.
I'm trying to make a new keyboard layout kind of like devorak but the layout is set to either layout1 or layout2 depending on if you are holding a hot key or not (the hot key should probably be ctrl?)
e.g. press d -> "z" prints to the screen using key layout1
e.g. press ctrl d -> "x" prints to the screen using key layout2
My main problem (and question that needs answering) is the way characters need to print to the screen.
if someone presses the keys (in this order) "(a)(b)(c)(d)(ctrl+d)(shift+e=E)(f)(Enter)"
now lets say the output for these key presses should be "oijzxKb"
I don't want output to render with new lines:
o
i
j
z
x
K
b
I want the characters to appear instantly on the screen as each character is pressed (without waiting for them to press enter).
e.g.
press o
Screenshot1 o
press i
Screenshot2 oi
press j
Screenshot3 oij
.. etc
I assume I will need the following:
a way to read keypresses instantly
a way to print key presses instantly (to the terminal or a GUI or whatever is easiest initially, if it worked on any editor that would be cool!)
I could probably do this in PyGame (but then I probably wouldn't be able to cut and paste etc) and I'm guessing there should be an easier way.
I'm using a Logitech G110 keyboard, I may eventually want to use this as an alternative to my qwerty keyboard on all my applications across all my devices.
Thanks!
EDIT: SOLUTION:
Thanks to the first response,
using Getch from http://code.activestate.com/recipes/134892/
getch = _Getch()
word=""
while True:
c=getch.impl()
if c=="a":
word+="z"
elif ord(c)==127: #backspace
word=word[:-1]
else:
word+=c
print word
This will suffice for now thank you. Once I'm happy with refinement I'll look at doing something lower level, operating system specific without python.
One problem with getch however is that ctrl+a cant be distinguished between ctrl+A (e.g. if you hold ctrl and press keys, it can't tell the difference between upper and lower case)
If it's ok to depends on the X window system, you can use the python-xlib module or the xpyb module to access the X window system and use a XGrabKey call to grab the keyboard related events. Upon each KeyPress event you will be able to print the pressed key.
Now, if you really want to write a keymap, this is totally OS/window system dependent. If you use the X window system (Ubuntu does), you need to check the X documentation about how to write a new keymap. On Ubuntu, the current keymaps definition should be in /usr/share/X11/xkb. Take a look, and try to copy and edit one. You can use setxkbmap to change the current keymap then.
To modify the key mapping of your keyboard, you must use the tools provided by your OS. Most applications don't accept generated events for security reasons.
In your case, that would be xmodmap. Don't forget to create a backup of your current keymap using the -pke option because you will make a mistake - and then, your keyboard won't be working anymore.
If you also want your new keymap work on the console, have a look at the kbd package which changes the keyboard layout at the kernel level.