News for hackers. Stuff that matters.

EsportToys

Re:A useless infinite scroll experiment on Tuesday March 10, 2026 @07:24AM (#47321761)
You may also be interested in my little modification of middle-scroll behaviour:

https://github.com/esporttoys/librescroll

Re:Microsoft PowerToys on Wednesday September 10, 2025 @03:35PM (#45202541)
I wrote https://github.com/EsportToys/TPMouse a while back with the “grid mode” that moves the mouse cursor by bisecting the screen coordinate incrementally.
Re:Physically Based Rendering in Filament on Wednesday August 20, 2025 @12:02AM (#44958533)
Nice, it's also a great test for my https://github.com/EsportToys/LibreScroll
Re:I'm Unsatisfied with Easing Functions on Wednesday July 23, 2025 @12:29PM (#44661049)
You can trivially calculate the time-to-peak overshoot using the closed form equation. It’s the first (0-indexed) zero of the velocity response, i.e. happens at t = (pi / scale)

And obviously it would only apply for the underdamped case.

Re:I'm Unsatisfied with Easing Functions on Wednesday July 23, 2025 @11:59AM (#44660682)
A middleground is to use fixed timesteps with the closed form solution. Then the integration factors can be statically precomputed as constants, and every frame becomes just a 2x2 matrix multiplication.

And even if you are to calculate the integration factors based on dynamic frame rates, they only need to be computed just once per frame for all objects that share the same damping configuration.

Re:I'm Unsatisfied with Easing Functions on Wednesday July 23, 2025 @10:40AM (#44659745)
It’s the general solution to a damped harmonic oscillator/mass-spring-damper system:

    m * x’’ + c * x’ + k * x = f(t)
See https://web.archive.org/web/20230604215211/https://esporttoy...
Re:I'm Unsatisfied with Easing Functions on Wednesday July 23, 2025 @09:19AM (#44658925)
Closed-form (non-iterative) PID solution:

https://www.desmos.com/calculator/mu80ttc9aa

   function sprung_response(t,pos,vel,k,c,m)
      local decay = c/2/m
      local omega = math.sqrt(k/m)
      local resid = decay*decay-omega*omega
      local scale = math.sqrt(math.abs(resid))
      local T1,T0 = t , 1
      if resid<0 then
         T1,T0 = math.sin( scale*t)/scale , math.cos( scale*t)
      elseif resid>0 then
         T1,T0 = math.sinh(scale*t)/scale , math.cosh(scale*t)
      end
      local dissipation = math.exp(-decay*t)
      local evolved_pos = dissipation*( pos*(T0+T1*decay) + vel*(   T1      ) )
      local evolved_vel = dissipation*( pos*(-T1*omega^2) + vel*(T0-T1*decay) )
     return evolved_pos , evolved_vel
   end
For anticipation, just add an extra initial velocity in the opposite direction and let the closed-form solution handle the time evolution. The main trick here is to keep both position and velocity as state. There is no need to “step through the simulation”.
Seconded for Love2D, here's a sample of how simple it is to quickly whip up something in it:

https://github.com/EsportToys/wireworld-love

Speaking of const-factor 2nd-order ODE, a.k.a. mass-spring-damper systems, I wrote a blog post deriving all possible general solutions in a concise matrix form that makes it easily implementable in software:

https://esporttoys.pages.dev/2022/11/21/damped

Re:What it takes to pass a file path to a Windows API in C++ on Monday September 25, 2023 @12:14AM (#37639620)
Actuall you're missing ClipCursor as another way of moving the cursor.

Also, mouse_event is just a wrapper around what's basically SendInput(mouse)

Re:Turning a Keyboard into a Mouse with Libevdev on Thursday September 07, 2023 @11:49PM (#37429034)
The friction/acceleration awkwardness can be solved by using a physically based timestep-independent formulation, which I implemented in TPMouse[0] and explained its derivation in a previous comment reply[1].

The gist of it is that the solution to a linearly damped particle is a linear system, so the x and y components can be calculated completely independently and the analytic solution is just an exponential of time.

It is a special case of the timestep-independent damped harmonic oscillator, which I previously wrote a blogpost about [10].

Namely it is the "unsprung" special case under "Overdamped"

The very same formulation is also what I used to implement LibreScroll[11] to add inertial scrolling to any mouse.

[0] https://github.com/EsportToys/TPMouse

[1] https://www.reddit.com/r/Trackballs/comments/ym9q2t/tpmouse_...

[10] https://news.ycombinator.com/item?id=35899215

[11] https://news.ycombinator.com/item?id=36783942

Re:Turning a Keyboard into a Mouse with Libevdev on Thursday September 07, 2023 @11:36PM (#37428938)
And for Windows, my https://github.com/EsportToys/TPMouse was inspired by warpd itself but more focused on making direct cursor motion more usable using momentum.
Re:Floor Mouse (2018) on Tuesday August 15, 2023 @02:37AM (#37130914)
Shameless plug, but you may like the Inertia Mode of my TPMouse script[0] if you need a keyboard-based workflow systemwide.

[0] https://github.com/EsportToys/TPMouse

A little known secret on Windows is that you can still get LGS via winget:

    winget install Logitech.LGS
Try running the exe version with wine and see if it works on your system -- this uses only very old/stable WinAPIs so I'd imagine that wine would have it well-covered by now.
Re:Don’t Make Fun of Renowned Dan Brown (2013) on Saturday July 22, 2023 @03:49AM (#36824288)
> There are two novels that can change a bookish fourteen-year old's life: The Lord of the Rings and Atlas Shrugged. One is a childish fantasy that often engenders a lifelong obsession with its unbelievable heroes, leading to an emotionally stunted, socially crippled adulthood, unable to deal with the real world. The other, of course, involves orcs.

http://kfmonkey.blogspot.com/2009/03/ephemera-2009-7.html

I use the G305 which is even more barebones in the buttons, however I remapped the dpi button to be a sort of "omnifunctional activator" that I combine Lua scripting from LGS with other Autoit scripting for accessing WinAPI to achieve multitouch gestures with my mouse. The UX isn't quite refined enough to be a standalone application that I can share on GitHub yet, but eventually I'll figure out how to turn them into a self-contained package.
Glad that you like it! You might also find my MouseTray utility useful (which I mentioned in another comment), since seeing from your bio that you're familiar with esports you might care a bit more about configurations.
I'm actually in the process of reworking it so that the keybinds can be fully remapped via a GUI. In fact, LibreScroll is my first step experimenting with multi-process delegation that will enable that functionality, since the current way of having to edit the code directly in scattered locations is very much not ergonomic.

In the meantime, for the current version of TPMouse on the dev branch, to change the remapping of arrows and mouse buttons, you need to edit `keybinds.au3` in three spots:

1. the virtual-key constant at the static array at the top

2. the hotkey string at the static array at the top

3. (this is really poor UX I know) in the static struct declaration inside the respective callback function, change the referenced virtual-key constant.

The list of virtual key codes can be found in `vkeys.au3`:

https://github.com/EsportToys/TPMouse/blob/dev/vkeys.au3

So for example, to remap mouse1 from F to A, I need to do the following:

Line 10:

    <<< before >>>
           $mb1    = [ $VK_F     , '{f}'     , callback_f     ] , _

    <<< after >>>
           $mb1    = [ $VK_A     , '{a}'     , callback_f     ] , _
Lin 68:

    <<< before >>>
     Local Static $struct = DllStructCreate('ushort MakeCode;ushort Flags;ushort VKey;'), $vkey = DllStructSetData($struct,'VKey',$VK_F)

    <<< after >>>
     Local Static $struct = DllStructCreate('ushort MakeCode;ushort Flags;ushort VKey;'), $vkey = DllStructSetData($struct,'VKey',$VK_A)

As for changing the activation hotkeys, if you wish to use a different modifier other than CapsLk, change the vkey code on line 74, 90, and line 107 of TPMouse.au3; for example, to change it from CapsLk to Alt:

Line 74:

    <<< before >>>
       Case $VK_CAPS

    <<< after >>>
       Case $VK_ALT
Line 90:

    <<< before >>>
               If $VK_Q = $struct.VKey And Not ( $sks($VK_CAPS) Or ($sks($VK_LSHIFT) And $sks($VK_RSHIFT)) ) Then Return

    <<< after >>>
               If $VK_Q = $struct.VKey And Not ( $sks($VK_ALT) Or ($sks($VK_LSHIFT) And $sks($VK_RSHIFT)) ) Then Return
Line 107:

    <<< before >>>
               If $sks($VK_CAPS) Or ($sks($VK_LSHIFT) And $sks($VK_RSHIFT)) Then

    <<< after >>> 
               If $sks($VK_ALT) Or ($sks($VK_LSHIFT) And $sks($VK_RSHIFT)) Then
Thank you! Another applet I made that I personally think is neat, although I see why it's not something many would care about, is the MouseTray[0] utility that gives me a quick "volume popup" but for mouse cursor speeds, it makes it quite easy for me to switch between using a mouse normally and drawing precisely without needing to reaching for my tablet.

Although it didn't get as much attention as my other utility, it's actually the app that I'm most happy about having made.

[0] https://github.com/esporttoys/mousetray

Thanks! It was actually inspired by rvaiya's warpd [0] which has a similar grid mode but with quadrants instead.

I thought that needing to choose out of four quadrants at once is a bit overwhelming on cognitive load for something that is meant to be a subconscious extension of your hands, so instead I just unified it with the arrow keys as a "shrink in this direction" choice rather than "choose one of four quadrants".

Changing it to bisection/binary partitioning also means that don't need any visual aids as it's exceedingly simple to see which edge your target is the closest to.

[0] https://github.com/rvaiya/warpd

I'm curious about what you think of Hold mode vs Flick mode? I personally use Flick mode myself but thought that it might confuse the user on first-impression, so I have it default to Hold mode to be on the safe side.
Thanks @dang for reviving my post! I was getting quite exasperated that nearly all of my posts had been blocked upon submission, especially the damped spring derivation I particularly wanted to share with HN —- tried resubmitting it three times and failed in every instance.
Thank you for the kind words! I’ve never used Linux before, I wonder if it will work well with Wine since this script only uses very old WinAPIs, namely SendInput and RawInput, and native win32 controls/tray, I would imagine that wine would have pretty good coverage of them.
So what you’re saying is, TCP is better than UDP?

Show HN: LibreScroll – enable flywheel-scrolling on any generic mouse

https://github.com/EsportToys/LibreScroll

Based on the framerate-independent momentum simulation[0] that I used in my TPMouse script[1]If you've ever used a mouse with Infinite-scrollwheel such as Logitech, this utility for Windows basically recreates that functionality for any generic mouse.Actually, it's even better than that: this allows for simultaneous horizontal and vertical scrolling, so essentially it combines two of the best...

( Read More... | 21 comments | on HN )
Re:Matrices and Graph on Saturday July 15, 2023 @09:11AM (#36736370)
I highly recommend anything in Finite Element Methods, it gives you an immediate grounding to a concrete application. I personally really benefitted a lot in the following YouTube lecture series:

https://www.math.colostate.edu/~bangerth/videos.html

Re:Matrices and Graph on Saturday July 15, 2023 @09:09AM (#36736347)
I think the most common application is describing mesh connectivity in Finite Element Methods, where each entry in the matrix represents the influence each node has on each other. Basically any N^2 table can be constructed to describe the general dependency of components in any simulation or systems in genera.
Re:Matrices and Graph on Saturday July 15, 2023 @08:35AM (#36736049)
Fun fact: this is possible because of tensor symmetries (tensors in the rigorous Physics sense with the symmetry requirements, rather than in machine-learning sense of the generic ndarrays); you could loosely say that for actual tensors, there is a notion of "selfness" for the entries, whereas a more general matrix/ndarray is just tabulated relations and can't be mapped back to itself in the same way.

Older »