MULTIKEY , Is the code correct?

New to FreeBASIC? Post your questions here.
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

MULTIKEY , Is the code correct?

Post by VANYA »

Hi ALL!

I'm trying to get the program to catch the SHIFT + KEY key combinations in the Linux terminal. For some reason, in about 10% of cases (randomly) when starting MULTIKEY does not work. Maybe I wrote the code wrong?

Code: Select all

dim as Zstring*5 key
dim as long iShift , iLeft , iRight
While Inkey <> "": Wend
do
	if (multikey(&h36)  or multikey(&h2A)) then ' SHIFT
		iShift = 1
	else
		iShift = 0
	EndIf
	if multikey(&h4B) then ' LEFT
		iLeft = 1
	else
		iLeft = 0
	EndIf   
	if multikey(&h4D) then ' RIGHT
		iRight = 1
	else
		iRight = 0
	EndIf
	if iShift andalso (iRight) then
		? "SHIFT+RIGHT" 
		While Inkey <> "": Wend
		sleep(200 , 1)
	elseif iShift andalso (iLeft) then
		? "SHIFT+LEFT"
		While Inkey <> "": Wend
		sleep(200 ,1)
	else
		key = inkey
		if len(key) then
			? *cast(short ptr , @key)
		endif
	EndIf	
loop until key = chr(27)
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: MULTIKEY , Is the code correct?

Post by VANYA »

Really nobody can tell, whether the code is correct?

I recorded a video showing the problem with this code. Let me explain:

The terminal window on the right is a program for catching global keys so you know what keys are being pressed. The SHIFT key has code 50 in its raw form. The LEFT key has code 113 , the Right key has code 114.
The terminal window on the left is the program itself with MULTIKEY. Unfortunately, it is not always possible to quickly catch the moment when Multikey does not work. But in this video I show several launches and on the last launch I caught the moment when Multikey does not work. I also did a few letter key presses while holding SHIFT. As well as a few Left and Right key presses without the SHIFT key.

Here's a video: https://disk.yandex.ru/i/HXhV-vn3ehyPkw
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: MULTIKEY , Is the code correct?

Post by fxm »

Can you try adding a SLEEP in the loop?

Code: Select all

dim as Zstring*5 key
dim as long iShift , iLeft , iRight
While Inkey <> "": Wend
do
	if (multikey(&h36)  or multikey(&h2A)) then ' SHIFT
		iShift = 1
	else
		iShift = 0
	EndIf
	if multikey(&h4B) then ' LEFT
		iLeft = 1
	else
		iLeft = 0
	EndIf   
	if multikey(&h4D) then ' RIGHT
		iRight = 1
	else
		iRight = 0
	EndIf
	if iShift andalso (iRight) then
		? "SHIFT+RIGHT" 
		While Inkey <> "": Wend
		sleep(200 , 1)
	elseif iShift andalso (iLeft) then
		? "SHIFT+LEFT"
		While Inkey <> "": Wend
		sleep(200 ,1)
	else
		key = inkey
		if len(key) then
			? *cast(short ptr , @key)
		endif
	EndIf
	sleep 10
loop until key = chr(27)
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: MULTIKEY , Is the code correct?

Post by VANYA »

fxm wrote: Nov 16, 2022 6:00 Can you try adding a SLEEP in the loop?
Unfortunately this doesn't help.

I don't know what the problem is anymore.
1) Is there an error somewhere inside the Multikey function?
2) Any bugs with the functions that Multikey is based on?
3) Maybe there are some problems of simultaneous use of Inkey and Multikey in the code?
4) ...

Unfortunately there is no other cross-platform way to get keyboard shortcuts SHIFT+LEFT , SHIFT+RIGHT in console applications on FB. :(
hhr
Posts: 206
Joined: Nov 29, 2019 10:41

Re: MULTIKEY , Is the code correct?

Post by hhr »

This short program does not work in linux:

Code: Select all

do
   if (multikey(&h36) or multikey(&h2A)) and multikey(&h4B) then
      ? "SHIFT+LEFT"
   end if
   
   if (multikey(&h36) or multikey(&h2A)) and multikey(&h4D) then
      ? "SHIFT+RIGHT"
   end if
loop until inkey = chr(27)
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: MULTIKEY , Is the code correct?

Post by VANYA »

hhr wrote: Nov 16, 2022 9:18 This short program does not work in linux:

Code: Select all

do
   if (multikey(&h36) or multikey(&h2A)) and multikey(&h4B) then
      ? "SHIFT+LEFT"
   end if
   
   if (multikey(&h36) or multikey(&h2A)) and multikey(&h4D) then
      ? "SHIFT+RIGHT"
   end if
loop until inkey = chr(27)
Replace:
or on orelse
and on andalso
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: MULTIKEY , Is the code correct?

Post by fxm »

VANYA wrote: Nov 16, 2022 9:26 Replace:
or on orelse
and on andalso
Why ?
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: MULTIKEY , Is the code correct?

Post by fxm »

See Keypressed issue:
fxm wrote: Apr 30, 2021 15:39 When using text mode screen, Multikey doesn't like Sleep in its sampling loop.
(see also viewtopic.php?f=6&t=27255)

Existing bug report:
#493 MULTIKEY does not work in text mode
hhr
Posts: 206
Joined: Nov 29, 2019 10:41

Re: MULTIKEY , Is the code correct?

Post by hhr »

A simple 'print' helps in Linux. The same with the initial program.

Code: Select all

print' : locate 1
do
   if (multikey(&h36) or multikey(&h2A)) and multikey(&h4B) then
      ? "SHIFT+LEFT"
   end if
   
   if (multikey(&h36) or multikey(&h2A)) and multikey(&h4D) then
      ? "SHIFT+RIGHT"
   end if
loop until inkey = chr(27)
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: MULTIKEY , Is the code correct?

Post by VANYA »

fxm wrote: Nov 16, 2022 9:34 Why ?
It just happened when I replaced it with andalso and orelse , this code worked for me :)
Just a coincidence.
#493 MULTIKEY does not work in text mode
Created: 2010-02-10
Oops, this bug is still hanging (12 years)!
A simple 'print' helps in Linux. The same with the initial program.
I'll try.

