***
FBKEYBOARD2 - improved key mappings + rotate modes
*** Notice that the Esc key causes the Kobo to go into sleep mode, which is a problem if we want to enter command mode in Vi, or call up the menu in elinks.
Until we address Kobo's grabbing of the input in various other ways, we can still get by with:
1) Ctrl-c in Vi can also be used instead of Esc to enter command mode.
2) We can remap the 'm' key instead of Esc in elinks to open the menu.
In Post #4 we already remapped some elinks keys by appending to the elinks config file:
$ nano -l /mnt/onboard/.adds/koreader/.elinks/elinks.conf
Code:
##################################
# Automatically saved keybindings
#
bind "main" "Ctrl-F" = "frame-next"
bind "main" "Ctrl-B" = "frame-prev"
bind "main" "," = "history-move-back"
bind "main" "." = "history-move-forward"
bind "main" "u" = "link-info"
bind "main" "Alt-l" = "lua-console"
bind "main" "Down" = "move-cursor-down"
bind "main" "Left" = "move-cursor-left"
bind "main" "Right" = "move-cursor-right"
bind "main" "Up" = "move-cursor-up"
bind "main" "Tab" = "move-link-next"
bind "main" "Shift-Tab" = "move-link-prev"
bind "main" "#" = "toggle-numbered-links"
bind "main" "Ctrl-Right" = "none"
This remapped the following:
Up,Down,Left,Right -> move cursor
Tab,Shift-Tab -> travel links on a page
. -> go forward in history
, -> go back in history
Some handy default key mappings are:
Space -> page down
b -> page up
[ or { -> scroll left
] or } -> scroll right.
Enter to edit a text field,
d -> download link
a -> add bookmark
s -> show bookmarks
Esc -> main menu
g -> enter new address or '.' for current directory
q -> quit
T -> open in new tab
<,> -> go to previous,next tab
c -> close tab
W -> wrap text
In the numeric layout of fbkeyboard.c, there are some empty key slots after the '/', which if pressed, currently yield "cvbnm".
We will assign "aswtc" to them in char *layout[] and in keys[][26] so that in elinks we can access when in the numeric keyboard layout:
a -> add bookmark
s -> show bookmarks
w -> wrap text
t -> open in new tab
c -> close tab
To do this we will further append to the elinks config file as follows:
$ nano -l /mnt/onboard/.adds/koreader/.elinks/elinks.conf
Code:
##################################
# Automatically saved keybindings
#
bind "main" "Ctrl-F" = "frame-next"
bind "main" "Ctrl-B" = "frame-prev"
bind "main" "," = "history-move-back"
bind "main" "." = "history-move-forward"
bind "main" "u" = "link-info"
bind "main" "Alt-l" = "lua-console"
bind "main" "Down" = "move-cursor-down"
bind "main" "Left" = "move-cursor-left"
bind "main" "Right" = "move-cursor-right"
bind "main" "Up" = "move-cursor-up"
bind "main" "Tab" = "move-link-next"
bind "main" "Shift-Tab" = "move-link-prev"
bind "main" "#" = "toggle-numbered-links"
bind "main" "Ctrl-Right" = "none"
#
bind "main" "w" = "toggle-wrap-text"
bind "main" "t" = "open-link-in-new-tab"
bind "main" "m" = "menu"
Also in fbkeyboard2, we will reassign top row keys when in CAPS LOCK mode from Up, Down, Left, Right, and PageDown to accelerated (4 x) direction keys,and PageUp.
Also in fbkeyboard2, we will configure rotation modes for the Clara HD.
***
$ source ~/koxtoolchain/refs/x-compile.sh kobo env bare
Build FBInk and Freetype as in Post #6.
$ unzip fbkeyboard-master.zip
$ cd fbkeyboard-master/
***
Edit fbkeyboard.c * EXACTLY AS IN POST #6 *, except correct the following error:
$ nano -l fbkeyboard.c
Code:
...
605 fprintf(stderr, "fbkeyboard: fbval_t does not match framebuffer depth (%d bytes)\n", FBM_BPP(fb_mode()) );
...
Now for the new changes (note that switching to the Mono font seems to improve the key touch placement):
$ nano -l fbkeyboard.c
Code:
...
36 char *font = "./RobotoMono-Bold.ttf";
...
39 { "Esc", "Tab", " ^ ", " v ", " < ", " > ", ">> " },
40 { "Esc", "Tab", " 4^", " 4v", " 4<", " 4>", "<< " },
...
46 "1234567890-=[];\'\\,.`/aswtc",
47 "!@#$%^&*()_+{}:\"|<>~?aswtc"
...
60 KEY_GRAVE, KEY_SLASH, KEY_A, KEY_S, KEY_W, KEY_T, KEY_C },
...
102 switch (rotate) {
103 case FB_ROTATE_UR:
104 case FB_ROTATE_UD:
105 case FB_ROTATE_CW:
106 case FB_ROTATE_CCW:
107 break;
108 /* case FB_ROTATE_UD:
...
121 break; */
...
136 switch (rotate) {
137 case FB_ROTATE_UR:
138 case FB_ROTATE_UD:
139 case FB_ROTATE_CW:
140 case FB_ROTATE_CCW:
141 FT_Load_Char(face, c, FT_LOAD_RENDER);
142 x += face->glyph->bitmap_left;
143 y += (face->size->metrics.ascender >> 6) - face->glyph->bitmap_top;
144 advance = face->glyph->advance.x >> 6;
145 break;
146 /* case FB_ROTATE_UD:
...
184 break; */
...
307 switch (rotate) {
308 case FB_ROTATE_UR:
309 case FB_ROTATE_UD:
310 case FB_ROTATE_CW:
311 case FB_ROTATE_CCW:
312 lseek(fbfd, fblinelength * (fbheight - height * 6), SEEK_SET);
313 write(fbfd, buf, buflen);
314 keyb_refresh(fbfd, fbheight - height * 6, 0, width, fbheight);
315 break;
316 /* case FB_ROTATE_UD:
...
334 break; */
...
369 switch (rotate) {
370 case FB_ROTATE_UR:
371 *x = 0x10000 - absolute_y * 0x10000 / theight;
372 *y = absolute_x * 0x10000 / twidth;
373 break;
374 case FB_ROTATE_UD:
375 *x = 0x10000 - absolute_x * 0x10000 / twidth;
376 *y = 0x10000 - absolute_y * 0x10000 / theight;
377 break;
378 case FB_ROTATE_CW:
379 *x = absolute_y * 0x10000 / theight;
380 *y = 0x10000 - absolute_x * 0x10000 / twidth;
381 break;
382 case FB_ROTATE_CCW:
383 *x = absolute_x * 0x10000 / twidth;
384 *y = absolute_y * 0x10000 / theight;
385 break;
386 }
...
436 default:
437 *row = 5; // cursor, Enter, Home, PgDn, etc
438 /* *pressed = 3 * y / (0x10000 - trowh * 5);
439 *pressed *= 3;
440 *pressed += 3 * x / 0x10000; */
441 break;
...
466 if (pressed == 99) // second page
467 layoutuse ^= 2;
468 else if (row == 1 && (layoutuse & 1) > 0 && (layoutuse & 2) > 0 && (pressed > 20)) {
469 ie.type = EV_KEY;
470 ie.code = KEY_LEFTSHIFT;
471 ie.value = layoutuse & 0;
472 if (write(fduinput, &ie, sizeof(ie)) != sizeof(ie))
473 fprintf(stderr, "error sending uinput event\n");
474 send_key(keys[row + (layoutuse >> 1)][pressed]);
475 ie.type = EV_KEY;
476 ie.code = KEY_LEFTSHIFT;
477 ie.value = layoutuse & 1;
478 if (write(fduinput, &ie, sizeof(ie)) != sizeof(ie))
479 fprintf(stderr, "error sending uinput event\n");
480 } else if (row == 1) { // normal keys (abc, 123, !@#)
...
510 } else if (row == 0 && (layoutuse & 1) > 0) {
511 ie.type = EV_KEY;
512 ie.code = KEY_LEFTSHIFT;
513 ie.value = layoutuse & 0;
514 if (write(fduinput, &ie, sizeof(ie)) != sizeof(ie))
515 fprintf(stderr, "error sending uinput event\n");
516 if (pressed == 6) {
517 send_key(KEY_PAGEUP);
518 } else if (pressed == 2) {
519 send_key(KEY_UP);
520 send_key(KEY_UP);
521 send_key(KEY_UP);
522 send_key(KEY_UP);
523 } else if (pressed == 3) {
524 send_key(KEY_DOWN);
525 send_key(KEY_DOWN);
526 send_key(KEY_DOWN);
527 send_key(KEY_DOWN);
528 } else if (pressed == 4) {
529 send_key(KEY_LEFT);
530 send_key(KEY_LEFT);
531 send_key(KEY_LEFT);
532 send_key(KEY_LEFT);
533 } else if (pressed == 5) {
534 send_key(KEY_RIGHT);
535 send_key(KEY_RIGHT);
536 send_key(KEY_RIGHT);
537 send_key(KEY_RIGHT);
538 } else {
539 send_key(keys[row][pressed]);
540 }
541 ie.type = EV_KEY;
542 ie.code = KEY_LEFTSHIFT;
543 ie.value = layoutuse & 1;
544 if (write(fduinput, &ie, sizeof(ie)) != sizeof(ie))
545 fprintf(stderr, "error sending uinput event\n");
546 } else {
547 send_key(keys[row][pressed]);
548 }
...
673 switch (rotate) {
674 case FB_ROTATE_UR:
675 case FB_ROTATE_UD:
676 case FB_ROTATE_CW:
677 case FB_ROTATE_CCW:
678 landscape = fbheight < fbwidth;
679 width = fbwidth;
680 height = fbheight / (landscape ? 2 : 3) / 5; // height of one row
681 trowh = height * 0x10000 / fbheight;
682 linelength = fblinelength;
683 buflen = linelength * (height * 5 + 1);
684 break;
685 /* case FB_ROTATE_CW:
...
693 break; */
...
$ mkdir FBInk
$ cp -r ../FBInk-v1.25.0/Release FBInk/
$ cp ../FBInk-v1.25.0/fbink.h FBInk/
$ cp ../fbpad-eink-master/draw.c .
$ cp ../fbpad-eink-master/draw.h .
$ cp ../fbpad-eink-master/conf.h .
Edit draw.c and draw.h, also as in Post #6, but correct the following error:
$ nano -l draw.c
Code:
...
166 void keyb_refresh(int fd, int invalid_top, int invalid_left, int invalid_right, int invalid_bottom) {
...
$ cp ../freetype-2.13.1/objs/.libs/libfreetype.a .
$ arm-kobo-linux-gnueabihf-gcc -o fbkeyboard2 -I../freetype-2.13.1/include/ fbkeyboard.c draw.c libfreetype.a FBInk/Release/libfbink.a
$ ls -l fbkeyboard2
-rwxr-xr-x 588844 fbkeyboard2
Copy the fbkeyboard2 binary to the /mnt/onboard/.adds/koreader/scripts/ folder on your Kobo.
Copy the RobotoMono-Bold.ttf font to the /mnt/onboard/.adds/koreader/ folder on your Kobo (although with fbkeyboard you can also specify a font using the -f commandline argument.)
Edit /mnt/onboard/.adds/nm/config.txt to add a NickelMenu entry like this:
Code:
menu_item :main :fbkeyboard2 :cmd_spawn :quiet :export HOME="/mnt/onboard/.adds/koreader/" && cd "$HOME" && /mnt/onboard/.adds/koreader/scripts/fbkeyboard2
chain_success :dbg_toast :Started fbkeyboard2
chain_failure :dbg_toast :Error starting fbkeyboard2
ROTATION MODES:
Your NickelMenu may already have rotation options:
Code:
# Nickel_Orientation Actions
menu_item : main : Orientation - LANDSCAPE - handle above : nickel_orientation: landscape
menu_item : main : Orientation - LANDSCAPE - handle below : nickel_orientation: inverted_landscape
menu_item : main : Orientation - PORTRAIT - handle on left : nickel_orientation: inverted_portrait
menu_item : main : Orientation - PORTRAIT - handle on right : nickel_orientation: portrait
You can specify an fbkeyboard2 rotation with the -r commandline argument.
On my Clara HD, this is how they map:
fbkeyboard2 -r 3 -> LANDSCAPE - handle above
fbkeyboard2 -r 2 -> LANDSCAPE - handle below
fbkeyboard2 -r 1 -> PORTRAIT - handle on left
fbkeyboard2 -r 0 -> PORTRAIT - handle on right
If you are in landscape mode, you would want to restrict the percentage of the display that fbpad2 uses, with e.g.:
Code:
menu_item :main :fbpad2 -p 42 :cmd_spawn :quiet :/mnt/onboard/.adds/koreader/scripts/fbpad2 -p 42 /bin/sh 0</dev/tty1
chain_success :dbg_toast :Started fbpad2
chain_failure :dbg_toast :Error starting fbpad2
***
*UPDATE: COPY AND PASTE IN ELINKS
Edit: use 'e' instead of 'm' for opening menu in /mnt/onboard/.adds/koreader/.elinks/elinks.conf.
The default use of 'm' followed by a character, e.g. 'a' allows you to save your place in the document, and return to it by entering "'" then your character , e.g. 'a'.
bind "main" "e" = "menu"
bind "main" "S" = "save-as"
bind "main" "Ctrl-o" = "open-os-shell"
Use 'E' to open current link under cursor into a text field. (Or 'S' for current URL.)
Use "Ctrl-x" to copy link.
Use "Ctrl-v" to paste link.
***
Using Screen utility for copy-pasting:
The
screen app has only the following dependencies:
Depends (4)
libutempter
musl*
ncurses-libs*
utmps-libs
*already got these from elinks/nano install in Post #3.
RUN THESE COMMANDS FROM LINUX DESKTOP:
DOWNLOAD THE REQUIRED PACKAGES:
$ cd myalpine/
$ wget
https://dl-cdn.alpinelinux.org/alpin...n-4.9.0-r1.apk
$ wget
https://dl-cdn.alpinelinux.org/alpin...r-1.2.1-r5.apk
$ wget
https://dl-cdn.alpinelinux.org/alpin....12.0.1-r0.apk
$ wget
https://dl-cdn.alpinelinux.org/alpin...0.1.2.0-r1.apk
$ tar zxvf screen-4.9.0-r1.apk
$ tar zxvf libutempter-1.2.1-r5.apk
$ tar zxvf skalibs-2.12.0.1-r0.apk
$ tar zxvf utmps-libs-0.1.2.0-r1.apk
$ mv usr/bin/screen-4.9.0 scripts/screen
$ mv usr/lib/libutempter.so.1.2.1 libs/libutempter.so.0
$ mv lib/libskarnet.so.2.12.0.1 libs/libskarnet.so.2.12
$ mv lib/libutmps.so.0.1.2.0 libs/libutmps.so.0.1
NOW CONNECT YOUR KOBO TO YOUR PC:
Copy your screen binary from the scripts/ folder on the PC to the /mnt/onboard/.adds/koreader/scripts/ folder on the kobo.
Copy new libs from the libs/ folder on the PC to the /mnt/onboard/.adds/koreader/libs/ folder on the kobo:
libutempter.so.0
libskarnet.so.2.12
libutmps.so.0.1
Copy the usr/share/screen/ folder on the PC to the /usr/share/ folder on the kobo.
Copy the etc/screenrc file on the PC to the /etc/ folder on the kobo.
Copy the etc/skel/ folder on the PC to the /etc/ folder on the kobo.
RUN THESE FROM FBPAD2/FBKEYBOARD2 TERMINAL:
# . /korenv.sh
# screen
(Press Ret to dismiss message)
# elinks .
enter 'g' to open new URL
enter e.g. "g elinks doc"
click on the link, e.g. "http://elinks.or.cz/documentation/index.html"
enter 'a' to add to bookmarks
enter 's' to show bookmarks
Use the arrow keys to move to a link you want, e.g. "Documentation"
Use 'E' to open current link under cursor into a text field. (Or just 'S' to open current URL.)
Use "Ctrl-x" to copy link.
Use "Ctrl-v" to paste link.
Cancel to exit the dialog.
Enter "Ctrl-a" and then 'c' to open a new screen window.
Type the name of a command, e.g. 'echo > try.txt "' followed by "Ctrl-a" and then ']' and '"' and you get the text pasted to the file:
# cat try.txt
http://elinks.or.cz/documentation/index.html
(Was it worth the effort. i.e.you could have just saved as a bookmark, then retrieved the link from /mnt/onboard/.adds/koreader/.elinks/bookmarks!)
Move back and forth between screen terminals with "Ctrl-a" and then '0' or '1', or just "Ctrl-a" "Ctrl-a".
Enter 'q' to exit elinks.
"Ctrl-a" and then '\' to kill all windows and terminate screen.
***
Some time later...
OK definitely worth it for me anyway. Check this out:
On your Kobo:
# . /korenv.sh
Create a sample html file with a form field:
# nano text.html
Code:
<html>
<textarea rows="3" cols="20">
Enter text here...
</textarea>
</html>
# screen
# elinks text.hml
Enter "Ctrl-a" and then 'c' to open a second screen window.
# vi bla.txt
Enter 'i' to get into insert mode
Type some text in the editor, e.g.
Code:
blablabla
hahahaha
wawawa
Enter "Ctrl-a" then '[' (no 'Ctrl') to enter copy mode.
Enter "Ctrl-n" or "Ctrl-p" to get to the start line you want, then Space (no 'Ctrl') to start the copy.
Enter "Ctrl-n" or "Ctrl-p" to get to the end line you want, then Space (no 'Ctrl') to complete the copy.
Enter "Ctrl-a" then '0' (no 'Ctrl') to return to the first screen window.
Press Enter in the text box, then "Ctrl-a" then ']' (no 'Ctrl') to paste the text from the second window.
Screen also allow off-screen scrolling in copy mode using the same "Ctrl-n" or "Ctrl-p" keys.
Just remember not to press any other key,or it will be aborted.(Maybe "Ctrl-h" is permitted.)
(Must stay aware of the 'Ctrl' key toggle state.)
In this way I could even run 'ps' and copy offscreen process names like "/usr/local/kfmon/bin/kfmon" to the other window.
Enter "Ctrl-a" then 'd' (no 'Ctrl') to detach from the session.
Run KOReader.
From KOReader Terminal:
# screen -r
And you are back in!
"Ctrl-a" and then 'k' to kill window.
***
*UPDATE2 - LOWKEY PROFILES FOR MORE DISPLAY SPACE
$ nano -l fbkeyboard.c
Code:
76 int lowkey; // low key profile
...
97 int z;
...
312 lseek(fbfd, fblinelength * (fbheight - height * (6 + lowkey)), SEEK_SET);
313 write(fbfd, buf, buflen);
314 keyb_refresh(fbfd, fbheight - height * (6 + lowkey), 0, width, fbheight);
315 break;
...
395 void identify_touched_key(int x, int y, int *row, int *pressed)
396 {
397 z = ((0x10000 - y) / trowh);
398 if (z == (5 + lowkey)) {
399 *row = 0; // Esc, Tab, F10, etc
400 *pressed = x * 7 / 0x10000;
401 /* break; */
402 } else if (z == (4 + lowkey)) {
403 *row = 1; // q - p
404 *pressed = x * 10 / 0x10000;
405 /* break; */
406 } else if (z == (3 + lowkey)) {
407 *row = 1; // a - l
408 if (x > 0x10000 / 20 && x < 0x10000 * 19 / 20)
409 *pressed = 10 + (x * 10 - 0x10000 / 2) / 0x10000;
410 /* break; */
411 } else if (z == (2 + lowkey)) {
412 if (x < 0x10000 * 3 / 20) {
413 *row = 3;
414 *pressed = 0; // Left Shift
415 } else if (x < 0x10000 * 17 / 20) {
416 *row = 1; // z - m
417 *pressed = 19 + (x * 10 - 0x10000 * 3 / 2) / 0x10000;
418 } else {
419 *row = 3;
420 *pressed = 1; // Bcksp
421 }
422 /* break; */
423 } else if (z == (1 + lowkey)) {
424 *row = 4;
425 if (x < 0x10000 * 3 / 20)
426 *pressed = 99; // 123!@
427 else if (x < 0x10000 * 5 / 20)
428 *pressed = 0; // Left Alt
429 else if (x < 0x10000 * 15 / 20)
430 *pressed = 1; // Space
431 else if (x < 0x10000 * 17 / 20)
432 *pressed = 2; // Right Ctrl
433 else
434 *pressed = 3; // Enter
435 /* break; */
436 } else {
437 *row = 5; // cursor, Enter, Home, PgDn, etc
438 /* *pressed = 3 * y / (0x10000 - trowh * 5);
439 *pressed *= 3;
440 *pressed += 3 * x / 0x10000; */
441 /* break; */
442 }
443 }
...
629 while ((c = getopt(argc, argv, "d:f:r:l:h")) != (char) -1) {
...
645 case 'l':
646 errno = 0;
647 lowkey = strtol(optarg, &p, 10) % 3;
648 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
649 printf("Invalid numeric value for -l option\n");
650 exit(0);
651 }
652 break;
...
688 height = fbheight / (landscape ? (2 + lowkey) : (3 + lowkey)) / 5; // height of one row
689 trowh = height * 0x10000 / fbheight;
690 linelength = fblinelength;
691 buflen = linelength * (height * 5 + (1 + lowkey));
***
Now you can use the -l commandline argument for lower profile keyboard layouts, to get more display space:
# fbkeyboard2 -r 0 -l 0 -> normal width
# fbkeyboard2 -r 0 -l 1 -> low key width
# fbkeyboard2 -r 0 -l 2 -> extreme "loco" low key width
***
*UPDATE3 - ADDITIONAL COMMANDLINE OPTIONS
# fbkeyboard2 -h
usage: fbkeyboard2 [options]
possible options are:
-h: print this help
-d: set path to input device
-f: set path to ttf font file
-r: set rotation 0-3
-l: set lowkey profile 0-2
-x: set direction key acceleration factor 1-9 (default 4)
-b: set base interval 1-999 (default 100) in uS between any key presses
-a: set additional interval 1-999 (default 250) in mS between same key presses
-g: set grab input events 0-1
$ nano -l fbkeyboard.c
Code:
77 int acceleration = 4; // direction keys acceleration factor
78 int baseDelay = 100; // base keybounce delay(uS) any key
79 int additionalDelay = 250; // additional keybounce delay(mS) same key
80 int grabInput = 0; // grab input events
...
317 lseek(fbfd, fblinelength * (fbheight - height * (6 + lowkey - grabInput)), SEEK_SET);
318 write(fbfd, buf, buflen);
319 keyb_refresh(fbfd, fbheight - height * (6 + lowkey - grabInput), 0, width, fbheight);
...
403 if (z == (5 + lowkey - grabInput)) {
404 *row = 0; // Esc, Tab, F10, etc
405 *pressed = x * 7 / 0x10000;
406 /* break; */
407 } else if (z == (4 + lowkey - grabInput)) {
408 *row = 1; // q - p
409 *pressed = x * 10 / 0x10000;
410 /* break; */
411 } else if (z == (3 + lowkey - grabInput)) {
412 *row = 1; // a - l
413 if (x > 0x10000 / 20 && x < 0x10000 * 19 / 20)
414 *pressed = 10 + (x * 10 - 0x10000 / 2) / 0x10000;
415 /* break; */
416 } else if (z == (2 + lowkey - grabInput)) {
417 if (x < 0x10000 * 3 / 20) {
418 *row = 3;
419 *pressed = 0; // Left Shift
420 } else if (x < 0x10000 * 17 / 20) {
421 *row = 1; // z - m
422 *pressed = 19 + (x * 10 - 0x10000 * 3 / 2) / 0x10000;
423 } else {
424 *row = 3;
425 *pressed = 1; // Bcksp
426 }
427 /* break; */
428 } else if (z == (1 + lowkey - grabInput)) {
429 *row = 4;
...
468 int k;
...
521 if (pressed == 6) {
522 send_key(KEY_PAGEUP);
523 } else if (pressed == 2) {
524 for (k = 0; k < acceleration; k++)
525 send_key(KEY_UP);
526 } else if (pressed == 3) {
527 for (k = 0; k < acceleration; k++)
528 send_key(KEY_DOWN);
529 } else if (pressed == 4) {
530 for (k = 0; k < acceleration; k++)
531 send_key(KEY_LEFT);
532 } else if (pressed == 5) {
533 for (k = 0; k < acceleration; k++)
534 send_key(KEY_RIGHT);
535 } else {
...
625 char c;
626 while ((c = getopt(argc, argv, "d:f:r:l:x:b:a:g:h")) != (char) -1) {
627 switch (c) {
...
650 case 'x':
651 errno = 0;
652 acceleration = strtol(optarg, &p, 10) % 10;
653 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
654 printf("Invalid numeric value for -x option\n");
655 exit(0);
656 }
657 if (acceleration < 1 || acceleration > 9)
658 acceleration = 4;
659 break;
660 case 'b':
661 errno = 0;
662 baseDelay = strtol(optarg, &p, 10) % 1000;
663 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
664 printf("Invalid numeric value for -b option\n");
665 exit(0);
666 }
667 if (baseDelay < 1 || baseDelay > 999)
668 baseDelay = 100;
669 break;
670 case 'a':
671 errno = 0;
672 additionalDelay = strtol(optarg, &p, 10) % 1000;
673 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
674 printf("Invalid numeric value for -a option\n");
675 exit(0);
676 }
677 if (additionalDelay < 1 || additionalDelay > 999)
678 additionalDelay = 250;
679 break;
680 case 'g':
681 errno = 0;
682 grabInput = strtol(optarg, &p, 10) % 2;
683 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
684 printf("Invalid numeric value for -g option\n");
685 exit(0);
686 }
687 break;
688 case 'h':
689 printf("usage: %s [options]\npossible options are:\n -h: print this help\n -d: set path to input device\n -f: set path to ttf font file\n -r: set rotation 0-3\n -l: set lowkey profile 0-2\n -x: set direction key acceleration factor 1-9 (default 4)\n -b: set base interval 1-999 (default 100) in uS between any key presses\n -a: set additional interval 1-999 (default 250) in mS between same key presses\n -g: set grab input events 0-1\n",
690 argv[0]);
691 exit(0);
692 break;
...
787 if (grabInput == 1) {
788 ioctl(fdinput, EVIOCGRAB, (void*)1);
789 fprintf(stderr,"Grabbing input");
790 }
...
851 if (pressed != -1 && (pressed != oldpressed && (long)diffstamp.tv_usec > baseDelay) || (long)diffstamp.tv_usec > additionalDelay * 1000)
852 send_uinput_event(row, pressed);
853 pressed = -1;
...
870 fb_free();
871 if (grabInput == 1) {
872 ioctl(fdinput, EVIOCGRAB, (void*)0);
873 fprintf(stderr,"Releasing input");
874 }
So running "fbkeyboard2 -g 1" grabs input, as was discussed in this thread:
https://www.mobileread.com/forums/sh...d.php?t=358066
Now you have to exit "fbkeyboard2" by running "pkill fbkeyboard" since you don't have access to the NickelMenu at this point.
***
* (MINI)UPDATE4 - EXIT BY "Ctrl-Alt-x"
OK, now you can exit fbkeyboard2 by entering "Ctrl-Alt-x":
$ nano -l fbkeyboard.c
Code:
849 if (released)
850 identify_touched_key(x, y, &row, &pressed);
851 if (pressed != -1 && (pressed != oldpressed && (long)diffstamp.tv_usec > baseDelay) || (long)diffstamp.tv_usec > additionalDelay * 1000) {
852 if (layoutuse == 0 && ctrllock == 1 && altlock == 1 && row == 1 && pressed == 20) {
853 break;
854 } else {
855 send_uinput_event(row, pressed);
856 }
857 pressed = -1;
858 usleep(50000);
859 }
***
*UPDATE5 - USE POLLING TO REDUCE %CPU USAGE, KEYBOARD CLEARANCE COMMANDLINE OPTION, SET GRAB INPUT EVENTS COMMANDLINE OPTION TO NEED ONLY SPECIFY "-g" rather than "-g 1":
$ nano -l fbkeyboard.c
Code:
...
31 #include <poll.h>
...
82 int clearance = -1; // keyboard base clearance
...
317 case FB_ROTATE_CCW:
318 lseek(fbfd, fblinelength * (fbheight - height * ((clearance >= 0)? clearance + 5 : (6 + lowkey - ((grabInput == 1)? ((lowkey == 2)? 2 : 1) : 0)))), SEEK_SET);
319 write(fbfd, buf, buflen);
320 keyb_refresh(fbfd, fbheight - height * ((clearance >= 0)? clearance + 5 : (6 + lowkey - ((grabInput == 1)? ((lowkey == 2)? 2 : 1) : 0))), 0, width, fbheight);
321 break;
...
404 if (z == (4 + ((clearance >= 0)? clearance : 1 + lowkey - ((grabInput == 1)? ((lowkey == 2)? 2 : 1) : 0)))) {
...
408 } else if (z == (3 + ((clearance >= 0)? clearance : 1 + lowkey - ((grabInput == 1)? ((lowkey == 2)? 2 : 1) : 0)))) {
...
412 } else if (z == (2 + ((clearance >= 0)? clearance : 1 + lowkey - ((grabInput == 1)? ((lowkey == 2)? 2 : 1) : 0)))) {
...
417 } else if (z == (1 + ((clearance >= 0)? clearance : 1 + lowkey - ((grabInput == 1)? ((lowkey == 2)? 2 : 1) : 0)))) {
...
429 } else if (z == (0 + ((clearance >= 0)? clearance : 1 + lowkey - ((grabInput == 1)? ((lowkey == 2)? 2 : 1) : 0)))) {
...
603 int fbfd, fdcons;
604 struct pollfd fdinput[1];
605 int timeout_ms = 100000;
...
629 while ((c = getopt(argc, argv, "d:f:r:l:x:b:a:c:gh")) != (char) -1) {
...
683 case 'c':
684 errno = 0;
685 clearance = strtol(optarg, &p, 10) % 100;
686 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
687 printf("Invalid numeric value for -c option\n");
688 exit(0);
689 }
690 if (clearance < 0 || clearance > 99)
691 clearance = -1;
692 break;
693 case 'g':
694 grabInput = 1;
695 break;
696 case 'h':
697 printf("usage: %s [options]\npossible options are:\n -h: print this help\n -d: set path to input device\n -f: set path to ttf font file\n -r: set rotation 0-3\n -l: set lowkey profile 0-2\n -x: set direction key acceleration factor 1-9 (default 4)\n -b: set base interval 1-999 (default 100) in uS between any key presses\n -a: set additional interval 1-999 (default 250) in mS between same key presses\n -c: set base keyboard clearance 0-99 \n -g: set grab input events\n",
...
734 buflen = linelength * (height * 5 + 1);
...
746 if (clearance > (landscape ? (2 + lowkey) * 5 - 5 : (3 + lowkey) * 5 - 5)) clearance = (landscape ? (2 + lowkey) * 5 - 5 : (3 + lowkey) * 5 - 5);
...
760 if (device) {
761 if ((fdinput[0].fd = open(device, O_RDONLY)) == -1) {
762 perror("failed to open input device node");
763 exit(-1);
764 }
765 } else {
766 DIR *inputdevs = opendir("/dev/input");
767 struct dirent *dptr;
768 fdinput[0].fd = -1;
769 while ((dptr = readdir(inputdevs))) {
770 if ((fdinput[0].fd =
771 openat(dirfd(inputdevs), dptr->d_name,
772 O_RDONLY | O_NONBLOCK)) != -1
773 && ioctl(fdinput[0].fd, EVIOCGBIT(0, sizeof(key)),
774 &key) != -1 && key >> EV_ABS & 1)
775 break;
776 if (fdinput[0].fd != -1) {
777 close(fdinput[0].fd);
778 fdinput[0].fd = -1;
779 }
780 }
781 if (fdinput[0].fd == -1) {
782 fprintf(stderr,
783 "no absolute axes device found in /dev/input\n");
784 exit(-1);
785 }
786 }
787 if ((ioctl(fdinput[0].fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_x) == -1) ||
788 (ioctl(fdinput[0].fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_y) == -1)) {
789 perror("error: getting touchscreen size");
790 exit(-1);
791 }
...
839 fdinput[0].events = POLLIN;
840 while (!done) {
...
855 poll(fdinput, 1, timeout_ms);
856 released = check_input_events(fdinput[0].fd, &x, &y);
...
865 }
866 pressed = -1;
867 }
868 }
869 int i;
...
883 fb_free();
884 if (grabInput == 1) {
885 ioctl(fdinput[0].fd, EVIOCGRAB, (void*)0);
886 fprintf(stderr,"Releasing input");
...
Now %cpu usage drops when fbkeyboard2 not in use.
(Credit goes to Szybet post for that one,lol)
Also you can enter just "-g" (instead of "-g 1") as an option, e.g.:
# fbkeyboard2 -r 3 -l 2 -g
# fbkeyboard2 -h
usage: fbkeyboard2 [options]
possible options are:
-h: print this help
-d: set path to input device
-f: set path to ttf font file
-r: set rotation 0-3
-l: set lowkey profile 0-2
-x: set direction key acceleration factor 1-9 (default 4)
-b: set base interval 1-999 (default 100) in uS between any key presses
-a: set additional interval 1-999 (default 250) in mS between same key presses
-c: set base keyboard clearance 0-99
-g: set grab input events
For example, set keyboard at bottom:
# fbkeyboard2 -c 0 -g
Or set keyboard at top:
# fbkeyboard2 -c 99 -g
Set keyboard in middle:
# fbkeyboard2 -c 5 -g
(Not sure why anyone would want to do that, but who knows?)
Now try in combination with updated version of fbpad2 (previous post):
# . /korenv.sh
# fbpad2 -p 63 -s 37 /bin/sh 0</dev/tty1 &
# fbkeyboard2 -c 99 -g
Keyboard is at the top, terminal output at the bottom!
***
*UPDATE6 - ALLOW USER TO SET INPUT ORIENTATION FOR THEIR OWN DEVICE VIA "-x" AND "-y" COMMANDLINE OPTIONS.
(CHANGE DIRECTION KEY ACCELERATION COMMANDLINE OPTION "-x" TO "-m" FOR DIRECTION KEY MULTIPLICATION.):
$ nano -l fbkeyboard.c
Code:
...
82 int clearance = -1; // keyboard base clearance
83 int xtouch = -1; // x input touch orientation
84 int ytouch = -1; // y input touch orientation
85
...
379 if (xtouch < 0) {
380 switch (rotate) {
381 case FB_ROTATE_UR:
382 *x = 0x10000 - absolute_y * 0x10000 / theight;
383 break;
384 case FB_ROTATE_UD:
385 *x = 0x10000 - absolute_x * 0x10000 / twidth;
386 break;
387 case FB_ROTATE_CW:
388 *x = absolute_y * 0x10000 / theight;
389 break;
390 case FB_ROTATE_CCW:
391 *x = absolute_x * 0x10000 / twidth;
392 break;
393 }
394 } else if (xtouch == 0) {
395 *x = absolute_x * 0x10000 / twidth;
396 } else if (xtouch == 1) {
397 *x = 0x10000 - absolute_x * 0x10000 / twidth;
398 } else if (xtouch == 2) {
399 *x = absolute_y * 0x10000 / theight;
400 } else if (xtouch == 3) {
401 *x = 0x10000 - absolute_y * 0x10000 / theight;
402 }
403
404 if (ytouch < 0) {
405 switch (rotate) {
406 case FB_ROTATE_UR:
407 *y = absolute_x * 0x10000 / twidth;
408 break;
409 case FB_ROTATE_UD:
410 *y = 0x10000 - absolute_y * 0x10000 / theight;
411 break;
412 case FB_ROTATE_CW:
413 *y = 0x10000 - absolute_x * 0x10000 / twidth;
414 break;
415 case FB_ROTATE_CCW:
416 *y = absolute_y * 0x10000 / theight;
417 break;
418 }
419 } else if (ytouch == 0) {
420 *y = absolute_x * 0x10000 / twidth;
421 } else if (ytouch == 1) {
422 *y = 0x10000 - absolute_x * 0x10000 / twidth;
423 } else if (ytouch == 2) {
424 *y = absolute_y * 0x10000 / theight;
425 } else if (ytouch == 3) {
426 *y = 0x10000 - absolute_y * 0x10000 / theight;
427 }
428
429 oldstamp.tv_sec = newstamp.tv_sec;
...
558 if (pressed == 6) {
559 send_key(KEY_PAGEUP);
560 } else if (pressed == 2) {
561 for (k = 0; k < multidir; k++)
562 send_key(KEY_UP);
563 } else if (pressed == 3) {
564 for (k = 0; k < multidir; k++)
565 send_key(KEY_DOWN);
566 } else if (pressed == 4) {
567 for (k = 0; k < multidir; k++)
568 send_key(KEY_LEFT);
569 } else if (pressed == 5) {
570 for (k = 0; k < multidir; k++)
571 send_key(KEY_RIGHT);
572 } else {
573 send_key(keys[row][pressed]);
...
665 while ((c = getopt(argc, argv, "d:f:r:l:m:b:a:c:x:y:gh")) != (char) -1) {
...
729 case 'x':
730 errno = 0;
731 xtouch = strtol(optarg, &p, 10) % 4;
732 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
733 printf("Invalid numeric value for -x option\n");
734 exit(0);
735 }
736 break;
737 case 'y':
738 errno = 0;
739 ytouch = strtol(optarg, &p, 10) % 4;
740 if (errno != 0 || p == optarg || p == NULL || *p != '\0') {
741 printf("Invalid numeric value for -y option\n");
742 exit(0);
743 }
744 break;
745 case 'g':
746 grabInput = 1;
747 break;
748 case 'h':
749 printf("usage: %s [options]\npossible options are:\n -h: print this help\n -d: set path to input device\n -f: set path to ttf font file\n -r: set rotation 0-3\n -l: set lowkey profile 0-2\n -m: set direction key multiplication factor 1-9 (default 4)\n -b: set base interval 1-999 (default 100) in uS between any key presses\n -a: set additional interval 1-999 (default 250) in mS between same key presses\n -c: set base keyboard clearance 0-99 \n -x: set x touch orientation 0-3\n -y: set y touch orientation 0-3\n -g: set grab input events\n",
750 argv[0]);
751 exit(0);
752 break;
...
# fbkeyboard2 -h
usage: fbkeyboard2 [options]
possible options are:
-h: print this help
-d: set path to input device
-f: set path to ttf font file
-r: set rotation 0-3
-l: set lowkey profile 0-2
-m: set direction key multiplication factor 1-9 (default 4)
-b: set base interval 1-999 (default 100) in uS between any key presses
-a: set additional interval 1-999 (default 250) in mS between same key presses
-c: set base keyboard clearance 0-99
-x: set x touch orientation 0-3
-y: set y touch orientation 0-3
-g: set grab input events
-x and -y commandline options allow user to set input touch orientation for their own device if it differs from that of the Clara HD.
(The former -x direction key acceleration factor has been moved to -m direction key multiplication factor.)
x/y touch orientation
0: absolute_x * 0x10000 / twidth
1: 0x10000 - absolute_x * 0x10000 / twidth
2: absolute_y * 0x10000 / theight
3: 0x10000 - absolute_y * 0x10000 / theight;
default: -x 3 -y 0
# fbkeyboard2 -g -x 3 -y 0
(touch orientation is normal for the Clara HD)
# fbkeyboard2 -g -x 2 -y 0
(x-axis touch is reversed for the Clara HD)
# fbkeyboard2 -g -x 3 -y 0
(touch orientation is normal for the Clara HD)
# fbkeyboard2 -g -x 3 -y 1
(y-axis touch is reversed for the Clara HD)
# fbkeyboard2 -g -m 2
(direction key multiplication factor set to 2)
***
MAKE SHARED VERSION OF FBKEYBOARD2:
$ cd ..
$ cd FBInk-v1.25.0/
$ make shared
$ cd ..
$ cd fbkeyboard-master/
$ cp -r ../FBInk-v1.25.0/Release FBInk/
$ arm-kobo-linux-gnueabihf-gcc -o fbkeyboard2-shared -I../freetype-2.13.1/include/ -LFBInk/Release/ fbkeyboard.c draw.c libfreetype.a -lfbink
***
Don't forget that:
-fbpad with USB keyboard needs agetty started and stopped in order to not stall.
-fbkeyboard needs WiFi on (or USB networking connected), though no hotspot connection needed, in order to not eventually freeze.
***
$ zip -r fbkeyboard2.zip fbkeyboard2/
***