talonhub / community

Voice command set for Talon, community-supported.
MIT License
643 stars 783 forks source link

Setting to allow pop to click without eye tracker #755

Closed splondike closed 1 year ago

splondike commented 2 years ago

Some Talon users don't have an eye tracker but would still like to use pop to click. For example they might like to use the mouse or trackpad to reposition the cursor, but avoid the strain of pressing to click or repeatedly saying 'touch'.

This issue is to allow this use case while maintaining the existing functionality.

The proposal is to change the type of the 'mouse_enable_pop_click' setting to a string. The following values would be accepted: 'off', 'with_tracker', 'on'. 'on' allows clicking at all times. 'with_tracker' is the existing control mouse functionality. The strings '0' and '1' would map to 'off' and 'with_tracker' to maintain backwards compatibility. The 'mouse_enable_pop_stops_scroll' setting would stay as is.

pokey commented 2 years ago

So is this one just waiting for someone to implement it?

timo commented 2 years ago

i would like to suggest making it easier to get any one of the sixty bajillion combinations of options:

in the last few weeks we've had a whole lot of questions about this, and each had a different desired behaviour.

we ought to utilise the settings system to the biggest extent possible as well, rather than asking users to modify code (seems obvious?)

There is already a pull request to turn on unconditional pop-to-click. It doesn't have a way to influence whether sleep mode turns pop-to-click off. That is currently implemented by sleep_mode.talon setting that to 0, which is not as user-configurable as I would like.

Thoughts?

pokey commented 2 years ago

So maybe we want to have one boolean setting for each of your bullet points, saying whether the given condition is required for pop to click to be on? Eg pop_to_click_requires_eyetracker, pop_to_click_disabled_on_sleep, pop_to_click_requires_control_mouse? Then the impl just returns false if any of these settings are true but their condition isn't met

I guess we'd also want a setting pop_to_click_disabled that could be used to turn it off entirely

splondike commented 2 years ago

I haven't been closely following the pop+click discussions in Slack; but it sounds like Timo has! I'd be up for a bunch of boolean operations.

We could keep the existing 'mouse_enable_pop_click' setting where now '0' would be off and '1' would be fully enabled. We'd also have the new setting 'mouse_pop_to_click_requires_eyetracker' which would default to '1'. In this way the behaviour of the existing setting would have the same effect while allowing for more detailed control via the new settings (which could all default to '0').

pokey commented 2 years ago

Sounds good. What do you mean by "fully" when you say "1 would be fully enabled", though?

splondike commented 2 years ago

Badly phrased that, I just mean that the logic would be something like the following:

def allow_pop_click():
  if mouse_enable_pop_click == 1:
    if mouse_pop_to_click_requires_eyetracker == 1:
      return is_eyetracker_enabled()
    elif is_wheel_gaze_mode():
      return mouse_allowed_in_wheel_gaze == 1
    elif ...:
      ...
    else:
      return True
  else:
     return False

That is if the mouse_enable_pop_click setting is 1 then we go through the logic of all the other specific checks.

pokey commented 2 years ago

I don't think that logic is quite right. I believe it should be something like:

def allow_pop_click():
    return (
        pop_to_click_enabled == 1 and
        (not pop_to_click_requires_eyetracker or is_eyetracker_enabled()) and
        (not pop_to_click_disabled_in_wheel_gaze or not is_wheel_gaze_mode()) and
        (not pop_to_click_disabled_on_sleep or mode != "sleep") and
        (not pop_to_click_requires_control_mouse or is_control_mouse())
    )
knausj85 commented 2 years ago

Would it be better to create an interim user.pop action that could be overridden per-context?

pokey commented 2 years ago

Interesting idea. Probably the most flexible, but puts more burden on the user, for something that I'd imagine even non-technical users will encounter. I guess we could have some example templates in the wiki or something?

codecat555 commented 2 years ago

It's not necessarily an either or type of thing, is it? Why not do both?

pokey commented 2 years ago

Fair enough. Then when we get to the many-settings version that would just go into the default action impl that is enabled in global context?

codecat555 commented 2 years ago

I guess so, I haven't really looked at the different use cases and how they fit together. It just seemed to me that a generic user.pop action and a unconditional pop setting were both useful and not mutually exclusive.

rntz commented 2 years ago

I think there's three reasonable options here:

  1. Have a user.pop_to_click setting that's a string indicating when popping clicks. PRO: simple for end-users. CON: we have to figure out when people might want popping to click, not as flexible.

  2. Have a user.pop_to_click setting that's a boolean which, if true, means popping clicks. Then we can set this setting conditionally in various contexts; e.g. make it true when eye-tracking is active, or whenever we're not asleep. PRO: simple & flexible. CON: slightly less user-friendly, no single central global setting to adjust.

  3. Have an overrideable user.pop action. PRO: maximum flexibility, makes it easy to make pop do things other than clicking. CON: even more annoying to customize for end-users.

Votes? I prefer (2).

rntz commented 2 years ago

votes for option (1): a string setting indicating when popping clicks.

rntz commented 2 years ago

votes for option (2): a boolean setting which makes popping click when true, overridden contextually

rntz commented 2 years ago

votes for option (3): a contextually overrideable user.pop() action

ym-han commented 1 year ago

Btw one way to potentially make it easier for the end user to adjust the conditional settings for option 2 (and really for anything that might seem to involve a lot of 'if' statements) might be to use a decision table (https://www.hillelwayne.com/post/decision-tables/).

So, e.g., you could have a table in Markdown (or in a GUI) whose columns would include the various contexts ("asleep", "eye tracking active", etc), along with a column for user.pop_to_click. And then that table could be auto-converted to a set of Python if statements with a tool like https://github.com/smucclaw/dmnmd

knausj85 commented 1 year ago

addressed with https://github.com/knausj85/knausj_talon/pull/1139