XKeysymToKeycode, XTestFakeKeyEvent and mapping - keyboard

I have the following problem:
I'm trying to send fake key events to the X server.
To do this, I'm aware of two methods:
XSendEvent - I tried this tutorial with the XK_Z instead of XK_Down
Does not work with GTK3
XTestFakeKeyEvent - See my code below
My problem is, None of this method takes account of the keyboard mapping. I mean, when I select AZERTY mapping I have a "z" character as I expect, when I select the QWERTY mapping I get a "w" and with my beloved BÉPO mapping I get an "é".
How can I get the same character independently of the keyboard mapping??
I'm using Ubuntu 12.10 under Unity.
Here, my code for XTestFakeKeyEvent:
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
#include <iostream>
// The key code to be sent.
// A full list of available codes can be found in /usr/include/X11/keysymdef.h
/* g++ -o XFakeKey tst.c -L/usr/X11R6/lib -lX11 -lXtst */
char *text = "z";
main()
{
// Obtain the X11 display.
Display *display = XOpenDisplay(0);
if(display == NULL)
return -1;
Window focusWindow;
int revert;
XGetInputFocus(display, &focusWindow, &revert);
KeyCode code = XKeysymToKeycode(display, XStringToKeysym(text));
XTestFakeKeyEvent(display, code, True, CurrentTime);
XTestFakeKeyEvent(display, code, False, CurrentTime);
XCloseDisplay(display);
return 0;
}

Use the XChangeKeyboardMapping API to bind a unicode Keysym to an unused Keycode.
Then, you send the remapped Keycode (using XTestFakeKeyEvent or XSendEvent) and applications that use XKeycodeToKeysym will get your intended symbol, independent of the current keyboard/IME.
Not tested, but seems to work according to this comment.

Related

Only some unicode characters work with ncurses

