Bug 66658 - syndaemon should support disabling the pad when a TrackPoint is in use [+patch]
Summary: syndaemon should support disabling the pad when a TrackPoint is in use [+patch]
Status: RESOLVED WONTFIX
Alias: None
Product: xorg
Classification: Unclassified
Component: Input/synaptics (show other bugs)
Version: unspecified
Hardware: All Linux (All)
: medium enhancement
Assignee: Peter Hutterer
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 74544
  Show dependency treegraph
 
Reported: 2013-07-07 03:08 UTC by V. Martinez
Modified: 2014-03-12 07:51 UTC (History)
3 users (show)

See Also:
i915 platform:
i915 features:


Attachments
Syndaemon trackpoint monitoring (1.34 KB, patch)
2013-07-08 08:50 UTC, V. Martinez
no flags Details | Splinter Review
1-trackpoint-support (5.86 KB, patch)
2013-07-08 08:55 UTC, V. Martinez
no flags Details | Splinter Review
[minor] deleting commented code.. (1.34 KB, patch)
2013-07-08 08:56 UTC, V. Martinez
no flags Details | Splinter Review
test program for device idle counters (4.54 KB, text/plain)
2013-07-08 22:34 UTC, Peter Hutterer
no flags Details
Proposed patch for syndaemon (25.24 KB, patch)
2014-02-14 18:55 UTC, Lyude Paul
no flags Details | Splinter Review
Proposed patch for syndaemon (28.78 KB, patch)
2014-02-27 20:24 UTC, Lyude Paul
no flags Details | Splinter Review
Proposed patch for syndaemon (28.78 KB, patch)
2014-02-27 20:42 UTC, Lyude Paul
no flags Details | Splinter Review
Proposed patch for syndaemon (28.72 KB, patch)
2014-02-27 22:47 UTC, Lyude Paul
no flags Details | Splinter Review
Proposed patch for syndaemon (28.72 KB, patch)
2014-02-27 23:35 UTC, Lyude Paul
no flags Details | Splinter Review
0001-Add-support-for-monitoring-pointing-sticks.patch (29.05 KB, patch)
2014-02-28 06:49 UTC, Peter Hutterer
no flags Details | Splinter Review
Proposed patch for syndaemon (29.08 KB, patch)
2014-02-28 15:48 UTC, Lyude Paul
no flags Details | Splinter Review
0001-Add-support-for-monitoring-pointing-sticks.patch (30.21 KB, patch)
2014-03-03 00:55 UTC, Peter Hutterer
no flags Details | Splinter Review
0002-syndaemon-exit-if-the-device-idle-timer-failed-to-in.patch (1.01 KB, patch)
2014-03-07 05:43 UTC, Peter Hutterer
no flags Details | Splinter Review
0003-syndaemon-when-failing-to-find-the-default-trackstic.patch (5.64 KB, patch)
2014-03-07 05:46 UTC, Peter Hutterer
no flags Details | Splinter Review
Alternative to patching syndaemon (4.66 KB, patch)
2014-03-07 18:50 UTC, Lyude Paul
no flags Details | Splinter Review
Alternative to patching syndaemon (5.13 KB, patch)
2014-03-10 20:54 UTC, Lyude Paul
no flags Details | Splinter Review
Alternative to patching syndaemon [1/2] (4.30 KB, patch)
2014-03-11 00:44 UTC, Lyude Paul
no flags Details | Splinter Review
Alternative to patching syndaemon [2/2] (3.44 KB, patch)
2014-03-11 00:46 UTC, Lyude Paul
no flags Details | Splinter Review
Alternative to patching syndaemon [1/2] (3.66 KB, patch)
2014-03-11 23:25 UTC, Lyude Paul
no flags Details | Splinter Review
Alternative to patching syndaemon [2/2] (1.30 KB, patch)
2014-03-11 23:27 UTC, Lyude Paul
no flags Details | Splinter Review

Description V. Martinez 2013-07-07 03:08:37 UTC
IBM TrackPoint users (and similar) may sometimes want to disable their trackpad while the trackpoint is being used, in order to avoid erratic cursor movements from palms in contact with the surface. There have been a few requests (e.g. http://askubuntu.com/questions/181676/how-to-disable-touchpad-while-using-trackpoint-on-a-thinkpad).

This patch adds a new option (-T) to enable monitoring the TrackPoint device. Feel free to bury it if it doesn't meet any acceptance criteria...
Comment 1 Peter Hutterer 2013-07-07 23:24:34 UTC
I think you forgot to attach the patch :)
Comment 2 V. Martinez 2013-07-08 08:50:36 UTC
Created attachment 82171 [details] [review]
Syndaemon trackpoint monitoring

