Forum Archive

Check multi-keys press

yaley

Hi, i tried to use objc UIViewController to get key press with text field, but the problem is, if i press left arrow key first, and then press right arrow key, the right arrow key’s CustomViewController_pressesBegan_withEvent_ will not triggered, pls help?

DOGGY

You can try to use

key_command(sender)

and

get_key_commands()

For documentation : visit here

yaley

i tried it before, but thank for your help :D it does the same result

cvp

@yaley said

if i press left arrow key first, and then press right arrow key

I guess you did not release the first press. Then perhaps you could intercept pressesChanged(_:with:)

DOGGY

@yaley ok. How about using pygame module? It might work :

import pygame
screen = pygame.display.set_mode((0,0,320,320))
while True:
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN or event.type == pygame.KEYUP:
            if event.mod == pygame.KMOD_NONE:
                print('No modifier keys were in a pressed state when this '
                  'event occurred.')
            else:
                if event.mod & pygame.KMOD_LSHIFT:
                     print('Left shift was in a pressed state when this event '
                      'occurred.')
                if event.mod & pygame.KMOD_RSHIFT:
                     print('Right shift was in a pressed state when this event '
                      'occurred.')
                if event.mod & pygame.KMOD_SHIFT:
                    print('Left shift or right shift or both were in a '
                      'pressed state when this event occurred.') 
cvp

@DOGGY as explained here pygame is not Pure PyThon thus does not work in Pythonista

yaley

@cvp my code is still not working


def CustomViewController_pressesBegan_withEvent_(_self, _cmd, _presses, event):
    global activeKeys
    presses = ObjCInstance(_presses).allObjects()
    keyCode = presses[0].key().keyCode()

    activeKeys[keyCode] = True

def CustomViewController_pressesEnded_withEvent_(_self, _cmd, _presses, event):
    global activeKeys
    presses = ObjCInstance(_presses).allObjects()
    keyCode = presses[0].key().keyCode()

    activeKeys[keyCode] = False

def CustomViewController_pressesChanged_withEvent_(_self, _cmd, _presses, event):
    global activeKeys
    presses = ObjCInstance(_presses).allObjects()
    keyCode = presses[0].keyCode()

    activeKeys[keyCode] = False

cvp

@yaley why do you set your activeKeys as False in changed?

DOGGY

@yaley Yes, sorry, as @cvp and my tries, using pygame module is not possible in Pythonista because Pythonista doesn’t have pygame Stash also cannot

yaley

@DOGGY It’s ok :)

yaley

@cvp oops that’s my wrong, but after changing it to True, it’s still not working, everything turns True, let me see the documentation carefully again.

After the key changed, the activeKey turns True, but then it will forever True, until next keyup

cvp

@yaley don't forget that presses is a kind of array with eventually multiple keys thus perhaps not only check [0]

DOGGY

@YaleY that would be a hard one…..

yaley

@cvp so what should i do now???? Can you show me the code with successful running?

cvp

@yaley said

Can you show me the code with successful running?

Ho no, you are further than me. I only try to think about it.
When you press the right arrow, your first key is still pressed?

yaley

@cvp yes, but the problem is when the second press joined CustomViewController_pressesChanged_withEvent_() didnt run about it

yaley

@cvp You’re method is correct, just i am stupid, i typed wrongly, i set the variable to True in the pressesEnded def

XD

cvp

@yaley right, just tested

yaley

Wait no, why??? Why my first test is correct and then the second test is not working?????

cvp

@yaley for me, changed not called
If you change something in a created class, restart Pythonista

yaley

@cvp here’s my code, I’ve tried to restart Pythonista

def CustomViewController_pressesBegan_withEvent_(_self, _cmd, _presses, event):
    global activeKeys
    presses = ObjCInstance(_presses).allObjects()
    keyCode = presses[0].key().keyCode()

    activeKeys[keyCode] = True

def CustomViewController_pressesEnded_withEvent_(_self, _cmd, _presses, event):
    global activeKeys
    presses = ObjCInstance(_presses).allObjects()
    keyCode = presses[0].key().keyCode()

    activeKeys[keyCode] = False

