PCXT
27th October 2020, 23:14
Hello
My configuration:
- Debian 10 Buster, Qt 5.11.3 (from distribution packages), X11-based desktop.
I have a problem with Qt (probably with Qt) and I just don't know where to start looking for its culprit. First of all, I decided to make a small program in which I need to insert characters to other applications. Generally, the window is like on-screen keyboard and pressing a button will cause character being sent to currently open application.
The code I have for this action is a known approach, XLib and Xtest to feed re-defined keycodes:
void MainWindow::push_char(char character)
{
Display * disp; //current X11 display
disp=XOpenDisplay(nullptr); //TODO: fail gracefully when abused in console.
KeySym * xkeysyms = nullptr;
int temporaryKeyCode=0;
int keycodes_start=0;
int keycodes_end=0;
int keysyms_per_keycode=0;
XDisplayKeycodes(disp,&keycodes_start,&keycodes_end); //obtain keycode range for current display.
xkeysyms=XGetKeyboardMapping(disp,keycodes_start,k eycodes_end-keycodes_start,&keysyms_per_keycode); //get keysyms start-end
for (int i=keycodes_start; i<=keycodes_end; i++) //Iterate through keycode list to obtain free one
{
bool empty_keycode=true;
for (int j=0; j<keysyms_per_keycode; j++) //check all keysyms to be zero
{
int keysym_index = (i - keycodes_start) * keysyms_per_keycode + j; //obtain keysym position
if(xkeysyms[keysym_index] != 0) //if the key is not empty...
{
empty_keycode=false; //nope... next one
break;
}
}
if (empty_keycode) //use this code for our character.
{
temporaryKeyCode=i;
break;
}
}
XFree(xkeysyms); //this finding and freeing must be done every time, not at the program boot-up,
XFlush(disp); //as user may change X settings on the fly, including key tables.
usleep(100*1000); //0.1 delay
//Prepare for character send
KeySym sym = XStringToKeysym("U01F92A"); //Uxxxx links unknown UTF char to key even when it's not in any definition. As in xkbcommon-keysyms.h
// KeySym sym = XStringToKeysym("U0142"); //THIS WORKS., the above does not in all applications.
if (sym == NoSymbol) //This should rarely happen.
{
sym=XStringToKeysym("x"); //have anything here or throw error.
}
KeySym symlist[2]={sym, sym}; //create a keysym list for shifted and unshifted chr
XChangeKeyboardMapping(disp,temporaryKeyCode,2,sym list,1); //assign the list to the mapping
XFlush(disp);
KeyCode code=temporaryKeyCode; //create code out of temporary
XTestFakeKeyEvent(disp, code, true, 0); //Press...
XFlush(disp);
usleep(90 * 1000);
XTestFakeKeyEvent(disp, code, false, 0); //Release...
XFlush(disp);
symlist[0]=0;
symlist[1]=0;
XChangeKeyboardMapping(disp,temporaryKeyCode,2,sym list,1); //revert the mapping
usleep(90 * 1000);
XCloseDisplay(disp); //End routine
return;
}
In the code, I have two test lines for making a keysym of UTF character: First one makes it from "U0142", second is "U01F92A" (or U1F92A - an emoji which, at least in my system, shows a smiley).
The routine (currently argument is not processed) works, but not for all characters and not for all applications. Things I observed:
- When characters are like Uxxxx, 2 hex bytes after U, it's OK for all applications I tested: Based on GTK, Qt, Qt Creator itself too, WxWidgets and even an old ?Qt3-based? TDE.
- When characters are longer, like Uxxxxxx - 3 hex bytes after U, it works for GTK, WxWidgets, TDE, but not Qt applications, even not in Qt Creator itself.
This is a strange behavior and for me it looks like there may be some problem with library configuration in my set-up?
When instead of my code I use xdotool (xdotool type "?") I have a similar behavior, that's why I think about misconfiguration.
Thanks in advance.
MW
My configuration:
- Debian 10 Buster, Qt 5.11.3 (from distribution packages), X11-based desktop.
I have a problem with Qt (probably with Qt) and I just don't know where to start looking for its culprit. First of all, I decided to make a small program in which I need to insert characters to other applications. Generally, the window is like on-screen keyboard and pressing a button will cause character being sent to currently open application.
The code I have for this action is a known approach, XLib and Xtest to feed re-defined keycodes:
void MainWindow::push_char(char character)
{
Display * disp; //current X11 display
disp=XOpenDisplay(nullptr); //TODO: fail gracefully when abused in console.
KeySym * xkeysyms = nullptr;
int temporaryKeyCode=0;
int keycodes_start=0;
int keycodes_end=0;
int keysyms_per_keycode=0;
XDisplayKeycodes(disp,&keycodes_start,&keycodes_end); //obtain keycode range for current display.
xkeysyms=XGetKeyboardMapping(disp,keycodes_start,k eycodes_end-keycodes_start,&keysyms_per_keycode); //get keysyms start-end
for (int i=keycodes_start; i<=keycodes_end; i++) //Iterate through keycode list to obtain free one
{
bool empty_keycode=true;
for (int j=0; j<keysyms_per_keycode; j++) //check all keysyms to be zero
{
int keysym_index = (i - keycodes_start) * keysyms_per_keycode + j; //obtain keysym position
if(xkeysyms[keysym_index] != 0) //if the key is not empty...
{
empty_keycode=false; //nope... next one
break;
}
}
if (empty_keycode) //use this code for our character.
{
temporaryKeyCode=i;
break;
}
}
XFree(xkeysyms); //this finding and freeing must be done every time, not at the program boot-up,
XFlush(disp); //as user may change X settings on the fly, including key tables.
usleep(100*1000); //0.1 delay
//Prepare for character send
KeySym sym = XStringToKeysym("U01F92A"); //Uxxxx links unknown UTF char to key even when it's not in any definition. As in xkbcommon-keysyms.h
// KeySym sym = XStringToKeysym("U0142"); //THIS WORKS., the above does not in all applications.
if (sym == NoSymbol) //This should rarely happen.
{
sym=XStringToKeysym("x"); //have anything here or throw error.
}
KeySym symlist[2]={sym, sym}; //create a keysym list for shifted and unshifted chr
XChangeKeyboardMapping(disp,temporaryKeyCode,2,sym list,1); //assign the list to the mapping
XFlush(disp);
KeyCode code=temporaryKeyCode; //create code out of temporary
XTestFakeKeyEvent(disp, code, true, 0); //Press...
XFlush(disp);
usleep(90 * 1000);
XTestFakeKeyEvent(disp, code, false, 0); //Release...
XFlush(disp);
symlist[0]=0;
symlist[1]=0;
XChangeKeyboardMapping(disp,temporaryKeyCode,2,sym list,1); //revert the mapping
usleep(90 * 1000);
XCloseDisplay(disp); //End routine
return;
}
In the code, I have two test lines for making a keysym of UTF character: First one makes it from "U0142", second is "U01F92A" (or U1F92A - an emoji which, at least in my system, shows a smiley).
The routine (currently argument is not processed) works, but not for all characters and not for all applications. Things I observed:
- When characters are like Uxxxx, 2 hex bytes after U, it's OK for all applications I tested: Based on GTK, Qt, Qt Creator itself too, WxWidgets and even an old ?Qt3-based? TDE.
- When characters are longer, like Uxxxxxx - 3 hex bytes after U, it works for GTK, WxWidgets, TDE, but not Qt applications, even not in Qt Creator itself.
This is a strange behavior and for me it looks like there may be some problem with library configuration in my set-up?
When instead of my code I use xdotool (xdotool type "?") I have a similar behavior, that's why I think about misconfiguration.
Thanks in advance.
MW