I'm using ncurses 6.3, installed on OSX 12.0.1. My program is:
#define NCURSES_WIDECHAR 1
#include <locale.h>
#include <ncurses.h>
int main() {
setlocale(LC_ALL, "");
initscr();
// prints fine. Even the red heart, which is multiple code-points.
addwstr(L"🙂❤️\n");
// doesn't print the check mark. Interesting...
addwstr(L"️✅");
refresh();
getch();
endwin();
// Prints fine.
printf("%ls\n", L"✅");
return 0;
}
I'm not sure if this is a bug in ncurses, or much more likely I am misusing it.
U+2705 was added to Unicode in 2010, which makes it a little old, but wcwidth returns -1, making ncurses believe it is nonprinting. I can see this in a debug trace using the ncurses test program (using mouse to select/highlight the missing character's position),
which has this chunk:
PUTC 0x20
PutAttrChar({{ {-1:\u2705} }}) at (2, 25)
forced to blank
PUTC 0x20
The part in {{..}} comes from a trace function (see source) using _nc_wacs_width, which in turn is either a macro calling wcwidth directly, or a function calling wcwidth. Either way, it doesn't appear to be a bug in ncurses.

is %llx or %llu not supposed to work with wsprintf?

I am using Visual Studio 2017 C++. When I use printf with a specification such as %llx or %llu everything works as expected. If I use the same format spec, %llu or %llx, with wsprintf, I get junk in the buffer instead of the result I had gotten with printf.
My question is: is there a way to get wsprintf to give the result that should be obtained when using %llx and/or %llu ?
Below is a very simple console program that demonstrates the different behavior of printf and wsprintf.
#include "stdafx.h"
#include <Windows.h>
#include <inttypes.h>
int main()
{
DWORD64 OffsetHWM = 0x7123456789012345;
WCHAR BufferBytes[256] = { 0 }; // initialized - no junk in there
// the wprintf below works as expected
wprintf(L"from wprintf : %8llX\n", OffsetHWM);
// this call to wsprintf isn't filling the buffer with the expected value
wsprintf(BufferBytes, L"%8llX\n", OffsetHWM);
wprintf(L"from wsprintf: %s\n", BufferBytes); // prints junk
wprintf(L"\n"); // just for neatness
wsprintf(BufferBytes, L"%8" PRIx64 "\n", OffsetHWM);
wprintf(L"from wsprintf: %s\n", BufferBytes);
// this truncates (as expected) the value of OffsetHWM - not useful
wsprintf(BufferBytes, L"%8lx\n", OffsetHWM);
wprintf(L"from wsprintf: %s\n", BufferBytes);
return 0;
}
wprintf() should not be used any more, it is a Windows specific function which calls either wsprintfA() or wsprintfW() to do the actual work, both of which have the following note on their Windows Dev Centre Documentation site (https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-wsprintfa):
Note Do not use. Consider using one of the following functions instead: StringCbPrintf, StringCbPrintfEx, StringCchPrintf, or StringCchPrintfEx. See Security Considerations.

proper way of catching control+key in ncurses

What is the proper way of catching a control+key in ncurses?
current im doing it defining control like this:
#define ctl(x) ((x) & 0x1f)
it works ok, but the problem is that i cannot catch C-j and ENTER at the same time, and this is because:
j = 106 = 1101010
0x1f = 31 = 0011111
1101010 & 0011111 = 0001010 = 10 = ENTER key..
So.. how shall I catch it?
Thanks!
--
Edit:
If i try the code below,
I am not able to catch the enter key correctly, not even in the numeric keyboard. Enter gets catched as ctrl-j.
#include <stdio.h>
#include <ncurses.h>
#define ctrl(x) ((x) & 0x1f)
int main(void) {
initscr();
int c = getch();
nonl();
switch (c) {
case KEY_ENTER:
printw("key: %c", c);
break;
case ctrl('j'):
printw("key: ctrl j");
break;
}
getch();
endwin();
return;
}
New code:
#include <stdio.h>
#include <ncurses.h>
#define ctrl(x) ((x) & 0x1f)
int main(void) {
initscr();
int l = -1;
int c = getch();
cbreak();
noecho();
nonl();
keypad(stdscr, TRUE);
switch (c) {
case KEY_ENTER:
printw("key: %c", c);
break;
case ctrl('j'):
printw("key: ctrl j");
break;
}
printw("\nnow press a key to end");
getch();
endwin();
return;
}
Try nonl:
The nl and nonl routines control whether the underlying display device
translates the return key into newline on input, and whether it translates newline into return and line-feed on output (in either case, the
call addch('\n') does the equivalent of return and line feed on the
virtual screen). Initially, these translations do occur. If you disable them using nonl, curses will be able to make better use of the
line-feed capability, resulting in faster cursor motion. Also, curses
will then be able to detect the return key.
Further reading: the Notes section of the getch manual page:
Generally, KEY_ENTER denotes the character(s) sent by the Enter key on
the numeric keypad:
the terminal description lists the most useful keys,
the Enter key on the regular keyboard is already handled by the
standard ASCII characters for carriage-return and line-feed,
depending on whether nl or nonl was called, pressing "Enter" on the
regular keyboard may return either a carriage-return or line-feed,
and finally
"Enter or send" is the standard description for this key.
That addresses the question about newline/carriage-return translation. A followup comment is a reminder to point out that the manual page gives basic advice in the Initialization section:
To get character-at-a-time input without echoing (most interactive,
screen oriented programs want this), the following sequence should be
used:
initscr(); cbreak(); noecho();
and that OP's sample program did not use cbreak (or raw). The manual page for cbreak says
Normally, the tty driver buffers typed characters until a newline or
carriage return is typed. The cbreak routine disables line buffering
and erase/kill character-processing (interrupt and flow control characters are unaffected), making characters typed by the user immediately
available to the program. The nocbreak routine returns the terminal to
normal (cooked) mode.
Initially the terminal may or may not be in cbreak mode, as the mode is
inherited; therefore, a program should call cbreak or nocbreak explicitly. Most interactive programs using curses set the cbreak mode.
Note that cbreak overrides raw. (See curs_getch(3x) for a discussion
of how these routines interact with echo and noecho.)
Also, in curs_getch you may read
If keypad is TRUE, and a function key is pressed, the token for that
function key is returned instead of the raw characters:
The predefined function keys are listed in <curses.h> as macros
with values outside the range of 8-bit characters. Their names begin with KEY_.
That is, curses will only return KEY_ENTER if the program calls keypad:
keypad(stdscr, TRUE);
For the sake of discussion, here is an example fixing some of the problems with your sample program as of May 17:
#include <stdio.h>
#include <ncurses.h>
#define ctrl(x) ((x) & 0x1f)
int
main(void)
{
int c;
initscr();
keypad(stdscr, TRUE);
cbreak();
noecho();
nonl();
c = getch();
switch (c) {
case KEY_ENTER:
printw("\nkey_enter: %d", c);
break;
case ctrl('j'):
printw("\nkey: ctrl j");
break;
default:
printw("\nkeyname: %d = %s\n", c, keyname(c));
break;
}
printw("\nnow press a key to end");
getch();
endwin();
return 0;
}
That is, you have to call keypad before getch, and the value returned for KEY_ENTER is not a character (it cannot be printed with %c).
Running on the Linux console with the usual terminal description, you will see only carriage return for the numeric keypad Enter, because that description does not use application mode. Linux console does support application mode, and a corresponding description could be written. As a quick check (there are differences...) you could set TERM=vt100 to see the KEY_ENTER.

How to set carriage return location or equivalent?

I am looking for a way to set where the carriage return, returns to or an equivalent way to do so.
For example I have a line like this:
^ denotes cursor location
myshell>cat file.txt
^
After carriage return it should look like this.
myshell>cat file.txt
^
You're probably after what's collectively called ANSI escape sequences. Its hard to search for if you really have no idea what you're after.
This tiny example saves/restores cursor position:
#include <stdio.h>
int main(int argc, char**argv)
{
char cmd_buf[100];
cmd_buf[0]=0;
while(strncmp(cmd_buf, "quit", 4))
{
printf("mypromt>\033[s <-Cursor should go there\033[u");
fflush(stdout);
fgets(cmd_buf, sizeof(cmd_buf), stdin);
printf("\nYou entered: %s\n", cmd_buf);
}
}
Note that in terminator, gnome-terminal and xterm on Ubuntu, this "magically" supports CTRL+U as-is, but not CTRL+A or CTRL+E.
There are many, many more sequences available. The wikipedia page is probably the simplest reference to get you started.
Update: Also, unless you're doing this as a learning exercise (which I get the impression Benjamin is), to build an interactive shell, you should probably use one of the two well established libraries for shell-style line editing, namely:
readline (GPLv3, but far more popular)
editline (BSD licensed, closest "second place")
They are the libraries that provide the emacs-style (typical default) and vi-style keybindings and history features we all know and love from bash, python, lua, perl, node, etc, etc.
For positioning on the screen, termios is of limited use (the ioctl's dealing with screensize are not in POSIX), and unless you want to assume a lot about the terminal characteristics, control characters and escape sequences have their limitations.
You can do what's asked in curses using the filter function to tell the library you want to use just the current line of the display. As written, the question is puzzling since it does not mention any output other than the current line. But for example (this is exactly what was asked):
#include <curses.h>
int
main(void)
{
int ch, y, x;
filter();
initscr();
cbreak();
addstr("myshell>");
getyx(stdscr, y, x);
while ((ch = getch()) != ERR) {
if (ch == '\n')
move(y, x);
}
endwin();
return 0;
}
However, a usable program would do more than that. There's an example of the filter() function in ncurses-examples, which you may find useful for reading. A screenshot:

can't capture keyboard strokes with cvWaitKey()

I have a problem here and need your help. I've been trying to capture keyboard strokes using cvWaitKey() function.
cvWaitKey(10) should return the keyboard stroke pressed every 10ms.
But in my case, I'm getting every 18 seconds, all the keys that I've pressed during this period of 18 seconds, at once.
And the window that should normally close when I press 'esc' (see the code) is still open.
In console I get this:
VIDIOC_QUERYMENU:Invalid argument
VIDIOC_QUERYMENU:Invalid argument
VIDIOC_QUERYMENU:Invalid argument
-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-11536870939-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-111536870939-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1
With:
1536870939 corresponds to when I pressed 'esc'
-1 correspond to when no key was pressed
Thanks for help.
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "iostream"
using namespace std;
int main()
{
IplImage *src=cvCreateImage(cvSize(640,480), 8, 3);
CvCapture* capture =cvCaptureFromCAM(CV_CAP_ANY);
int key;
while(1){
src = cvRetrieveFrame( capture );
cvNamedWindow( "out", CV_WINDOW_AUTOSIZE );
cvShowImage( "out", src );
key = cvWaitKey(10);
cout<<key;
if( key == 1536870939 ) break; //if 'esc' is pressed (in ubuntu 10.04)
cvGrabFrame( capture );
}
cvDestroyAllWindows();
cvReleaseCapture( &capture );
return 0;
}
I'm using: Opencv 2.2.0 , ubuntu 10.04 LTS , CodeBlocks 8.02
try using a 0xff mask to return 27 on an ESC key press:
if( (cvWaitKey(10)&0xff) == 27 ) break;
Alternatively, you can cast to a character:
if( (char)cvWaitKey(10) == 27 ) break;
The cause of the problem is the way cout works: it buffers characters and only sends them to the console if you send a newline character or if you explicitly ask it to do so. (Third case: the buffer gets full... but that's what you have to wait 18 seconds for.)
So put either cout << '\n'; or cout.flush(); after your current cout statement.
(By the way: VIDIOC_QUERYMENU:Invalid argument is from the v4l (webcam) driver... and I have no idea where 1536870939 comes from, ESC should be 27 :))

Resources