Well that was embarassing...
Comment 3 V. Martinez 2013-07-08 08:55:51 UTC
Created attachment 82173 [details] [review]
1-trackpoint-support
Comment 4 V. Martinez 2013-07-08 08:56:31 UTC
Created attachment 82175 [details] [review]
[minor] deleting commented code..
Comment 5 Peter Hutterer 2013-07-08 22:32:14 UTC
Comment on attachment 82173 [details] [review]
1-trackpoint-support

Review of attachment 82173 [details] [review]:
-----------------------------------------------------------------

I like the idea, the patch itself needs some work though:
* please double-check all indentations and spacing to match the rest of the file (4-space indentation, spaces around operators, etc)
* make the device variable, so that the trackpoint is the default but a user can supply another device name
* skip the device type check when searching for the device - the name is enough.
* CursorPosition should be a static struct, not a pointer (currently you don't free it anywhere either)

The approach itself works, but I think there's a better way. As of a few server versions ago, each device has it's own idle timer now. So what we should be doing here is monitor the idle counter on that device and determine activity based on that. We don't use the idle counter for keyboard activity because of the -K/-k flags but for this approach it would work nicely.

The side-effect of such an approach would be that we can allow multiple -T arguments, and it would work for both -R and polling mode. I'll attach a little sample script to show how idle timers can be used, that should give you enough of a start.
Comment 6 Peter Hutterer 2013-07-08 22:34:02 UTC
Created attachment 82201 [details]
test program for device idle counters
Comment 7 V. Martinez 2013-07-09 09:40:48 UTC
Thanks for the feedback (and the script). I'll work on that. 

I had initially tried a static struct but my C skills are quite rusty and wasn't sure what the best way to initialize (whilst not having to check for each property's value?) was... hence a null pointer, which I'm also not freeing (ouch!). I guess if I set the first property to -1, it would do the job. However, using the device idle time seems like a much better approach and makes this unnecessary.

I've just noticed there are quite a few number of device names:  
 > MatchProduct	"TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint|USB Trackpoint pointing device"

So now I'm hesitant to make any of these a default (I reckon any device that has "Trackpoint" in the name, but I'd rather not go for such a wildcard). I'll make the TTPS/2 Trackpoint the default for now and accept any other device name as a variable.

