Binding to multiple button clicks - hammerspoon

To bind to the 1 key I use:
hs.hotkey.bind(hyper, '1'
How to bind to multiple presses of 1 key? Something like:
hs.hotkey.bind(hyper, '1+1'
Reading the documentation, this functionality is not mentioned.
By multiple presses I mean press 1 twice to run some code and press 1 three times to run a separate piece of code.

You're going to have to implement this yourself. Here's a basic summary of how to accomplish this:
Start a timer from zero, and set a flag for the first press initially to false, which indicates the first press has not happened yet
Observe and watch keypresses with hs.eventtap, specifically hs.eventtap.event.types.keyPress
When the event (keyPress) happens, check if the key pressed was the correct key
If it was the right key, check if it's the second press and if it was in time, if it wasn't in time or was not the second press then set the timer to the current time and first flag to true
If it was the second press and was in time, then execute our handler and reset timer and first flag
If it wasn't the right key then reset the timer and first flag
Translated into code, this is what is could look like (I'm not a Lua expert). Note that the flags could be implemented as booleans here, or as an internal table holding keypresses so far which you could check:
local timer = require("hs.timer")
local eventtap = require("hs.eventtap")
local keycodes = require("hs.keycodes")
local events = eventtap.event.types --all the event types
timeFrame = 1 --this is the timeframe in which the second press should occur, in seconds
key = 50 --the specific keycode we're detecting, in this case, 50
--print(keycodes.map["`"]) you can look up the certain keycode by accessing the map
function twoHandler()
hs.alert("Pressed ` twice!") --the handler for the double press
end
function correctKeyChecker(event) --keypress validator, checks if the keycode matches the key we're trying to detect
local keyCode = event:getKeyCode()
return keyCode == key --return if keyCode is key
end
function inTime(time) --checks if the second press was in time
return timer.secondsSinceEpoch() - time < timeFrame --if the time passed from the first press to the second was less than the timeframe, then it was in time
end
local pressTime, firstDown = 0, false --pressTime was the time the first press occurred which is set to 0, and firstDown indicates if the first press has occurred or not
eventtap.new({ events.keyDown }, function(event) --watch the keyDown event, trigger the function every time there is a keydown
if correctKeyChecker(event) then --if correct key
if firstDown and inTime(pressTime) then --if first press already happened and the second was in time
twoHandler() --execute the handler
elseif not firstDown or inTime(pressTime) then --if the first press has not happened or the second wasn't in time
pressTime, firstDown = timer.secondsSinceEpoch(), true --set first press time to now and first press to true
return false --stop prematurely
end
end
pressTime, firstDown = 0, false --if it reaches here that means the double tap was successful or the key was incorrect, thus reset timer and flag
return false --keeps the event propogating
end):start() --start our watcher
I've commented the code line-by-line for a better understanding. If you want to detect 3 or 4 or some other arbitrary N number of presses, just set flags for N - 1 presses and add a few checks, but it's unusual to have key combinations that take more than 2 successive presses. It does seem a little verbose, but AFAIK this is how you do it. To avoid duplicate code and boilerplate, try putting this in a class-like structure or a module so that you can reuse code.
As for executing a different handler for 2 successive presses, or 3 successive presses, that would be a little more hacky since you would have to wait the whole timeframe before knowing if the user will press again to know which handler to execute. That would cause a slight delay and a bad user experience, I would suggest against that, though you could probably implement that by refactoring the code and doing some more checks such as if it's the timeframe and the first flag was triggered, then execute the handler for one press.

You can not bind all keys or multiple keys with bind. Instead you can use this function: http://www.hammerspoon.org/docs/hs.eventtap.html#keyStroke
So the most straight forward programming language agnostic approach is as follows:
Call your function for any key stroke.
Within the function keep a static instance variable that will keep previous key strokes.
As the first task of your function append the new coming character to that variable.
Check the last 3 characters if they are the desired "11" string.
Extra for extreme conditions:
If the variable length pass a certain point reduce it to length 1 so that it does not keep unnecessary place in memory.

A solution for n keypresses
Very late to the party but there's little to no info on this, so I thought I should really put this here considering this is one of the only search results for this.
My solution is a bit more elegant then some others (in my opinion); there are definitely some things that could be improved about it but I'm not really familiar enough with Lua or Hammerspoon to fix them.
It should work to assign a shortcut to as many consecutive keypresses as you want.
Read the code comments for an explanation of how it works. I've tried to be as detailed as possible, in an effort to make it more beginner friendly for those that don't know much about coding and those that aren't that familiar with Lua or Hammerspoon (like me).
require("hs.timer") -- Load timer module, used for timing
keyDownCount = 0 -- Keypress counter, used later in the program to store the number of times the key has been pressed
keyMultipressGapTime = 0.3 -- Max time between consecutive keypresses, used to determine when the user has stopped pressing the key
keyMaxPressCount = 3 -- Max number of key presses
testKeyCode = 18 -- Key code to bind shortcut to (in this case the 1 key)
-- READ CheckKeyDownCount FUNCTION CODE (BELOW) FIRST
-- Function to press a key with code
-- This isn't completely intuitive so I'm including it
-- Im sure there's a better way of doing this but this is what I figured out
function PressKey(keyCode)
keyDown = hs.eventtap.event.newKeyEvent(keyCode, true) -- Create new keydown event using the keycode passed in the keycode argument
keyDown:setProperty(hs.eventtap.event.properties.eventSourceUserData, 1) -- Sets user data byte of keydown event to 1, used later to prevent keydown event handler from self triggering
keyDown:post() -- Fire keydown event
hs.eventtap.event.newKeyEvent(keyCode, false):post() -- Create and fire keyup event using the keycode passed in the keycode argument
end
-- READ EVENT HANDLER CODE (BELOW) FIRST
-- Function to check the number of times the key was pressed and act accordingly
-- Pretty self explanatory
function CheckKeyDownCount()
CheckKeyDownCountTimer:stop() -- Stops keydown timer so it doesn't repeat
-- There may be a better way of doing this but I can't find a way to creating and restarting a non repeating timer without creating a whole new timer object every time
if keyDownCount == 1 then -- Perform action based on number of keypresses
hs.alert("Pressed once")
PressKey(testKeyCode)
elseif keyDownCount == 2 then
hs.alert("Pressed twice")
elseif keyDownCount == 3 then
hs.alert("Pressed thrice")
end
keyDownCount = 0 -- Reset keypress counter
end
CheckKeyDownCountTimer = hs.timer.new(keyMultipressGapTime, CheckKeyDownCount) -- Creates timer for determining when the user has stopped pressing the key
-- Time interval is set to the max time between consecutive keypresses
-- Runs the CheckKeyDownCount function at end of time interval
-- IMPORTANT: Time interval automatically resets when timer is stopped and started
-- Creates keydown event handler
-- FOR BEGINNERS: An event handler is a routine that runs when triggered by an event (kind of like an interrupt if you know what that is), normally they call a function, like below
-- FOR BEGINNERS CONTINUED: The timer above is also an event handler of sorts, with the event being the end of the time interval, event handlers are very useful because they allow asynchronous code execution
-- FOR BEGINNERS CONTINUED: In this case asynchronous code execution means that the program will continue executing until an event needs to be handled, the program will then stop where it is, handel the event, and then jump back to where it left off
multipressBtnShortcuts = hs.eventtap.new({hs.eventtap.event.types.keyDown}, function(event)
-- FOR BEGINNERS: "function(event)" creates anonymous function containing the below code and passes it the keydown event as an object called "event" (Just makes the code neater, you could use a separate function if you want)
-- FOR BEGINNERS CONTINUED: An anonymous function is just a function without an identifier (name), instead they're objects and often behave kinda like variables (look this up, it's kinda hard to explain and not relevant here)
-- RANDOM NOTE: Also turns out all functions in lua are anonymous which is pretty interesting, the interpreter just converts the structure "function foo(x) return 2*x end" into "foo = function (x) return 2*x end"
if event:getKeyCode() == testKeyCode and event:getProperty(hs.eventtap.event.properties.eventSourceUserData) == 0 then -- Check if keycode is the shortcut keycode and check if the user data byte is set to 0 (default)
-- The user data byte check is to prevent the event handler from triggering itself (SEE PressKey FUNCTION ABOVE)
-- I'm sure there's a better way to do this but I cant find it
event:setType(hs.eventtap.event.types.nullEvent) -- Null the keypress event
-- Overrides the keypress, remove if you don't want the original keypresses to be overridden
-- I'm sure there's a better way to do this but I cant find it
keyDownCount = keyDownCount + 1 -- Add one to keypress counter
if CheckKeyDownCountTimer:running() then -- If the max key press gap timer is running stop it (NOTE: Stopping and starting it also resets it)
CheckKeyDownCountTimer:stop()
end
if keyDownCount < keyMaxPressCount then -- If keypress counter is less then the max number of keypresses restart the max key press gap timer (NOTE: Stopping and starting it also resets it)
CheckKeyDownCountTimer:start()
else -- Alternativly, if the keypress counter is greater than or equal to the max number of keypresses run the CheckKeyDownCount function
CheckKeyDownCount()
end
end
return false -- Ends the anonymous function by returning false, not sure if this is really necessary but it's what other people seem to do
end)
multipressBtnShortcuts:start() -- Starts the keydown event handler

Related

How can I toggle SetTimer off with a hotkey in AutoHotKey?

I am trying to write a script toggling a function.
This is an AutoHotkey 2 Script.
j::
SetTimer "NewTimer", 1000
return
k::
SetTimer "NewTimer", Off
return
NewTimer() {
SendInput "NewInput"
}
Pressing J should start the timer, pressing K should stop it.
Currently, pressing K only stops it as long as I hold the key down.
How can I stop the timer with the key press?
k::
SetTimer "NewTimer" , "Off"
Return
Off must be in quotes, otherwise it will try to pass the contents of the varaible "Off". The reason holding K seems to pause it is because it's rapidly updating the period to the value contained in Off which is null and an error, so it reverts to the previous period of 1000.
Alternatively, if this is the only timer, using just SetTimer , "Off" also works.
You can consider that excerpt from the official docs for SetTimer:
If hotkey response time is crucial (such as in games) and the script contains any timers whose subroutines take longer than about 5 ms to execute, use the following command to avoid any chance of a 15 ms delay. Such a delay would otherwise happen if a hotkey is pressed at the exact moment a timer thread is in its period of uninterruptibility:
Thread, interrupt, 0 ;//Make all threads always-interruptible.

How to have a true sliding window that ignores recent events?

I was trying to build something like a window that behaves like a sliding window and:
Counts events, ignoring the ones since the end of the window up to a certain "delay"
Triggers once and only once per event
Output count of events in [event TS - delay - duration , event TS - delay]
Using pre-aggregation to avoid saving all the events.
The parameters of the window would be:
Duration: duration of the window
Output: offset of the events to trigger, counting from the end of the window. Analogous to "slide".
Delay: offset of the events to ignore, counting from the end of the window. Essentially ignore events such that timestamp <= end of window - slide - delay.
The idea I was trying involved having a sliding window with:
Duration: duration + output + delay
Slide: output
Trigger whenever the event TS is in [window end - output, window end]. This causes only one window to trigger.
The question now is: how to filter events in order to ignore the ones before "delay"? I've thought of:
Having an aggregator that only sums the value if the event TS is between the correct bounds. This is not possible because aggregators in windows can't be a RichAggregateFunction and therefore I have no access to the window metadata. Is this assumption correct?
Having pre-aggregation with:
Typical sum reducer
RichWindowFunction that uses managed state to keep track of how many elements were seen in the "area to ignore" and subtract that from the aggregator result received. The problem is that getRuntimeContext().getState() is not maintained per window and therefore can't be used. Is this assumption correct?
Are there any alternatives I'm missing or is any of the assumptions incorrect?
I may have gotten a bit lost in the details, but maybe I see a solution.
Seems like you could use a custom Trigger that fires twice, before and after the delay. Then use a ProcessWindowFunction with incremental aggregation, and use per-window state to hold the count of the first firing (and then subtract later).
Given the complexity in putting that all together, a solution based on a ProcessFunction and managed state might be simpler.

Switch Debouncing Logic in C

I came across this code by Ganssle regarding switch debouncing. The code seems pretty efficient, and the few questions I have maybe very obvious, but I would appreciate clarification.
Why does he check 10 msec for button press and 100 msec for button release. Can't he just check 10 msec for press and release?
Is polling this function every 5 msec from main the most effecient way to execute it or should I check for an interrupt in the pin and when there is a interrupt change the pin to GPI and go into the polling routine and after we deduce the value switch the pin back to interrupt mode?
#define CHECK_MSEC 5 // Read hardware every 5 msec
#define PRESS_MSEC 10 // Stable time before registering pressed
#define RELEASE_MSEC 100 // Stable time before registering released
// This function reads the key state from the hardware.
extern bool_t RawKeyPressed();
// This holds the debounced state of the key.
bool_t DebouncedKeyPress = false;
// Service routine called every CHECK_MSEC to
// debounce both edges
void DebounceSwitch1(bool_t *Key_changed, bool_t *Key_pressed)
{
static uint8_t Count = RELEASE_MSEC / CHECK_MSEC;
bool_t RawState;
*Key_changed = false;
*Key_pressed = DebouncedKeyPress;
RawState = RawKeyPressed();
if (RawState == DebouncedKeyPress) {
// Set the timer which will allow a change from the current state.
if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
else Count = PRESS_MSEC / CHECK_MSEC;
} else {
// Key has changed - wait for new state to become stable.
if (--Count == 0) {
// Timer expired - accept the change.
DebouncedKeyPress = RawState;
*Key_changed=true;
*Key_pressed=DebouncedKeyPress;
// And reset the timer.
if (DebouncedKeyPress) Count = RELEASE_MSEC / CHECK_MSEC;
else Count = PRESS_MSEC / CHECK_MSEC;
}
}
}
Why does he check 10 msec for button press and 100 msec for button release.
As the blog post says, "Respond instantly to user input." and "A 100ms delay is quite noticeable".
So, the main reason seems to be to emphasize that the make-debounce should be kept short so that the make is registered "immediately" by human sense, and that the break debounce is less time sensitive.
This is also supported by a paragraph near the end of the post: "As I described in the April issue, most switches seem to exhibit bounce rates under 10ms. Coupled with my observation that a 50ms response seems instantaneous, it's reasonable to pick a debounce period in the 20 to 50ms range."
In other words, the code in the example is much more important than the example values, and that the proper values to be used depends on the switches used; you're supposed to decide those yourself, based on the particulars of your specific use case.
Can't he just check 10 msec for press and release?
Sure, why not? As he wrote, it should work, even though he wrote (as quoted above) that he prefers a bit longer debounce periods (20 to 50 ms).
Is polling this function every 5 msec from main the most effecient way to execute it
No. As the author wrote, "All of these algorithms assume a timer or other periodic call that invokes the debouncer." In other words, this is just one way to implement software debouncing, and the shown examples are based on a regular timer interrupt, that's all.
Also, there is nothing magical about the 5 ms; as the author says, "For quick response and relatively low computational overhead I prefer a tick rate of a handful of milliseconds. One to five milliseconds is ideal."
or should I check for an interrupt in the pin and when there is a interrupt change the pin to GPI and go into the polling routine and after we deduce the value switch the pin back to interrupt mode?
If you implement that in code, you'll find that it is rather nasty to have an interrupt that blocks the normal running of the code for 10 - 50ms at a time. It is okay if checking the input pin state is the only thing being done, but if the hardware does anything else, like update a display, or flicker some blinkenlights, your debouncing routine in the interrupt handler will cause noticeable jitter/stutter. In other words, what you suggest, is not a practical implementation.
The way the periodic timer interrupt based software debouncing routines (shown in the original blog post, and elsewhere) work, they take only a very short amount of time, just a couple of dozen cycles or so, and do not interrupt other code for any significant amount of time. This is simple, and practical.
You can combine a periodic timer interrupt and an input pin (state change) interrupt, but since the overhead of many of the timer-interrupt-only -based software debounces is tiny, it typically is not worth the effort trying to combine the two -- the code gets very, very complicated, and complicated code (especially on an embedded device) tends to be hard/expensive to maintain.
The only case I can think of (but I'm only a hobbyist, not an EE by any means!) is if you wanted to minimize power use for e.g. battery powered operation, and used the input pin interrupt to bring the device to partial or full power mode from sleep, or similar.
(Actually, if you also have a millisecond or sub-millisecond counter (not necessarily based on an interrupt, but possibly a cycle counter or similar), you can use the input pin interrupt and the cycle counter to update the input state on the first change, then desensitize it for a specific duration afterwards, by storing the cycle counter value at the state change. You do need to handle counter overflow, though, to avoid the situation where a long ago event seems to have happened just a short time ago, due to counter overflowing.)
I found Lundin's answer quite informative, and decided to edit my answer to show my own suggestion for software debouncing. This might be especially interesting if you have very limited RAM, but lots of buttons multiplexed, and you want to be able to respond to key presses and releases with minimum delay.
Do note that I do not wish to imply this is "best" in any sense of the world; I only want you to show one approach I haven't seen often used, but which might have some useful properties in some use cases. Here, too, the number of scan cycles (milliseconds) the input changes are ignored (10 for make/off-to-ON, 10 for break/on-to-OFF) are just example values; use an oscilloscope or trial-and-error to find the best values in your use case. If this is an approach you find more suitable to your use case than the other myriad alternatives, that is.
The idea is simple: use a single byte per button to record the state, with the least significant bit describing the state, and the seven other bits being the desensitivity (debounce duration) counter. Whenever a state change occurs, the next change is only considered a number of scan cycles later.
This has the benefit of responding to changes immediately. It also allows different make-debounce and break-debounce durations (during which the pin state is not checked).
The downside is that if your switches/inputs have any glitches (misreadings outside the debounce duration), they show up as clear make/break events.
First, you define the number of scans the inputs are desensitized after a break, and after a make. These range from 0 to 127, inclusive. The exact values you use depend entirely on your use case; these are just placeholders.
#define ON_ATLEAST 10 /* 0 to 127, inclusive */
#define OFF_ATLEAST 10 /* 0 to 127, inclusive */
For each button, you have one byte of state, variable state below; initialized to 0. Let's say (PORT & BIT) is the expression you use to test that particular input pin, evaluating to true (nonzero) for ON, and false (zero) for OFF. During each scan (in your timer interrupt), you do
if (state > 1)
state -= 2;
else
if ( (!(PORT & BIT)) != (!state) ) {
if (state)
state = OFF_ATLEAST*2 + 0;
else
state = ON_ATLEAST*2 + 1;
}
At any point, you can test the button state using (state & 1). It will be 0 for OFF, and 1 for ON. Furthermore, if (state > 1), then this button was recently turned ON (if state & 1) or OFF (if state & 0) and is therefore not sensitive to changes in the input pin state.
In addition to the accepted answer, if you just wish to poll a switch from somewhere every n ms, there is no need for all of the obfuscation and complexity from that article. Simply do this:
static bool prev=false;
...
/*** execute every n ms ***/
bool btn_pressed = (PORT & button_mask) != 0;
bool reliable = btn_pressed==prev;
prev = btn_pressed;
if(!reliable)
{
btn_pressed = false; // btn_pressed is not yet reliable, treat as not pressed
}
// <-- here btn_pressed contains the state of the switch, do something with it
This is the simplest way to de-bounce a switch. For mission-critical applications, you can use the very same code but add a simple median filter for the 3 or 5 last samples.
As noted in the article, the electro-mechanical bounce of switches is most often less than 10ms. You can easily measure the bouncing with an oscilloscope, by connecting the switch between any DC supply and ground (in series with a current-limiting resistor, preferably).

How to wait until an element is not changing in Selenium Webdriver?

I have begun to use explicit wait more and more to deal with asynchronous event on the page. For example i will wait for an element to be clickable before clicking it.
However many time i also face the situation when i need to wait an element to become stable, i.e. stop changing, before i will act on it. For example, i may do a query on a page, and wait for the search result (either shown in a list or a table) to stop changing, and then retrieve the results.
Off course, there will be a timeout period for this wait. So in a nutshell, i want to wait for a list or table while its values are not changed, say for 5 sec.
How to implement this kind of wait? Could anyone give a simple example in code, if possible?
Thanks,
Using FluentWait will do the job. Its advantage to implicitWait and explicitWait is that it uses polling and timeout frequency. For example, we have a timeout value of 5 seconds and 1 second for polling frequency. The element will be checked for every 1 second until it reaches the timeout value (5 sec). An exception is thrown if the timeout value is exceeded without having any result.
FluentWait is helpful in AJAX applications as well as in scenarios when element load time fluctuates often because it ignores specific types of exceptions like NoSuchElementExceptions while waiting for an element.
You can check the sample code for FluentWait here
I would do something like this. Basically you want to count what is changing, e.g. table rows, list elements, etc., wait X seconds, count again. If the count didn't change, you are done. If it did change, wait again.
int count = 0;
int newCount = 0;
boolean done = false;
while (!done)
{
newCount = driver.findElements(...).size();
if (newCount > count)
{
count = newCount;
}
else
{
// no new results, stop waiting
done = true;
}
Thread.sleep(2000);
}
Depending on your scenario, you might want to add an overall timeout so that you never exceed X minutes or whatever. Just add that to the while condition.

VisualBasic6 - read continuously a variable

I need read in an infinite loop some variables and in the case it changes the boolean status it must do something.
I tried to use a Do...Loop but the application crashes.
Is there a way in visual basic 6 to use an infinite loop without stunk?
My code:
Do
asd1 = readValue1
asd2 = readValue2
If asd1 <> asd1ex Then
Text1.Text = "yes"
End If
If asd2 <> asd2ex Then
Text1.Text = "no"
End If
Loop While True
Make a timer and on that timer check the status, instead of the loop.
Solved after comment that explained where the data was coming from (async COM component's property):
working with vb6 IDE on a realtime client-server project. I have to read some variables
and when one of these changes status it sends a socket message to
server. With the sleep it stuck equally
What did not help:
DoEvents and sleep
DoEvents
Sleep 100
might help, will need to refer to the windows function sleep. But VB6 is single thread (well one for UI and one for logic) so you should have a way to get out of the loop. What are you really trying to do? Can you describe at a top level?
Are you working on the VB6 IDE or in VBA code in Office?
For sleep to work declare:-
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
See this too https://stackoverflow.com/a/4540553/1643558
If your showing a form to the user to read value 1 and 2 then you can use a modal form and have a button to click when they are done, and hide the form only when you like the values. No need to have a loop then. Can show an error MsgBox on a modal form too.
See http://www.tek-tips.com/viewthread.cfm?qid=1117372
Maybe remove the sleep and only keep the DoEvents.
You could also make a timer and on that timer check the status, instead of the loop
It looks like you're trying to set up a sort of event handler. In effect, your loop is "listening" for a change to the variable. You don't explain how the variables get changed, and this is important . If whatever is changing the variables can also raise an event, then you're home free--you can get rid of your loop and use the event handler to send the socket message. (This is probably why Deanna asked how the variables change.) This is the preferred way to do what you want, so you should find ways to raise an event if the variables change.

Resources