def CustomViewController_pressesChanged_withEvent_(_self, _cmd, _presses, event):
    global activeKeys
    presses = ObjCInstance(_presses).allObjects()
    keyCode = presses[0].keyCode()

    activeKeys[keyCode] = True
cvp

@yaley you should add some print in each method to check if called

cvp

@yaley said

keyCode = presses[0].keyCode()

Key() missing in changed

cvp

@yaley only began is called once with left arrow, second with right arrow

Thus, forget changed, and all is ok because two keys imply 2 calls to began

yaley

@cvp thanks it solved!!!

yaley

@cvp looks like i found the problem, if in the changed def, i set activeKeys[keyCode] = presses[0].key().keyCode() it doesn’t work, but if i set activeKeys[keyCode] = presses[0].keyCode() then it works :)

cvp

@yaley sorry, perhaps I (or my eyes) become too old, but I don't see the difference

yaley

@cvp no it’s my wrong again xD They’re absolutely no difference before, lol

yaley

@cvp I’ve already changed it, read it again :D The difference is [0].key().keyCode() and [0].keyCode()

yaley

Wait, um, after i added print() the pressesChange is not activating

cvp

@yaley ok. And did you trace, sure that changed def is called?

Sorry: was typing while your previous post was coming

yaley

@cvp i dont think that that def was called :(

cvp

@yaley but do you really need it? The doc says it is called if you change something in your key press, like force. If you know which key is down and up, and when, you have all you need, haven't you?

yaley

Yep! Maybe…. No need!

yaley

@cvp But the main problem is just when arrow keys will happen, just like umm i give you an example:
I am detecting keys with ui.Textfield() And now i start pressing left arrow key. So in the input it goes left ( the selection bar ), but if the right arrow keys joined the right arrow key, the selection bar of input still goes left.

yaley

And, also, can vi.View().get_key_commands() and ui.View().key_command(sender) detect keyup? if can, then i can make

yaley

@cvp can it?

yaley

@cvp but the main thing is it cannot handle 3 keys, i press space first, then press “a” key ( space key is still holding ), finally press”d” key but “D” key is not triggered and still moving left ( “A” for left, “D” for right )

cvp

@yaley sorry, was driving to France for some days, not able to answer

cvp

@yaley said

can it?

No idea

JonB

There are four methods you can implement:

https://developer.apple.com/documentation/uikit/uiresponder/1621134-pressesbegan?language=objc

You also have pressesEnded_withEvent_, and pressesChanged_withEvent_. Technically, pressesCancelled_withEvent_, but that's rare.

See
https://developer.apple.com/documentation/uikit/mac_catalyst/handling_key_presses_made_on_a_physical_keyboard?language=objc

You can inspect the modifiers:
UIKeyModifierAlphaShift 1<<16
A modifier flag that indicates the user pressed the Caps Lock key.
UIKeyModifierShift 1<<17
A modifier flag that indicates the user pressed the Shift key.
UIKeyModifierControl 1<<18
A modifier flag that indicates the user pressed the Control key.
UIKeyModifierAlternate 1<<19
A modifier flag that indicates the user pressed the Option key.
UIKeyModifierCommand 1<<20
A modifier flag that indicates the user pressed the Command key.
UIKeyModifierNumericPad 1<<21
A modifier flag that indicates the user pressed a key located on the numeric keypad

Also, to check for special characters, you would look at charactersIgnoringModifiers, and check for special strings from https://developer.apple.com/documentation/uikit/uikeycommand/input_strings_for_special_keys?language=objc

for example 'UIKeyInputRightArrow'

(Convert to str before comparing).

Technically, when looking at apple docs, in this case then consts are defined as NSString *, so the way you get the value is

ObjCInstance(c_void_p.in_dll(c, 'UIKeyInputRightArrow'))

But in this case, the NSString is simply equal to the constant name.

yaley

@JonB so….. what should i change?