Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow mode-specific key and mouse bindings #426

Open
dev-zero opened this issue Mar 6, 2019 · 19 comments
Open

Allow mode-specific key and mouse bindings #426

dev-zero opened this issue Mar 6, 2019 · 19 comments

Comments

@dev-zero
Copy link

dev-zero commented Mar 6, 2019

I'm trying to setup the Logitech Spotlight presenter with pdfpc. The presenter itself is properly recognized by Linux as a mouse device which generates a LEFT and RIGHT key events with the control buttons.

The button to turn on the gyroscope-based mouse generates a mouse button 3 event as per xev:

ButtonPress event, serial 41, synthetic NO, window 0x7200001,
    root 0x296, subw 0x7200002, time 1217807330, (30,44), root:(3594,73),
    state 0x10, button 3, same_screen YES

EnterNotify event, serial 41, synthetic NO, window 0x7200001,
    root 0x296, subw 0x0, time 1217807330, (30,44), root:(3594,73),
    mode NotifyGrab, detail NotifyInferior, same_screen YES,
    focus YES, state 1040

KeymapNotify event, serial 41, synthetic NO, window 0x0,
    keys:  4294967190 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   

ButtonRelease event, serial 41, synthetic NO, window 0x7200001,
    root 0x296, subw 0x7200002, time 1217807394, (30,44), root:(3594,73),
    state 0x410, button 3, same_screen YES

LeaveNotify event, serial 41, synthetic NO, window 0x7200001,
    root 0x296, subw 0x0, time 1217807394, (30,44), root:(3594,73),
    mode NotifyUngrab, detail NotifyInferior, same_screen YES,
    focus YES, state 16

Using the binding mouse 3 switchMode pointer I can switch the mode to pointer while at the same time enabling the mouse. The problem is that it doesn't switch back to normal mode (and hide the pointer) when releasing the button again.

What I would need is something like:

mouse 3:down switchMode pointer
mouse 3:up switchMode normal

Plus maybe an option to not hide the mouse pointer on the presenter console when in normal mode to remember where I left the pointer.

An alternative to always switching modes could be to add a new command to change the opacity of the pointer.

Following the code I guess I would have to add a new attribute to the KeyDef type (and the BindTouple before including the respective config parsing) and then remove && button.type == Gdk.EventType.BUTTON_PRESS in the button_press implementation in src/classes/presentation_controller.vala?

@fnevgeny
Copy link
Member

fnevgeny commented Mar 6, 2019

This is just the first thought, but I am not sure that enabling binding to on/off button events is the right thing. What your presenter does is essentially (in the standard GUI terms) sending the mouse drag events, right? So probably a way to specify what to do on mouse drag would be the way to go.

An alternative to always switching modes could be to add a new command to change the opacity of the pointer.

That would be a dirty hack and rather a resource-hungry one at that...

@dev-zero
Copy link
Author

dev-zero commented Mar 6, 2019

This is just the first thought, but I am not sure that enabling binding to on/off button events is the right thing. What your presenter does is essentially (in the standard GUI terms) sending the mouse drag events, right? So probably a way to specify what to do on mouse drag would be the way to go.

hmm, I did some more testing and it seems that the device is a bit more complicated than I thought.

The button to enable the mouse has two modes: one is the click, which gives a ButtonPress/ButtonRelease with button 3. The other is press+hold at which point there is no Button-event, only the MotionNotify start to appear when moving the presenter and stop when releasing the button again.

ButtonPress event, serial 40, synthetic NO, window 0x7200001,
    root 0x296, subw 0x0, time 1225783166, (190,287), root:(2626,567),
    state 0x10, button 3, same_screen YES

ButtonRelease event, serial 40, synthetic NO, window 0x7200001,
    root 0x296, subw 0x0, time 1225783232, (190,287), root:(2626,567),
    state 0x410, button 3, same_screen YES

MotionNotify event, serial 40, synthetic NO, window 0x7200001,
    root 0x296, subw 0x0, time 1225785466, (189,287), root:(2625,567),
    state 0x10, is_hint 0, same_screen YES

