Getting key name from keycode (X11 XGrabKey) - c++

I have a global key event handler in linux as below. I need to know which keyboard is grabbed. For example if key 'P' is pressed I get the corresponding key code. Is there any way to get the key name ("P") from this unsigned key code ?
#include <xcb/xcb.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <QtX11Extras/QX11Info>
void EventFilter::setup(QWidget *target)
{
this->target = target;
Display * display = QX11Info::display();
unsigned int modifiers = ControlMask;
keycode = XKeysymToKeycode(display, XK_A);
XGrabKey(display, keycode, modifiers, DefaultRootWindow(display), 1, GrabModeAsync, GrabModeAsync);
}
bool EventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *)
{
if (eventType == "xcb_generic_event_t")
{
xcb_generic_event_t* xcbevent = static_cast<xcb_generic_event_t *>(message);
switch(xcbevent->response_type)
{
case XCB_KEY_PRESS:
xcb_key_press_event_t * keypress_event = static_cast<xcb_key_press_event_t *>(message);
if(keypress_event->state & XCB_MOD_MASK_CONTROL)
{
if(keypress_event->detail == keycode)
{
//print key name here
}
}
}
}
return false;
}

Given a key code, from the event detail field, you can get the KeySym using the XkbKeycodeToKeysym function, then a textual representation of the pressed key, passing the KeySym to the XKeysymToString function.
Have this extra include:
#include <X11/XKBlib.h>
Then, in the event handler:
case XCB_KEY_PRESS:
xcb_key_press_event_t * keypress_event = static_cast<xcb_key_press_event_t *>(message);
xcb_keycode_t code = keypress_event->detail;
qDebug() << XKeysymToString( XkbKeycodeToKeysym(QX11Info::display(), code, 0, 0) );
In the example above, an index of 0 is passed as the last argument of XkbKeycodeToKeysym. This will return the symbol for the pressed key as if the shift key (or caps lock, or any other modifier key) is not pressed. Passing an index of 1 will return the symbol as if the shift key was pressed. Other values (i.e. 2) will yield symbols one obtains pressing more modifier keys (e.g. in my italian keyboard I have to press Alt Gr to type square brackets).
Please notice, the returned string is really a name to identify the keyboard symbol, which can be, for example, a, b, c or X for letters, but comma, or backslash for other symbols.

Related

Qt catch shift + 3 on one key press

I'm using Qt 5.11.
I need to catch shift + 3 on one key press. But this combination generates special character ^ because I'm using Turkish Q Keyboard. So I can't catch it without press shift + 3 again.
I tried shift modifiers and multiple key press solutions but not working.
I want to override ^. Is there any possible ways to do it?
Try the following it could work. Although according to the documentation, nativeVirtualKey could return 0 even if there is valid information. So not sure if it will work all the time. I tested it with a german, english and arabic keyboard.
Update (tested it with turkish keyboard layout)
void keyPressEvent(QKeyEvent *ev)
{
if ((ev->nativeVirtualKey() == Qt::Key_3 || ev->key() == Qt::Key_3) && ev->modifiers() == Qt::ShiftModifier)
{
//Do something
}
}
For turkish layout, ^ caret (a dead key), in addition to the above, you can catch the dead key press by overriding the nativeEvent function and calling the keyEvent function manually
bool nativeEvent(const QByteArray & eventType, void * message, long * result)
{
MSG *msg = reinterpret_cast<MSG*>(message);
if (msg->message == WM_DEADCHAR)
{
QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, Qt::Key_3, Qt::ShiftModifier);
}
}
One minor issue, the keyEvent will be called even if ^ is pressed in another language, not necessarily only with Shift+3, so this is an unexpected behaviour, but maybe for your case you can tell the user that both shift+3 or ^ are the shortcut for your specific function

How to check if a key sequence is press?

I would like to check if a key sequence is press. Like a password, i would like that to see the message box you must type "bcqwl" in right sequenze. I tried
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
while(true)
{
if(GetKeyState('B') & 0x8000)
{
cout<<"b has been press"<<endl;
if(GetKeyState('C') & 0x8000)
{
cout<<"c has been press"<<endl;
if(GetKeyState('Q') & 0x8000)
{
cout<<"Q has been press"<<endl;
if(GetKeyState('W') & 0x8000)
{
cout<<"W has been press"<<endl;
if(GetKeyState('L') & 0x8000)
{
MessageBox(NULL,"YES","YES",MB_OK);
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
}
But it doesn't works. He print "B has been press" ,many times but not infinitely times,if b is pressed. If after to press b I press c nothing happens.
So i tired:
step:
if(GetKeyState('B') & 0x8000)
{
cout<<"B has been press"<<endl;
goto step1;
}
else
{
goto step;
}
step1:
if(GetKeyState('C') & 0x8000)
{
MessageBox(NULL,"WORK","yes",MB_OK);
}
else
{
goto step;
}
But doesn't work.
I also tired:
#include <iostream>
#include <windows.h>
int main()
{
int progress = 0;
while(progress<=4)
{
if(GetKeyState('B') & 0x8000)
{
std::cout<<"b has been press"<<std::endl;
progress=1;
}
else
{
progress=0;
}
if(progress==1)
{
if(GetKeyState('C') & 0x8000)
{
std::cout<<"c has been press"<<std::endl;
progress=2;
}
else
{
progress=0;
}
}
if(progress==2)
{
if(GetKeyState('Q') & 0x8000)
{
std::cout<<"q has been press"<<std::endl;
progress=3;
}
else
{
progress=0;
}
}
if(progress==3)
{
if(GetKeyState('W') & 0x8000)
{
std::cout<<"w has been press"<<std::endl;
progress=4;
}
else
{
progress=0;
}
}
if(progress==4)
{
if(GetKeyState('L') & 0x8000)
{
std::cout<<"l has been press"<<std::endl;
progress=5;
}
else
{
progress=0;
}
}
}
return 0;
}
But that output "b has been press" for many times but not infinitely if i press b, and after if i press c nothing is happening, praticaly after press b and the program go in if(process==1) but if i press c nothing happen
P.S. sorry for my bad english.
The problem you are still having comes from the fact that you are in no way storing the progress in your key sequence.
Let's say your password is stored in a char array (for easier access to the single characters later on):
#define PWD_LEN 6 // bcqwl has a length of 5 characters but you need +1 for the '\0' (terminating character) at the end of your string
// ...
char password[PWD_LEN] = "bcqwl";
In addition you will need a counter:
#define PWD_LEN 5
// ...
char password[PWD_LEN] = "bcqwl";
int progress = 0;
while(true) { ... }
Both need to be stored before and outside the while loop because both store data that you don't want to reset in each iteration step in your loop.
The counter will be used to track the progress of the user towards completing the key sequence your password represents.
Whenever the user presses a key you will need to do the following checks:
Is the key allowed? - if you have a password abc but the user presses y or !, or something other then a, b or c the key is not allowed.
If the key is allowed take the character it represents and check if it's the same as the character in your password at index progress:
if ( key allowed )
{
if (password[progress] == '<your key character here>')
{
++progress;
}
else
{
// Handle incorrect key stroke relative to key sequence
}
}
Now in order to prevent the counter going bananas I would suggest doing all the checking upon key released, which unlike key pressed is a one time event. A key being pressed can also be part of key hold, in which case you will land in the else (from the code snippet above) many times, which might not be such a good idea.
If the key is ok and in terms of sequence it fits your password then you increase the progress so that in the next iteration step you can do the same check with a new released key event and a new index value for accessing your password array.
When your progress reaches the required value indicating that the key sequence is completed and that all the characters your password consists of have been "inserted" you can break the loop.
This is very basic so I hope that the instructions are clear enough for you to implement.
PREVIOUS ANSWER (now obsolete due to change in the question)
Unless other out-of-the-box way is available to do that (I haven't used GetKeyState() or anything else from windows.h) the general practice is to simply store the pressed state of each button (in an array, a struct etc.).
In your loop you can use a simple chain of if statements (but not nested like you do it!) to check which button is pressed during the current iteration step. Whenever a known key (one that you application wants to process) is pressed, you just need to toggle the respective state of that button in your array, struct or whatever other container you use to store this information:
while(true)
{
// Check state of supported buttons
if(GetKeyState('A') & 0x8000)
{
// store change of state of key A
}
if(GetKeyState('B') & 0x8000)
{
// store change of state of key B
}
if (...)
{
// ...
}
}
At the end or beginning of your while's body you can then ask for the state of each button and also make combined queries:
while(true)
{
// Check state of supported buttons
if(GetKeyState('A') & 0x8000)
{
// store change of state of key A
}
if(GetKeyState('B') & 0x8000)
{
// store change of state of key B
}
if (...)
{
// ...
}
// Do something
// Check for states of buttons
// ...
}
For example let's say you are using the following structure to store the key's state:
typedef struct Key
{
char keyCode;
bool pressed;
} Key;
Key keyA;
keyA.pressed = false;
you can simply do
if (keyA.pressed)
{
// Trigger some change that key 'A' controls
}
to check if your specific button is currently pressed and respectively trigger some action.
For key combinations things are not much different. You just need to use simply boolean logic to handle it:
if (keyA.pressed && keyB.pressed)
{
// Both key 'A' and 'B' are pressed - we have a key combo!
}
You can improve the readability of your code by storing all supported buttons in an array and even adding a nice enum to provide easy access to each button:
enum KeyCode
{
A,
B,
...
};
Key keys[n]; //with n being the number of keys you want to support and also the number of elements your enum has
// Access with an improved readability
if (keys[A].pressed && keys[B].pressed)
{
// ...
}
If you can't find any code for GetKeyState() in particular (highly unlikely) you can look at SDL for example.

Check Q button is held down using GLUT?

What function can I use to check if the Q button (or any other button is pressed down) and what will be the value needed to specify this for the Q button?
Using glut you need to define a Keyboard Handler function, and tell GLUT to use it for handling key strokes. Something along the lines of:
bool is_q_pressed = false;
void KeyboardHandler(unsigned char key, int x, int y)
{
switch (key)
{
case "q":
case "Q":
is_q_pressed = !is_q_pressed;
if (is_q_pressed)
// do something... or elsewhere in program
break;
}
}
void KeyboardUpHandler(unsigned char key, int x, int y)
{
switch (key)
{
case "q":
case "Q":
is_q_pressed = false;
break;
}
}
int main()
{
// Other glut init functions...
...
// Keyboard handler
glutKeyboardFunc(KeyboardHandler);
// Keyboard up handler
glutKeyboardUpFunc(KeyboardUpHandler);
...
glutMainLoop();
return 0;
}
EDIT: Added support for keyboard up. Using global variables isn't the best practice, but GLUT almost forces you to use them to keep track of program states. The good thing is that you can use the global variable (is_q_pressed) anywhere in your program... like in the idle() for some logic, or in the draw function to draw something if that key is pressed.
And, as #aslg said, you can make an array of bools to keep track of every key pressed, check his answer for ideas too :)
The simplest thing you can do is to use an array of bools with enough bools to contain the 256 regular keys and the special keys (right, left, etc.. ).
bool keys[256];
Use the KeyDown func to set the matching key to true, and KeyUp to set false.
void KeyboardDown( int key, int x, int y ) {
if ( isalpha( key ) ) {
key = toupper( key );
}
keys[ key ] = true;
}
void KeyboardUp( int key, int x, int y ) {
if ( isalpha( key ) ) {
key = toupper( key );
}
keys[ key ] = false;
}
The toupper just makes sure that pressing q or Q is the same whether Caps-lock is on or off. You don't have to use it if you don't need it.
Then somewhere in the update code you can check if a key was pressed like
if ( keys['Q'] ) {
// do things
}

QTextEdit - How to "cancel" entered key codes in onKeyPress()

I am trying to "cancel" key codes in QTextEdit or QPlainTextEdit. When I say cancel, what I mean is, I want to turn the "entered" character into "nothing" depending on the key entered. Example: if the user hits "a" or "b" on the keyboard, I would not want to have "a" or "b" displayed / entered into the text, instead, the input would be ignored and turned into nothing / won't be processed.
With C++ Builder, you have a KeyDown_Event and a "Key" parameter. Once you detect the entered key code, if you don't like it, you can set the "Key" parameter to 0, so you set "Key = 0" and the key stroke would not be displayed. How do I achieve the same thing in Qt?
Let me explain with code:
if (e->key() == 67)
// do not send "c" to the QTextEdit (In C++ Bullder, you would do Key = 0)
if (e->key() == 65)
// do not send "a" to the QTextEdit (In C++ Bullder, you would do Key = 0)
How do I do this in Qt?
I tired doing e->setAccepted(false) and e->Ignore() but it made no difference. I think by the time e->ignore() is executed, the "char" is already inserted into the text box. With C++ Builder, you can intercept this with the KeyDown event and cancel it. I can't seem to find a way with Qt.
Thx
Similar to void QObject::installEventFilter ( QObject * filterObj ) example:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
textEdit->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (watched == textEdit && event->type() == QEvent::KeyPress) {
QKeyEvent *e = static_cast < QKeyEvent * >(event);
if (e->key() == Qt::Key_A) {
return true;
}
}
return QMainWindow::eventFilter(watched, event);
}
UPDATE
As IInspectable noticed, this won't help you with filtering Ctrl+C/Ctrl+V method. If you need these either, you'll need to connect to QTextEdit::textChanged signal and updated the text manually. Something like this:
static QString oldString;
QString s = textEdit->toPlainText();
if (s == oldString)
return;
int pos = textEdit->textCursor().position();
s.remove('a', Qt::CaseInsensitive);
oldString = s;
textEdit.setPlainText(s);
QTextCursor cursor = textEdit->textCursor();
cursor.setPosition(pos);
textEdit->setTextCursor(cursor);

C++: GetKeyState() has to run once

I need to listen keyboard key states for my tiny application.
#include <windows.h>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
while(1)
{
if(GetKeyState(VK_SPACE) & 0x80)
{
cout << "Space pressed.\r\n";
DoSpaceKeyTask();
}
if(GetKeyState(OTHER_KEY) & 0x80)
{
cout << "Other key pressed.\r\n";
DoOtherKeyTask();
}
}
return 0;
}
Once I click some keys from my keyboard, these functions has to run once. They're just some tiny tasks for my applications, which is not related in this topic.
My problem is, when I press a key, it executes the functions few times, due to while(1) looping few times during key press. I cannot use Sleep() in this case, because it still won't be effective.
I'm looking for a solution like this.
I press SPACE key.
DoSpaceKeyTask() executes "once."
I press OTHER key.
DoOtherKeyTask() executes "once."
I have like 5 keys that I will be using. Could anyone help me on this case?
Ps. If GetKeyState() function isn't useful on this task, feel free to suggest yours. My function knowledge is pretty limited on C++.
Your functions are called multiple times because of the duration time the button stays pressed. The system is very sensitive. So this is a workaround.
You could do something like this (set a flag that will assign a value when the key is down, and then reasign it when the key is up).
int k=0;//Flag
while(1){
//check if the key was pressed (key_down)
if((GetAsyncKeyState('0') & 0x8000) && (k == 0)){k=1; cout<<"'0' PRESSED."<<k<<endl;}//do your stuff here
//check if the key was released (key up)
else if(GetAsyncKeyState('0') == 0) k = 0;//reset the flag
}
I think that you will prefer to execute your functions "once" only when you have released up your keys, not when you have depressed (pressed) them down.
You don't need any additional flags and helper variables to define, allocate, assign to 0, and set each one to 1 and reset to 0 and so on, in order to achieve this goal. All what you need is just: First you have to use GetKeyState function inside the scope of while(1) to check when you have depressed a key. When the expression returns true, the executor pointer (the arrow that carry out a code line and then proceeds forward to the next code line when you either step into or step over) will enter into the if statement's scope. Then immediately trap it inside a loop and keep it trapped in there while the key you have depressed is still down and stop it before it is going to execute the function and free it when you have released that key up and then let it to execute the function.
For example, to execute the DoSpaceKeyTask function only "once" when you have depressed and released the space bar, then do the following code that should work:
while (1)
{
if (GetKeyState(VK_SPACE) & 0x80)
{
//The code here executes ONCE at the moment the space bar was pressed
cout << "Space pressed.\r\n";
while (GetKeyState(VK_SPACE) & 0x80) //You can write there ';' instead '{' and '}' below
{
//The executor pointer is trapped here while space bar is depressed and it will be free once space bar is released
}
//The code here executes ONCE at the moment the space bar was released
cout << "Space released.\r\n";
DoSpaceKeyTask();
}
}
Just the same with DoOtherKeyTask function:
while (1)
{
if (GetKeyState(OTHER_KEY) & 0x80)
{
//The code here executes ONCE at the moment the other key was pressed
cout << "Other key pressed.\r\n";
while (GetKeyState(OTHER_KEY) & 0x80) //You can write there ';' instead '{' and '}' below
{
//The executor pointer is trapped here while other key is depressed and it will be free once other key is released
}
//The code here executes ONCE at the moment the other key was released
cout << "Other key released.\r\n";
DoOtherKeyTask();
}
}
If you have already used either BT_'s idea or Pawel Zubrycki's idea, and now you want to use my idea, then you can delete all flags and variables that they suggested, because you don't need them anymore.
By the way, I have already tried the code that Pawel Zubrycki posted, but it doesn't work for me. The output that says that I have pressed either space bar or other key was not displayed when I have really pressed the space bar or other key that I chose.
Try this approach:
#include <windows.h>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
char lastSpaceState = 0, lastOtherKeyState = 0, spaceState, otherKeyState;
while(1)
{
spaceState = (GetKeyState(VK_SPACE & 0x80) != 0);
lastSpaceState = (spaceState && !lastSpaceState);
if(lastSpaceState)
{
cout << "Space pressed.\r\n";
DoSpaceKeyTask();
}
otherKeyState = (GetKeyState(OTHER_KEY) & 0x80 != 0);
lastOtherKeyState = (otherKeyState && !lastOtherKeyState);
if(lastOtherKeyState)
{
cout << "Other key pressed.\r\n";
DoOtherKeyTask();
}
}
return 0;
}
or as Chris suggest in OP comment more "modern" async approach.
You want a windows hook to hook the game and react to the keyboard input that game gets. Now I haven't really done this specific type of hook, but I can give you a good idea of the flow. I'll leave it up to you to cut down the space by looping through a map of keys you need rather than a huge, repetitive switch, and also to work out any small kinks I put in.
int main()
{
//I imagine the last argument here is the thread
//containing the game's message loop
HHOOK hook = SetWindowsHookEx (WH_CALLWNDPROC, hookProc, NULL, NULL);
//main loop
UnhookWindowsHookEx (hook);
}
LRESULT CALLBACK hookProc (int code, WPARAM wParam, LPARAM lParam)
{
if (code == HC_ACTION)
{
CWPSTRUCT details = *((LPCWPSTRUCT)lParam);
if (details.message == WM_KEYDOWN)
{
switch (details.wParam)
{
case KEY_ONE:
if (last [KEY_ONE] == UP)
{
DoKeyOneStuff();
last [KEY_ONE] = DOWN;
}
break;
}
}
else if (details.message == WM_KEYUP)
{
switch (details.wParam)
{
case KEY_ONE:
last [KEY_ONE] = UP;
break;
}
}
}
return CallNextHookEx (NULL, code, wParam, lParam);
}
Note how I use last [KEY_ONE]. I would recommend using an std::map to store keys you need by their vk code. Then you can just loop through the map and cut down a lot of space that a switch would take.
I was having the same issue. I have several keys that act like toggle buttons and only want to register the key events once per press. My solution was to make a simple object to handle the logic. This keeps the main code clean:
class KeyToggle {
public:
KeyToggle(int key):mKey(key),mActive(false){}
operator bool() {
if(GetAsyncKeyState(mKey)){
if (!mActive){
mActive = true;
return true;
}
}
else
mActive = false;
return false;
}
private:
int mKey;
bool mActive;
};
And here is the usage:
#include <windows.h>
KeyToggle toggleT(0x54); // T key toggle
KeyToggle toggleF(0x46); // F key toggle
void main(void)
{
while(true){
if(toggleT) {;} // do something
if(toggleF) {;} // do something
}
}
I know that this is pretty old thread but I still want to share my solution. I think that creating some kind of "flags" or "switches" is really not needed. Here is my code of looping all keycodes:
while (true)
{
for (int i = 0x01; i < 0xFE; i++)
{
if (GetKeyState(i) & 0x8000)
{
std::cout << (char)i << "\n";
while (GetKeyState(i) & 0x8000) {}
}
}
}
As you can see, you can easily just use while and the same GetKeyState function to wait for the key unpress. Much simpler solution.
Try sth. like this;
while (!GetKeyState(VK_SPACE) && !GetKeyState('A') == 1) {
//std::cout << "Key not pressed... \n";
Sleep(40);
}
if (GetKeyState('A')) {
std::cout << "\"A \" key pressed... \n";
}
else if (GetKeyState(VK_SPACE)) {
std::cout << "Space key pressed... \n";
}