I'll put some more time on this later this week. Thanks for the help :)
Comment 8 Peter Hutterer 2013-07-09 22:36:19 UTC
(In reply to comment #7)
> I had initially tried a static struct but my C skills are quite rusty and
> wasn't sure what the best way to initialize (whilst not having to check for
> each property's value?)

static structs/variables are always initialized to zero, but you can do 
static CursorPosition a = {-1, -1}; as well.

> I've just noticed there are quite a few number of device names:  
>  > MatchProduct	"TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc.
> Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint|USB
> Trackpoint pointing device"
> 
> So now I'm hesitant to make any of these a default (I reckon any device that
> has "Trackpoint" in the name, but I'd rather not go for such a wildcard).
> I'll make the TTPS/2 Trackpoint the default for now and accept any other
> device name as a variable.

A wildcard is the ideal default, IMO because it can be documented well enough and it is just the default (for the flag). so syndaemon -T matches *TrackPoint* etc., -T "foo device" matches only "foo device". I think that's a good approach, don't you?
Comment 9 V. Martinez 2013-07-24 14:47:48 UTC
Apologies for the late reply.

I like the wildcard approach, it matches a wide range of devices. I've used "trackpoint"  (case-insensitive regex) to match the device name. One problem: the getopt() two colon syntax for optional arguments is a GNU extension - I believe this will be an issue on other platforms (bsd, darwin)? Having -T match *trackpoint* and -T "device-name" match "device-name", without getopt_long or getopt with ::, has proven non-trivial for me! (which says a lot of my C fluency).

The second issue is with the sync extensions. Every change in state in any of the buttons changes the device state:

> $ xinput query-state "TPPS/2 IBM TrackPoint"
> 2 classes :
> ButtonClass
> 	button[1]=up
> 	button[2]=up
> 	button[3]=down/down
> 	button[4]=up
> 	button[5]=up
> 	button[6]=up
> 	button[7]=up
> ValuatorClass Mode=Relative Proximity=In
> 	valuator[0]=446
> 	valuator[1]=1489

(unless there's a way to watch certain values of the device only, maybe via XSyncWaitCondition?)

So, that leaves me more or less where I was. I've made the changes suggested in trackpoint_activity() and I'm using regcomp/regexec to match the device name.
Comment 10 Peter Hutterer 2013-07-25 00:13:34 UTC
the last paragraph of the getopt man page DESCRIPTION section may help (just above getopt_long). If the first character of optstring is ":", then getopt returns ':' if an argument is missing. Look at the man page example, change optstring to ":nt:" and then add               
    case ':':
         printf("missing argument for: %c\n", optopt);
         break;
This handles the case we need, without needing GNU extensions. Hope that makes it clearer


(In reply to comment #9)
> The second issue is with the sync extensions. Every change in state in any
> of the buttons changes the device state:
> 
> (unless there's a way to watch certain values of the device only, maybe via
> XSyncWaitCondition?)

I'm not sure I understand the question here. each device has an idlecounter that is reset as soon as the device sends events. for this here to work is you'd put a negative transition counter on the trackpoint and disable the touchpad whenever the idle counter hits 0. and then re-enable it whenever the idle counter goes past the timeout (positive transition). Is that what you're doing at the moment? If you're unsure, attach the patch(es) you already have and I can have a look.
Comment 11 Lyude Paul 2014-02-14 18:55:55 UTC
Created attachment 94095 [details] [review]
Proposed patch for syndaemon

Proposed patch for adding trackpoint handling to syndaemon.
Depends on the other patches in #74544 to build properly.
Comment 12 Peter Hutterer 2014-02-16 22:33:57 UTC
Comment on attachment 94095 [details] [review]
Proposed patch for syndaemon

Review of attachment 94095 [details] [review]:
-----------------------------------------------------------------

Thanks for the patch! A few comments, see below:

You can skip the configure.ac bit. libXext is pulled in by libXi which is unconditional. It'd be enough to just add 'xext' explicitly to the PKG_CHECK_MODULES(XI... line.
That also means you can skip the #ifdefs for sync.h, it's available in every version we depend on.

Adding trackpoint monitoring to the non-record code would be simple enough too - just add a XPending() XNextEvent() before/after keyboard_activity() and handle it like with the xrecord parts.

For the select code, please calculate max_fd first instead of that ternary condition. Since the fd's don't change anyway, this will make the code easier to read.
In the alarm event handling code, I'd like an if condition for the second alarm too and an error if neither is hit, because that would indicate a bug that shouldn't happen.

pstick_name should be const char* to avoid errors.

+ set_idle_state_option(enum TouchpadIdleMode mode, const char * state) 
why not let that return the idle mode (or -1 on error), rename it to "..parse..." and the code would be
  idle_state[KeyboardIdle] = parse_idle_mode(argv[optind]);
I think that's easier to understand.

+ if (pstick_id == 0) {
just print an error of ("couldn't find pointing stick %s", pstick_name)

I wonder if it'd be simpler to keep two idle state variables for keyboard and pstick and then calculate the touchpad mode based on them. So instead of set_touchpad_mode(KeyboardIdle), you'd have
   tp_state[KeyboardIdle] = Idle;
   update_touchpad_state();
And in there you look at both values and decide on the actual state we want. This would provide us with a nice matrix of what to set when which is a lot easier follow (and document :) than the current code.

Other general notes:
- commit messages should generally be as an action, i.e. "Add support for monitoring...", since that's what the patch does. Minor nitpick, not the end of the world. We do require you sign-off your patch though
- I'm beginning to think we should add proper option parsing instead of a quite confusing array of shortopts. Something like --monitor=keyboard,trackstick or so would be a lot more obvious that knowing that -P disables -M unless -R...
- I'd make the -I default time to be identical to the -i time instead of a separate default. I'm not sure we even need a separate -I, at least not for now. Benjamin mentioned in an email that we probably need to make the trackstick mode without a timeout - i.e. it stays on until the touchpad is used as touchpad again (would require some more driver cooperation). So for now, I'd say take the -I parts out and just re-use the keyboard idle time, we can sort the rest out later
Comment 13 Lyude Paul 2014-02-19 14:20:00 UTC
(In reply to comment #12)
> Comment on attachment 94095 [details] [review] [review]
> Proposed patch for syndaemon
> 
> Review of attachment 94095 [details] [review] [review]:
> -----------------------------------------------------------------
> 
> Thanks for the patch! A few comments, see below:
> 
> You can skip the configure.ac bit. libXext is pulled in by libXi which is
> unconditional. It'd be enough to just add 'xext' explicitly to the
> PKG_CHECK_MODULES(XI... line.
> That also means you can skip the #ifdefs for sync.h, it's available in every
> version we depend on.
> 
> Adding trackpoint monitoring to the non-record code would be simple enough
> too - just add a XPending() XNextEvent() before/after keyboard_activity()
> and handle it like with the xrecord parts.
> 
> For the select code, please calculate max_fd first instead of that ternary
> condition. Since the fd's don't change anyway, this will make the code
> easier to read.
> In the alarm event handling code, I'd like an if condition for the second
> alarm too and an error if neither is hit, because that would indicate a bug
> that shouldn't happen.
> 
> pstick_name should be const char* to avoid errors.
> 
> + set_idle_state_option(enum TouchpadIdleMode mode, const char * state) 
> why not let that return the idle mode (or -1 on error), rename it to
> "..parse..." and the code would be
>   idle_state[KeyboardIdle] = parse_idle_mode(argv[optind]);
> I think that's easier to understand.
> 
> + if (pstick_id == 0) {
> just print an error of ("couldn't find pointing stick %s", pstick_name)
> 
> I wonder if it'd be simpler to keep two idle state variables for keyboard
> and pstick and then calculate the touchpad mode based on them. So instead of
> set_touchpad_mode(KeyboardIdle), you'd have
>    tp_state[KeyboardIdle] = Idle;
>    update_touchpad_state();
> And in there you look at both values and decide on the actual state we want.
> This would provide us with a nice matrix of what to set when which is a lot
> easier follow (and document :) than the current code.
> 
> Other general notes:
> - commit messages should generally be as an action, i.e. "Add support for
> monitoring...", since that's what the patch does. Minor nitpick, not the end
> of the world. We do require you sign-off your patch though
> - I'm beginning to think we should add proper option parsing instead of a
> quite confusing array of shortopts. Something like
> --monitor=keyboard,trackstick or so would be a lot more obvious that knowing
> that -P disables -M unless -R...
> - I'd make the -I default time to be identical to the -i time instead of a
> separate default. I'm not sure we even need a separate -I, at least not for
> now. Benjamin mentioned in an email that we probably need to make the
> trackstick mode without a timeout - i.e. it stays on until the touchpad is
> used as touchpad again (would require some more driver cooperation). So for
> now, I'd say take the -I parts out and just re-use the keyboard idle time,
> we can sort the rest out later

Regarding the changes you want, I'll fix up the patch and resubmit it asap.
Regarding the options, yeah, I agree we should add some proper functions. Once I fix up the original patch, I'll work on adding that in a subsequent patch (or I can work it into this patch if you want).
Comment 14 Lyude Paul 2014-02-27 20:24:35 UTC
Created attachment 94850 [details] [review]
Proposed patch for syndaemon

Adds pointing stick support to syndaemon.
Comment 15 Lyude Paul 2014-02-27 20:42:56 UTC
Created attachment 94851 [details] [review]
Proposed patch for syndaemon

Updated patch to be against latest master
Comment 16 Lyude Paul 2014-02-27 22:47:20 UTC
Created attachment 94854 [details] [review]
Proposed patch for syndaemon

Used the wrong timeout value with poll(), causing it to return instantly. Somehow I managed not to notice this when I was testing the changes. Fixed now.
Comment 17 Lyude Paul 2014-02-27 23:35:53 UTC
Created attachment 94855 [details] [review]
Proposed patch for syndaemon

Please excuse me, this sort of thing usually doesn't happen
Fixed -P only working if -M was enabled.
Comment 18 Peter Hutterer 2014-02-28 06:49:13 UTC
Created attachment 94858 [details] [review]
0001-Add-support-for-monitoring-pointing-sticks.patch

I figured it's easier and quicker if I just hack a bit instead of trying to explain everything I wanted :)

Here's a new diff, changes to your last version:
* re-localised a few variables that you made global
* changed tp_state and last_tp_state to is_idle and was_idle, makes it easier to read (IMO, anyway)
* changed update_touchpad_state() to check all permutations, I find this easier to read
* extra check to ignore non-alarm events
* fixed the sleep() back to usleep(). sleeping for 200s is not useful ;)
* fixed a crasher if -T was given without an option
* removed a hunk of duplicate code in main(), looked like a copy/paste error
* moved setup_xsync to before issuing the actual counters
* unconditionally check for alarm events - the pollfd is the same that xlib uses, so Xlib may read the events off the fd to get to the XQueryKeymap replies. Then poll won't trigger, so we never notice the trackstick movements.

I've tested this in normal mode, but still needs more testing, especially in record mode (haven't tested that at all yet). Please give it a try
Comment 19 Lyude Paul 2014-02-28 15:48:20 UTC
Created attachment 94895 [details] [review]
Proposed patch for syndaemon

Looks like in the ternary statement on line 674 you forgot to change that when you changed tp_state to is_idle, so it was only setting the timeout when there wasn't activity and as a result getting stuck on mode 1. Fixed that in the patch, other then that it seems to work perfectly on my system.
Comment 20 Peter Hutterer 2014-03-03 00:55:40 UTC
Created attachment 94995 [details] [review]
0001-Add-support-for-monitoring-pointing-sticks.patch

Two minor changes: the timespec handling wasn't correct for some cases, added helper functions to handle this for us. And replaced a if condition with the #define max()

Otherwise it seems to work fine here.
Comment 21 Peter Hutterer 2014-03-07 05:43:58 UTC
Created attachment 95285 [details] [review]
0002-syndaemon-exit-if-the-device-idle-timer-failed-to-in.patch

will be squashed with the other patch, but separate to make for an easier review.
Comment 22 Peter Hutterer 2014-03-07 05:46:27 UTC
Created attachment 95286 [details] [review]
0003-syndaemon-when-failing-to-find-the-default-trackstic.patch

Don't fail when we don't find the default trackstick. This makes starting syndaemon in a generic manner easier, since can just provide -P without having to check first if a trackstick is present.
Comment 23 Lyude Paul 2014-03-07 18:50:49 UTC
Created attachment 95313 [details] [review]
Alternative to patching syndaemon

Fixes the top soft button behavior, making TrackPoints without physical buttons easily usable without requiring syndaemon.
Comment 24 Peter Hutterer 2014-03-10 01:27:44 UTC
GNOME bug filed here: https://bugzilla.gnome.org/show_bug.cgi?id=726011
Comment 25 Lyude Paul 2014-03-10 20:54:35 UTC
Created attachment 95552 [details] [review]
Alternative to patching syndaemon

Inhibits movements by changing the use_cumulative_coords variable instead of running a check when ignore_motion is set.
Comment 26 Lyude Paul 2014-03-11 00:44:18 UTC
Created attachment 95564 [details] [review]
Alternative to patching syndaemon [1/2]

Split the commit into two before applying some other changes at the request of whot
Comment 27 Lyude Paul 2014-03-11 00:46:17 UTC
Created attachment 95565 [details] [review]
Alternative to patching syndaemon [2/2]

Now ignores movement starting from the top soft button area regardless of where it ends, in case the user accidentally moves their finger outside of the top soft button area when making a click with their trackpoint. Idea originally from Hans.
Comment 28 Lyude Paul 2014-03-11 23:25:43 UTC
Created attachment 95627 [details] [review]
Alternative to patching syndaemon [1/2]

Rebased against lastest upstream
Comment 29 Lyude Paul 2014-03-11 23:27:43 UTC
Created attachment 95629 [details] [review]
Alternative to patching syndaemon [2/2]

Changed back to original behavior with ignoring movement starting in the top soft buttons area at the request of Hans de Geode. Also rebased against the latest upstream master.
Comment 30 Peter Hutterer 2014-03-12 07:51:02 UTC
with current git master 17bbcad28000bbd896a33047c0720ada89e05f5d no patches to syndaemon should be necessary. I'm going to close this bug as WONTFIX, we'll re-open if the current solution proves unworkable.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.