MotionNotify event, serial 40, synthetic NO, window 0x7200001,
    root 0x296, subw 0x0, time 1225785485, (189,287), root:(2625,567),
    state 0x10, is_hint 0, same_screen YES

This means that easiest way to get it basically working is a toggleMode action. Then I could simply click once to enable the pointer, do a click+hold to drag it around and then click once again to switch back to normal.

@fnevgeny
Copy link
Member

fnevgeny commented Mar 6, 2019

The other is press+hold at which point there is no Button-event, only the MotionNotify start to appear when moving the presenter and stop when releasing the button again.

Well, isn't it exactly the same what normal mouse does?

@dev-zero
Copy link
Author

dev-zero commented Mar 6, 2019

The other is press+hold at which point there is no Button-event, only the MotionNotify start to appear when moving the presenter and stop when releasing the button again.

Well, isn't it exactly the same what normal mouse does?

Yes and no: on a mouse you have a ButtonDown event first, then the Motion events, then the ButtonRelease event, which gives you the drag action, right? Here it's just that while holding the button it acts as a normal mouse but you don't get the ButtonDown/Release events.

@fnevgeny
Copy link
Member

fnevgeny commented Mar 6, 2019

Here it's just that while holding the button it acts as a normal mouse but you don't get the ButtonDown/Release events.

I'm confused. When you press the button, how does the device know - will you just release it (i.e., intending to make a click and then it needs to send ButtonDown) or continue keeping it pressed (no ButtonDown now and no ButtonRelease later on)? Does it come with a crystal ball attached? :)

PS. It's so inconsiderate of Logitech not sending their new devices to pdfpc developers for testing :)

@dev-zero
Copy link
Author

dev-zero commented Mar 6, 2019

Here it's just that while holding the button it acts as a normal mouse but you don't get the ButtonDown/Release events.

I'm confused. When you press the button, how does the device know - will you just release it (i.e., intending to make a click and then it needs to send ButtonDown) or continue keeping it pressed (no ButtonDown now and no ButtonRelease later on)? Does it come with a crystal ball attached? :)

When I press+hold the button there is a small delay until the cursor starts moving. So my guess is that they have a built-in delay to either generate a ButtonDown+ButtonRelease event or start sending the movement events.

PS. It's so inconsiderate of Logitech not sending their new devices to pdfpc developers for testing :)

