View Single Post
Old 01-03-2024, 08:27 PM   #12
elinkser
Groupie
elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.elinkser has survived committing the World's Second Greatest Blunder.
 
Posts: 185
Karma: 146236
Join Date: Oct 2022
Device: Kobo Clara HD
FBKEYBOARD2 - improved key mappings + rotate modes

***

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/


***
Attached Files
File Type: zip fbkeyboard2.zip (462.1 KB, 33 views)
File Type: zip shared.zip (499.0 KB, 141 views)

Last edited by elinkser; 01-26-2024 at 06:42 PM. Reason: copy, lowkey,screen+exit+poll,clearance+touch,shared update fbpad2
elinkser is offline   Reply With Quote