Thanks to everyone for participating in this thread. Hopefully Jeff will see this bug and fix it.

--------------------
Added last:

First I wrote print , as advised by hhr. I ran my program 50 times in a row and everything seems to be fine. It looks like this solves the problem.
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: MULTIKEY , Is the code correct?

Post by speedfixer »

OK. Looks like a fun game. (I have never seen a problem with multikey. I only use Linux.)

Code: Select all

'dim as Zstring*5 key
dim as string key
dim as string keypressed
dim as long iShift , iLeft , iRight
dim as long addtime     ' normal keypress can be 15 to 50 msec
                        ' TWO keys -- lots longer
cls : print : print " last key pressed:"; : print : print

while inkey <> "": wend
do
    sleep 10 + addtime, 1                 'first, give the cpu some time
    keypressed = "" : addtime = 0
    iShift = 0 : iLeft = 0 : iRight = 0

    if (multikey(&h36) or multikey(&h2A)) then ' SHIFT
        iShift = 1
    end if

    if multikey(&h4B) then ' LEFT
        iLeft = 1
    end if

    if multikey(&h4D) then ' RIGHT
        iRight = 1
    end if

    if iShift and (iRight) then
        keypressed = " SHIFT+RIGHT "
    end if

    if iShift and iLeft then
        keypressed = " SHIFT+LEFT "
    end if

    if iRight and iLeft then
        keypressed =  " RIGHT+LEFT "
    end if

' unless you have a really slow machine - 40 tests here would be easy
' Console is slow - a graphics page is much faster - 200+ tests easy

    if (not ishift) and (not ileft) then
        key = inkey
' your OS or terminal/console program MAY steal some of your keys
' In Linux, choosing/configuring the console program can be tricky
        if len(key) then
'            ? str(*cast(integer short ptr , @key)) ' this tells you what?
'       also, as a pointer, it should be an integer to be meaningful
' if you want the extended keys, then add them as tests just above this line
' those tests are a different topic.
            keypressed = trim(str(asc(key)))
        end if
    end if
    while inkey <> "": wend     'only need this once

    if len(keypressed) <> 0 then
        locate 5, 10, 0
        print " "; keypressed; "          ";
        addtime = 95
    end if

loop until key = chr(27)

cls : print : print "done" : print
Hope this helps someone.
david

(edit: I forgot to mention: I would NEVER use print inside a test loop like this - unpredicatable OS response times.)
hhr
Posts: 206
Joined: Nov 29, 2019 10:41

Re: MULTIKEY , Is the code correct?

Post by hhr »

'cls' in the first line also works.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: MULTIKEY , Is the code correct?

Post by dodicat »

I only have windows.
As well as flushing the keyboard, multikey can also be flushed out of it's torpor when a sleep in introduced.
This seems to work for shift+left or right arrow keys, but I admit, it is not coded strictly analytically, more trial and error.(due to the bug)

Code: Select all

#include "fbgfx.bi"
Using fb

#define shift multikey(SC_Lshift) and multikey(SC_Rshift)

Sub flush
    Dim As Long flag
    While Inkey <> "": Wend
    While flag=0
        For n As Long=0 To 127
            If Multikey(n) Then flag=1:Exit For
        Next
    Wend
End Sub


Do
    Var key=""
    If shift Then
        If Multikey(SC_Left) Then key= "LEFT  with SHIFT"
        If Multikey(SC_Right) Then key= "RIGHT  with SHIFT"
    End If
    
    If Len(key) Then Print key
    
    Sleep(100)
    If Inkey=Chr(27) Then Exit Do
    flush
Loop



 
hhr
Posts: 206
Joined: Nov 29, 2019 10:41

Re: MULTIKEY , Is the code correct?

Post by hhr »

@dodicat
In Linux I have to replace 'and' with 'or' in the third line, and the first line must be 'cls' or 'print'.
I don't know why it works in Windows with 'and', and why you need 'cls' or 'print' in Linux. This was done by accident.
It also works with 'locate' in Linux and it must not be the first line.

@speedfixer
You have 'cls : print...' before you use multikey.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: MULTIKEY , Is the code correct?

Post by fxm »

Misbehavior of Multikey when using text mode screen

I have already noticed (under Windows) with Multikey (with text mode screen) that a code structure like:

Code: Select all

Do
    For I As Long = 0 TO 255
        If Multikey(I) Then
            If I = n1 Then .....
            If I = n2 Then .....
            .....
            If I = 1 Then Exit Do  '' escape
        End If
    Next I
    Sleep 25, 1
Loop
always works, which is not always the case if we only test the useful values with Multikey.

Otherwise even more abruptly, by adding only the following line (which seems useless) as the first line of the scanning loop of the useful values for Multikey:
For I As Long = 0 To 255 : Multikey(I) : Next I
this unblocked the cases of not working (with text mode screen).
Post Reply