Given that Logitech does not care for Linux and that on Windows and macOS they have their own software taking care of it (and allowing for additional effects), I doubt they would :(

Anyway, my first attempt is something like:

diff --git a/src/classes/presentation_controller.vala b/src/classes/presentation_controller.vala
index 9ae2010..d8b355e 100644
--- a/src/classes/presentation_controller.vala
+++ b/src/classes/presentation_controller.vala
@@ -344,6 +344,7 @@ namespace pdfpc {
         }
 
         private AnnotationMode annotation_mode = AnnotationMode.NORMAL;
+        private AnnotationMode prev_annotation_mode = AnnotationMode.NORMAL;
 
         /**
          * Instantiate a new controller
@@ -610,6 +611,7 @@ namespace pdfpc {
                 return;
             }
 
+            this.prev_annotation_mode = this.annotation_mode;
             this.annotation_mode = mode;
 
             switch (mode) {
@@ -902,6 +904,10 @@ namespace pdfpc {
             this.set_mode(AnnotationMode.parse(mode_variant.get_string()));
         }
 
+        public void toggle_mode() {
+            this.set_mode(this.prev_annotation_mode);
+        }
+
         protected void add_actions() {
             add_action("next", this.next_page,
                 "Go to the next slide");
@@ -968,6 +974,8 @@ namespace pdfpc {
             add_action_with_parameter("switchMode", GLib.VariantType.STRING,
                 this.set_mode_to_string,
                 "Switch annotation mode (normal|pointer|pen|eraser)", "mode");
+            add_action("toggleMode", this.toggle_mode,
+                "Toggle between current and previous annotation mode");
 
             add_action("increaseSize", this.increase_size,
                 "Increase the size of notes|pointer|pen|eraser");

... only problem being that my toggle_mode doesn't get called anymore after entering pointer mode.

@fnevgeny
Copy link
Member

fnevgeny commented Mar 6, 2019

... only problem being that my toggle_mode doesn't get called anymore after entering pointer mode.

Yes, the configurable mouse bindings actually operate only in the "normal" mode, in others everything is hardcoded (including some keystrokes). To some extent it's reasonable, since e.g., the (standard) binding of mouse1 to next shouldn't affect one's ability to draw a curve in the drawing mode, etc...

I'm not sure what to do. One option is to introduce configurable context-sensitive (that's, mode-sensitive) bindings (either only mouse or mouse and keys alike). This is probably the most general approach, but would mean a rather substantial coding. Another option is to hardcode mouse3 to switch to the normal mode (when in any other mode). Which might come handy also with a normal mouse.

@dev-zero
Copy link
Author

dev-zero commented Mar 6, 2019

👍 🤣 thanks for the hint!

diff --git a/src/classes/presentation_controller.vala b/src/classes/presentation_controller.vala
index 9ae2010..088f0cf 100644
--- a/src/classes/presentation_controller.vala
+++ b/src/classes/presentation_controller.vala
@@ -770,6 +770,9 @@ namespace pdfpc {
                 drag_x=-1;
                 drag_y=-1;
 
+                if (event.button == 3) {
+                    this.set_normal_mode();
+                }
                 return true;
             });

@dev-zero
Copy link
Author

dev-zero commented Mar 8, 2019

Small update: on a newer kernel (4.20.12 than 4.12.14), the button to enable the mouse shows up as button 1 instead of button 3. Everything else remains the same.

@fnevgeny
Copy link
Member

fnevgeny commented Mar 8, 2019

Hmm, then you cannot use it for forward movement (when in the normal mode)??

@fnevgeny
Copy link
Member

fnevgeny commented Mar 8, 2019

OK, I see. The next/prev buttons send the keyboard events; the device is recognized as a keyboard/mouse combo.

@fnevgeny
Copy link
Member

fnevgeny commented Mar 9, 2019

Maybe instead of catering for this rather specific device, an external application should translate/map its events reasonably? Have you seen this project, BTW?

@dev-zero
Copy link
Author

Yes, I've seen that and almost tried it. But then I discovered that pdfpc has a pointer mode already built-in and decided it would be much easier to use, especially when it comes to mapping from a presenter console to the presentation screen.

In fact, the only thing missing to make it work is a (limited, but separate) action-support in pointer mode.

The alternative would be to setup some mapping as described in one of the following:

@fnevgeny fnevgeny changed the title Allow binding button press & release separately Allow mode-specific key and mouse bindings Mar 11, 2019
@fnevgeny
Copy link
Member

@dev-zero BTW, do you know how to send commands back to the presenter device (make it vibrate)? It would be possible to couple it with some timer events (which is what the vendor software does under Win/Mac, if I understand correctly).

@mayanksuman
Copy link

mayanksuman commented Oct 23, 2019

@fnevgeny Check this comment. It is possible to make the presenter vibrate by sending a special package on usb.

@fnevgeny
Copy link
Member

Thanks. It doesn't work for me, though, for a reason. Also, not applicable when connecting through BT directly...

@mayanksuman
Copy link

Thanks. It doesn't work for me, though, for a reason. Also, not applicable when connecting through BT directly...

It is not clear to me. Does it work on usb? The problem only remain if the device is used with BT.

The code is not supposed to work with BT as it uses libusb which do not support BT devices. I am currently working on hidapi based code that might work with BT also.

@fnevgeny
Copy link
Member

It is not clear to me. Does it work on usb?

No. Don't have it now with me, the error was something like command sequence not recognized.

@fnevgeny
Copy link
Member

The problem is that it doesn't switch back to normal mode (and hide the pointer) when releasing the button again.

Does your original problem boil down to switching off the cursor (after some period of inactivity)? That would make sense in general, irrespective of a specific input device used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants