jahnf / Projecteur

Linux Desktop Application for the Logitech Spotlight device (and similar devices) - Digital Laser Pointer
MIT License
379 stars 33 forks source link

Feature Request: Allow to modify the key-events sent by the spotlight device #43

Closed DenizThatMenace closed 4 years ago

DenizThatMenace commented 4 years ago

Problem

Some presentation tools (like reveal.js) allow to navigate through slides in multiple directions:

As Projecteur always sends <left> and <right> keystrokes, navigating through such slides skips a lot of slides.

Solution

Expose the selected key-settings to the GUI application and allow to change that with another key-combination. (Here, it would be <space> and <space>+<shift>.)


By the way: Thanks a lot for Projecteur. It is a cool tool.

jahnf commented 4 years ago

Thanks for the interest in this little project. Actually Projecteur does currently not send any keystrokes.

The device registers itself as a mouse and a keyboard. Right now Projecteur only monitors the relative mouse movement of the device to turn the spotlight on/off - not interfering any of the keystrokes or mouse events from the device. This is great because it's so simple and can work with other similar devices out of the box.

Custom keystrokes are planned, but it will probably need the integration of libusb and talking to the device directly (instead of only reading a Linux input device). This will then go hand in hand with the vibration support.

Probably in v0.8, but no promises :smiley:

DenizThatMenace commented 4 years ago

Thanks for the interest in this little project. Actually Projecteur does currently not send any keystrokes.

Thank you for your answer. I realized that after I wrote this feature-request.

The device registers itself as a mouse and a keyboard. Right now Projecteur only monitors the relative mouse movement of the device to turn the spotlight on/off - not interfering any of the keystrokes or mouse events from the device. This is great because it's so simple and can work with other similar devices out of the box.

Custom keystrokes are planned, but it will probably need the integration of libusb and talking to the device directly (instead of only reading a Linux input device). This will then go hand in hand with the vibration support.

Probably in v0.8, but no promises smiley

I was able to change the key-strokes it emits... or I did re-map them.
I used the guide from here.

Using an implementation which uses libusb is probably the cleaner and best solution, but maybe just wrapping and automating the steps from the mentioned guide might help, until the clean/correct solution is implemented?

The next section is a guide for how I was able to re-map the key-strokes my Spotlight emits.


The following command showed me the connected input devices:

xinput list

The interesting part of the output is this:

⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
.
.    ...
.
⎜   ↳ Logitech USB Receiver Consumer Control    id=23   [slave  pointer  (2)]
⎜   ↳ Logitech USB Receiver Mouse               id=26   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
     ...
    ↳ Logitech USB Receiver                     id=22   [slave  keyboard (3)]
    ↳ Logitech USB Receiver Consumer Control    id=24   [slave  keyboard (3)]
    ↳ Logitech USB Receiver System Control      id=25   [slave  keyboard (3)]

The Logitech USB Receiver virtual core keyboard with ID 22 is my Spotlight device.

I then used the following command to extract the current key-settings for the device:

xkbcomp -i 22 $DISPLAY /tmp/logitech_spotlight.xkb

I then just needed to adjust the extracted /tmp/logitech_spotlight.xkb file and re-enable it again for the device with the following command:

xkbcomp -i 22 /tmp/logitech_spotlight.xkb $DISPLAY

With the help of the following command I was able to find out what key-codes the device emits and which I had to change:

xev -event keyboard

In my case, the key-codes are 114 (for <right> arrow key) and 113 (for <left> arrow key).

And as my presentation uses Reveal.js, working navigation-keys are n (for next) and p (for previous). xev showed me that the key-code for n is 57 and for p is 33.

So in the extracted key-mapping file I just switches the meaning from these keys, as the following diff shows.

--- /tmp/logitech_spotlight.xkb
+++ /tmp/logitech_spotlight.xkb
@@ -26,7 +26,7 @@
     <AD07> = 30;
     <AD08> = 31;
     <AD09> = 32;
-    <AD10> = 33;
+    <LEFT> = 33;
     <AD11> = 34;
     <AD12> = 35;
     <RTRN> = 36;
@@ -50,7 +50,7 @@
     <AB03> = 54;
     <AB04> = 55;
     <AB05> = 56;
-    <AB06> = 57;
+    <RGHT> = 57;
     <AB07> = 58;
     <AB08> = 59;
     <AB09> = 60;
@@ -105,8 +105,8 @@
     <HOME> = 110;
       <UP> = 111;
     <PGUP> = 112;
-    <LEFT> = 113;
-    <RGHT> = 114;
+    <AD10> = 113;
+    <AB06> = 114;
      <END> = 115;
     <DOWN> = 116;
     <PGDN> = 117;

Applying this modified key-mappings works but does not persist a reboot (and probably not restarting the X-server). But at least it will work for my talk next week. :smile:

jahnf commented 4 years ago

Awesome, thanks for your detailed description. I guess button mappings for 'long presses' can't be done this way? Would you be interested in putting a shell script together for remapping that I can put in the readme / wiki?

DenizThatMenace commented 4 years ago

Awesome, thanks for your detailed description. I guess button mappings for 'long presses' can't be done this way?

To be honest, I do not know. But it would be great if the device would support that.

Would you be interested in putting a shell script together for remapping that I can put in the readme / wiki?

I can try to do that, but I guess I won't be able to do it before next week (due to the conference coming up where I am using Projecteur to present my talk :smile:).

jahnf commented 4 years ago

Thanks, that would be great. - Good luck with your talk (is it about CMake?) and just for safety make sure you have a Projecteur version with you as backup plan before the "Merge branch 'feature/follow-cursor-across-screens' into develop" (9882686b03bd1195e1b96dc66a47faed32f317ab). Just in case :) - since there are changes that affect how the screen is set. - Should work, but you never know.

DenizThatMenace commented 4 years ago

Thanks, that would be great. - Good luck with your talk (is it about CMake?)

Thank you. And yes, it is about CMake. :wink: (My talk's abstract)

and just for safety make sure you have a Projecteur version with you as backup plan before the "Merge branch 'feature/follow-cursor-across-screens' into develop" (9882686). Just in case :) - since there are changes that affect how the screen is set. - Should work, but you never know.

Actually, I am using your latest stable release version, Projecteur 0.5, which seems to not include that commit, when I am not mistaken.

jahnf commented 4 years ago

Thank you. And yes, it is about CMake

Very good, I think I have a wild mix of modern and traditional CMake in this project :laughing:

Actually, I am using your latest stable release version, Projecteur 0.5, which seems to not include that commit, when I am not mistaken.

Yes I am referring to changes on develop

DenizThatMenace commented 4 years ago

I already found the time to build a nice bash-script which does all these things automatically:

#!/bin/bash

## The Logitech Spotlight device's USB-receiver should be recognized as
## keyboard and mouse device when attached to your PC.  
## You can verify this by calling `xinput list` on the command-line.
## The output should contain three "Virtual core keyboard" devices
## whose names start with "Logitech USB Receiver". The one, which is
## exactly called this (without any further suffix) is the device for
## which this script modifies the key-mappings.
##
## The command `xev -event keyboard` can be used on the command-line to
## find out the key-codes emitted by the Logitech Spotlight. It is also
## helpful in finding out the key-codes of the keys to which you want
## to remap the button presses to.
##
##

## These are the key-codes for the keys to which the button presses
## will be remapped.  
## Adjust accordingly!
MAPPED_FORWARD_keycode=57   # 'n' key
MAPPED_BACKWARD_keycode=33  # 'p' key

## The following key-codes are the ones that are emitted by the
## Logitech Spotlight device. Should the emitted key-codes ever change,
## then you need to adjust these here!  
## In general, you should leave these untouched!
FORWARD_keycode=114
BACKWARD_keycode=113

## -------------------------------------------
## Remap the button presses to different keys:
## -------------------------------------------

## Retrieve the device ID of the Logitech Spotlight device.
DEVICE_ID=$(xinput list --id-only "Logitech USB Receiver")
EXIT_CODE=$?
if [[ ${EXIT_CODE} -ne 0 ]]; then
    exit ${EXIT_CODE}
fi

## The temporary files that will hold the extracted and modified
## key-settings of the Logitech Spotlight device and some log-output.
xkbfile=$(mktemp --tmpdir logitech_spotlight.xkb.XXXXXXXXX)
logfile=$(mktemp --tmpdir logitech_spotlight.log.XXXXXXXXX)

## Extract the key-mappings of the device and store them in the file.
xkbcomp -i ${DEVICE_ID} $DISPLAY ${xkbfile}

## Extract the key-codes section from the key-mappings file (with
## line-numbers prepended).
KEYCODES_SECTION=$(cat -n ${xkbfile} |
                   sed -n '/^[ ]\+[0-9]\+[\t]xkb_keycodes.* {$/,/}/p')
## Retrieve the current identifiers for the key-codes to which to remap.
MAPPED_FORWARD_id=$(echo "${KEYCODES_SECTION}" |
    sed -n "/^[ ]\+[0-9]\+[\t][ \t]*[<][^>]\+[>][ ]*=[ ]*${MAPPED_FORWARD_keycode};\$/s/^.*\([<][^>]*[>]\).*\$/\1/p")
MAPPED_BACKWARD_id=$(echo "${KEYCODES_SECTION}" |
    sed -n "/^[ ]\+[0-9]\+[\t][ \t]*[<][^>]\+[>][ ]*=[ ]*${MAPPED_BACKWARD_keycode};\$/s/^.*\([<][^>]*[>]\).*\$/\1/p")
## Retrieve the line-numbers of the key-codes emitted by the Logitech Spotlight device.
FORWARD_linenumber=$(echo "${KEYCODES_SECTION}" |
    sed -n "/^[ ]\+[0-9]\+[\t][ \t]*[<][^>]\+[>][ ]*=[ ]*${FORWARD_keycode};\$/s/^[ ]\+\([0-9]\+\).*/\1/p")
BACKWARD_linenumber=$(echo "${KEYCODES_SECTION}" |
    sed -n "/^[ ]\+[0-9]\+[\t][ \t]*[<][^>]\+[>][ ]*=[ ]*${BACKWARD_keycode};\$/s/^[ ]\+\([0-9]\+\).*/\1/p")

## Modify the key-mappings.
sed -i "${FORWARD_linenumber}s/[<][^>]\+[>]/${MAPPED_FORWARD_id}/" ${xkbfile}
sed -i "${BACKWARD_linenumber}s/[<][^>]\+[>]/${MAPPED_BACKWARD_id}/" ${xkbfile}

## Reload the modified key-mappings for the device and activate them.
xkbcomp -i ${DEVICE_ID} ${xkbfile} $DISPLAY 2>${logfile}
EXIT_CODE=$?
if [[ ${EXIT_CODE} -ne 0 ]]; then
    cat ${logfile}
    exit ${EXIT_CODE}
fi

## Remove the temporary files again.
rm ${xkbfile}
rm ${logfile}

It is quite lengthy but should be self-explanatory.

jahnf commented 4 years ago

Very nice, thank you :tada: .

After releasing 0.6, I will put it into the repo as util/helper-script until there is a way within Projecteur to assign key-events - if that is okay with you of course.

DenizThatMenace commented 4 years ago

After releasing 0.6, I will put it into the repo as util/helper-script until there is a way within Projecteur to assign key-events - if that is okay with you of course.

That's just fine.

jahnf commented 4 years ago

This feature, as well as #68 and #58 will be covered in #69

jahnf commented 4 years ago

@Bagira80 If you have a chance please check out the latest version on develop - Button mappings like you described in your initial request (e.g. for reveal.js) are now possible and directly configurable from within Projecteur.

DenizThatMenace commented 4 years ago

@jahnf Great work! :+1:

I tried it out and it works like a charm.

I was able to set different key-mappings for comfortably navigating through reveal.js presentations. In particular, mapping single-press, double-press, triple-press and even quadruple-press events worked for all three spotlight buttons.

However, long-press events I was not able to configure. Increasing the input sequence interval did not help with that.
Should configuring these be possible?

jahnf commented 4 years ago

Thank you for feedback and testing. :+1: About the long press: unfortunately this is currently not detectable with the hid input event. The device does not even send the button press event immediately, it is send together with the release event when you release the button.

This might be detectable with the hidraw/usb integration but that needs more investigation and testing. + Some reverse engineering the spotlight specific proprietary protocol. (That is also used for the vibration timer and other features)

jahnf commented 4 years ago

Closing this issue.
For the long press: @mayanksuman reported in #71 about the missing events for from the device itself. Like mentioned in the previous comment, that is something that most probably will need direct communication with the device. That is something that can be investigated when vibration timer support will be integrated. If there are bugs regarding the button mapping functionality please add them to issue #69