204

I'm working for a foundation that raises awareness for accessibility in the internet. For a presentation, we want to offer a small workshop that simulates different disabilities/impairments to people. This is done via a website created especially for this presentation.

One of the demonstrated impairments is having a tremor, which means experiencing shaky, difficult-to-control hand movements. With this impairment, it's very difficult to move the mouse cursor exactly and to press the mouse button while the mouse is over a link. Both some old people and people with disease, e.g. Parkinson's, can suffer from tremor.

Now I'd like to somehow move the mouse cursor in an unpredictable way, so that it's very hard for people to click on a small button. Because JavaScript doesn't allow moving the mouse cursor directly, I'm looking for other ways to achieve this. I came up with the following ideas:

  • Using a mouse driver / utility that simulates the mouse shaking.
  • Hide the mouse cursor via CSS, place a GIF animation of a shaking mouse cursor at the place of the original cursor (with JavaScript), and then make the target link clickable only every few seconds for a second or so. This would at least give the feeling as if one always clicks at the wrong moment.

While the first idea would be pretty cool, I couldn't find a tool like this, whether for Mac nor for Windows. And I don't have any skills in programming such a thing myself.

The second idea seems a bit clumsy, but it would achieve the desired effect, I think.

Does anybody have another idea?

Matthew Haugen
  • 12,916
  • 5
  • 38
  • 54
Joshua Muheim
  • 12,617
  • 9
  • 76
  • 152
  • 35
    You actually can control the cursor position (well, an emulated one) with the [Pointer Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) – Stuart P. Bentley Aug 12 '14 at 07:58
  • 2
    Try looking at https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API#example. The direct link to the demo is https://mdn.github.io/pointer-lock-demo/. As long as it is acceptable for your purpose to tell the users the click on a canvas and allow the page to disable the mouse cursor, you might want to base your code off of this – Nick Meyer Aug 12 '14 at 08:06
  • 5
    The very question raises awareness among us web developers. Thanks for asking! How large do you think a button should be in order to be clickable? – Ideogram Aug 14 '14 at 08:04
  • @Ideogram, there are no final guidelines about this topic, not even from the WCAG group. http://www.w3.org/TR/WCAG20/ – Joshua Muheim Aug 14 '14 at 08:08
  • 4
    Just a level-set on tremor: There are two basic kinds -- "essential tremor" and Parkinson's tremor -- and they are entirely different. "Essential tremor" (which is *not* purely a condition of the elderly), is an "intention" tremor, meaning it's apparent only when the individual is trying to do something, and gets worse the harder the individual tries to control it. PD tremor, on the other hand, occurs primarily at rest, and the tremor is often not obvious when the individual is trying to do something (though stiffness due to PD may well be present). – Hot Licks Aug 14 '14 at 15:07
  • (And you can tell a PD patient from someone with ET by examining their handwriting. The PD patient will write tiny but fairly neat characters ("micrographia"), while the person with ET will struggle to write legibly, even if writing double-size.) – Hot Licks Aug 14 '14 at 15:14
  • (I suspect that you really want to simulate essential tremor, not PD.) – Hot Licks Aug 14 '14 at 15:14
  • 2
    I posted a linux version that uses xdotool to control the mouse, but there is a similar tool for windows called autoit. It looks pretty simple and there is even a tag for it [autoit]. Also it sounds like you need 2 versions. One that shakes more until movement starts and then calms down a bit while the other one is relatively stable until movement starts. – technosaurus Aug 15 '14 at 09:37
  • Can you post a link to the tool? Thank you. – Joshua Muheim Aug 15 '14 at 09:39
  • Sure, its http://www.autoitscript.com I also tried it out and ported my xdotool script to it (see below), only took a couple of minutes; kudos to them for a really nice tool. If you add the autoit tag, I'm sure you'd get something better. – technosaurus Aug 15 '14 at 09:57
  • Just a note that the motions of tremors, whether rest or intention tremors, are not random. In fact, they are the opposite. The brain tracks the body by sending out vast numbers of small twitches in all muscles. Since the twitches are completely random, they balance each other out making for smooth motion. Tremors result when the twitches begin to develop a periodic clustering, the twitches all begin to occur on a cycle with opposing groups of muscles active at opposite ends the cycle. This causes the affected muscles to jerk back and forth. Random mouse motion won't much much like a tremor. – TechZen Aug 18 '14 at 00:37
  • 2
    A simple way to get people thinking about accessibility: ask everyone to use the mouse left-handed. – Colonel Panic Aug 18 '14 at 09:21
  • @ColonelPanic, this is a very nice input, indeed! Thanks. – Joshua Muheim Aug 18 '14 at 09:25
  • Sorry if this is a bit off-topic, but would it be possible for the computer the compensate the random movement (to some degree)? Like taking the average position of the cursor within a certain radius? Or would this impact the "reaction time" of the cursor so much that it leads to bad UX on a different end? – Felix Kling Aug 25 '14 at 16:49

13 Answers13

147

I made a quick demo of something that you hopefully should be able to base your code on, using the Pointer Lock API.

I forked this pointer-lock-demo repo and modified it to add a random movement element.

Here is the link to my GitHub page: https://aristocrates.github.io/pointer-lock-demo
And here is the link to my repo: https://github.com/aristocrates/pointer-lock-demo

The javascript code of importance is contained in app.js, in the canvasLoop(e) method.

The only thing I changed from the original demo was after the lines

x += movementX * 2;
y += movementY * 2;

I added two lines to represent random movement:

x += Math.floor(Math.random()*3 - 1);
y += Math.floor(Math.random()*3 - 1);

There are still plenty of things you could improve, but hopefully this can help you get started.

Nick Meyer
  • 1,771
  • 1
  • 17
  • 29
  • 36
    As a note in the functionality, random movement is not the same as a shaking hand. With random movement the pointer can drift across the screen. With a shaking hand the pointer is going to vibrate around a central point. – zzzzBov Aug 12 '14 at 14:53
  • 5
    It is worth noting that browser support for the Pointer Lock Api is not great - this will not work in Internet Explorer or Safari. – Steve Sanders Aug 12 '14 at 16:41
  • 3
    I didn't find the time to try it out myself, but maybe you know this one: does the pointer-lock API also work outside a canvas? Or is it restricted to a canvas? – Joshua Muheim Aug 13 '14 at 12:34
  • What's difficult isn't to replace the real cursor with a shaky cursor. What's difficult is to handle click events so that it reflects where the fake mouse is instead of where the mouse actually is. – Lie Ryan Aug 13 '14 at 22:58
  • @LieRyan In this code example the fake mouse location is represented by the global variables `x` and `y`, so shouldn't handling click events be as simple as using those values? – Nick Meyer Aug 14 '14 at 00:32
  • Once you had the mouse position, you still need to figure out a way trigger a mouse click event on the specified coordinates, and make sure that those event bubbles up the way normal mouse clicks do. And then there's drag and drop. Of course these may not be necessary for the OP. – Lie Ryan Aug 14 '14 at 00:52
  • 8
    A more realistic implementation would track the "real" position of the cursor and move randomly within a circle around that, but that might be too complex. – tckmn Aug 14 '14 at 07:08
  • @ComFreek - I'm trying to look at your jsfiddle demo, but the canvas doesn't display anything in Chrome/Firefox/IE - is there something I'm missing? – Krease Oct 24 '14 at 23:32
  • 1
    @Chris Chrome now throws `Blocked pointer lock on an element because the element's frame is sandboxed and the 'allow-pointer-lock' permission is not set.`. It seems that jsFiddle is embedding the content in a sandboxed frame (i.e. not allowing pointer lock via ` – ComFreek Oct 25 '14 at 12:46
36

Non-javascript way

Actually, I like solutions, which may be based on javascript, since they are more likely web-related, and good chances are — OS-independent. However, I was thinking about — how to resolve your issue for all browsers, since javascript solutions, in this case, will be difficult to adjust for all possible browsers (I'm not sure if it's possible at all).

So, as you've mentioned, there is another way — i.e. to emulate the behavior on OS level. This has another advantage too — you may be sure that for browser it looks 100% as it was human (because, well, it's driver which is sending the signal). So you may use driver/device-based solutions with any browsers (or even in situation, when javascript is disabled).

Linux

Unfortunately, involving driver/device immediately causes OS dependency. So for each OS you'll need own solution. In this post I'm focused on Linux-based solution (so, will work with Linux) — and Mac OS a little. With Linux, it's possible to write events to device explicitly, so below is sample of function with main loop:

int main()
{
    struct input_event event, event_end;

    int  fd = open("/dev/input/event4", O_RDWR);
    long ma = getInteger("Enter max amplitude [points, 0..50]: ", 0, 50);
    long ta = getInteger("Enter max wait time [usecs , 0..200000]: ", 0, 200000);
    if (fd < 0)
    {
        printf("Mouse access attempt failed:%s\n", strerror(errno));
        return -1;
    }
    memset(&event, 0, sizeof(event));
    memset(&event, 0, sizeof(event_end));
    gettimeofday(&event.time, NULL);
    event.type = EV_REL;
    gettimeofday(&event_end.time, NULL);
    event_end.type = EV_SYN;
    event_end.code = SYN_REPORT;
    event_end.value = 0;
    while(1)
    {
        event.code  = rand() % 2 ? REL_X : REL_Y;
        event.value = (rand() % 2 ? -1 : 1) * randomTill(ma);
        write(fd, &event, sizeof(event));
        write(fd, &event_end, sizeof(event_end));
        usleep(randomTill(ta));
    }
    close(fd);
    return 0;
}

My full code for the issue be found here. The program will ask for amplitude of "tremor" and it's frequency (thus, how many time in micro-seconds are between "tremors"). To emulate situation, it will force mouse to move randomly for 0..X points in random direction (up-down-left-bottom) and wait randomly 0..Y micro-seconds till next "tremor", there X is amplitude of "tremor" and Y is frequency of "tremor"

Another thing may be to adapt the program for your system. The program is "dummy" and can't detect mouse by itself, so "/dev/input/event4" is hard-coded. To realize what may be identifier for your system you may try:

user@host:/path$ cat /proc/bus/input/devices | grep mouse
H: Handlers=mouse0 event3 
H: Handlers=mouse1 event4

And so possibilities are "event3" and "event4" — but for your system that may have other values. So, if that is different from currently used in C code, just change the corresponding line (so, line with int fd = open("/dev/input/event4", O_RDWR); and place your device instead of event4)

A gif demo for this program (low frame rate, unfortunately, so keep image not too large) here.

A little side note (if you don't know what to do with C code) — to compile program above, just use:

user@host:/path$ gcc -std=gnu99 file.c -o m

where file.c is the name of your C source code file, then you'll get executable, called m in your directory. Most likely you'll need permissions to write into mouse device directly, so you may use sudo:

user@host:/path$ sudo ./m

Other OS

The logic will remain same:

  • Find a way to access your mouse device
  • Write event of moving mouse
  • Apply randomization to your event

That's it. For instance, Mac OS has its own way to work with mouse (not like Linux, Mac hasn't procfs as well), it's well-described here.

As a conclusion

What is better — javascript or device-oriented solutions — is up to you, because certain condition (like cross-browser or cross-OS) may decide everything in this case. Therefore, I've provided guidelines together with certain working example of how to implement that on OS level. The benefit here is that solution is cross-browser, but as a cost we have OS-binded program.

Community
  • 1
  • 1
Alma Do
  • 37,009
  • 9
  • 76
  • 105
  • Thanks a lot for this very detailed post. I suspect that we will demonstrate on a tablet (android or ios), so we won't be able to change the mouse behavior at OS level. But very interesting anyways! – Joshua Muheim Aug 12 '14 at 12:38
  • 53
    How the heck are you gonna demonstrate shaky mouse on touchscreen devices? – Davor Aug 12 '14 at 14:43
  • 6
    @Davor Honestly, I *highly doubt* that people who actually have trouble with tremors/shaky hands would use a *touch device*, unless they wanted to intentionally drive themselves mad. – Chris Cirefice Aug 13 '14 at 13:50
  • 2
    @ChrisCirefice: Or are forced to, because they have to use one of the gazillion devices out there that are meant to make our lifes nicer and use touch screens... remember this is to raise awareness of the problem that these people have problems with that. – PlasmaHH Aug 13 '14 at 22:37
  • @PlasmaHH The OP didn't mention that this is to raise awareness for people who have tremors and their difficulty (specifically) with touch-screen devices. And again, I don't think anyone who actually has problems with tremors is masochistic enough to try to use ***hand-held** touch-screen devices*. There are devices that are much easier to use, such as phones with large (mechanical) buttons. Most operating systems include navigation by speech (e.g, Speech Recognition - Windows OS). I imagine that seriously-afflicted individuals would use those tools instead of an iPhone. – Chris Cirefice Aug 14 '14 at 02:30
  • @ChrisCirefice: I didn't know that there are only hand held touch screen devices. I always thought all those vending machines and stuff around where you touch the screen are called touch screen devices too. And even I have sometimes problems using their tiny buttons with not so much shaking hands. But probably I should stay at home and get a voice controlled device instead of trying to interact with things like self checkouts at superemarkets. – PlasmaHH Aug 14 '14 at 08:37
  • Please, point - to __where__ OP wants "web-solution". Note, that he even mentioned the way that I've implemented as an acceptable option (but stated that didn't implemented becase is unfamiliar with such programming) – Alma Do Aug 14 '14 at 15:57
  • @AlmaDo: yeah, upon reflection, it's ambiguous. My bad. Downvote and comment rescinded. – Ben Mosher Aug 14 '14 at 15:57
  • Using `XWarpPointer` rather than `/dev/input` should be portable to most unix systems (except Mac OS X which has no X). – kasperd Aug 15 '14 at 12:31
23

I did this as a joke once, on the Puppy Linux Forum and got the comment that:

People with Parkinson's won't think it's funny !!!

Cure here is simply cntrl-C, luckily.

Here is the shell script which requires xdotool

#!/bin/sh
while :; do
   xdotool mousemove_relative -- -$(($RANDOM % 10)) $(($RANDOM % 10))
   xdotool mousemove_relative -- $(($RANDOM % 10)) -$(($RANDOM % 10))
   sleep ${1:-.1} #adjust this as necessary for effect
done

Name as parkinson_sim and run with optional argument for the time between tremors which can be 0.001 to 999.0.

parkinson_sim [time_between_tremors_in_seconds] #default is 0.1

I made the mistake of clicking on it myself instead of running it from the command line and quickly discovered how frustrating it must be. It took me several tries to get a terminal window open to kill it.

technosaurus
  • 7,676
  • 1
  • 30
  • 52
  • 1
    you might want to replace the colon by something like "sleep 0.01" to limit cpu usage and speed, because on my rig it makes unrealistic fast jumps with your code. – nonchip Aug 13 '14 at 17:11
  • 1
    @nonchip - Thanks for the info, I never ran it long enough to find out the cpu usage. Added a sleep to the body. – technosaurus Aug 13 '14 at 21:12
  • You know in most Linux distros you can open the terminal using keyboard commands, right? – justhalf Aug 14 '14 at 16:47
  • @justhalf In default Puppy at the time, the terminal shortcut was to press `\`` in a ROX-Filer window. It took a couple of tries to open it, so I used the keyboard to open the menu. Shortly afterwards I created a rudimentary voice control daemon using pocketsphinx_continuous and about 10 lines of shell. – technosaurus Aug 14 '14 at 19:56
  • `while :; do ...; sleep $time; done` should almost always be `while sleep $time; do ...; done`, because when the user presses Ctrl-C, the currently executing command will almost certainly be `sleep`, and shells don't always end the script when the user wants to. This most notably happens during testing in interactive shells, but it can sometimes happen even in scripts. Even better would be `while xdotool ... && xdotool ... && sleep ...; do :; done`. –  Aug 18 '14 at 06:55
17

Your second idea (hide the cursor) is halfway to one that I think may work well for you:

  • Hide the mouse cursor via CSS, as you suggest. (cursor:none IIRC)
  • Instead of a shaky-cursor GIF, use some image + CSS absolute positioning + JS to emulate the mouse pointer; i.e., follow the mouse around the page and plant the cursor image where the mouse cursor natively would be.

Then, you add some tremor math to your cursor code, to "shake" the cursor. Up to you to determine what the right curves are to properly simulate tremor input.

Finally: for whatever controls you are programming (links, etc.):

  • capture click events, nudge them to the current "tremor" location based on the state of your tremor curves, and bounds-check your elements to see if the user has shaken out of the element intended, or possibly into an element that was not intended.

One major bonus with this implementation: your 'shaky cursor' will be displayed on touch devices, which would not have a cursor to begin with.


Edit:

Based on Michael Theriot's (very clean and helpful!) base JSFiddle from the comments, here's one that tremors constantly with a normally-distributed sweep around the current cursor location: http://jsfiddle.net/benmosher/0x4mc64v/4/

(The normal array is the result of calling rnorm(100) in my R console. Simplest way I could think of in JS to sample a normally-distributed random integer.)

Community
  • 1
  • 1
Ben Mosher
  • 13,251
  • 7
  • 69
  • 80
14

Just an idea for getting the tremor "right", you can record the mouse movement of a real patient, this makes it more authentic when you tell people where the data comes from.

There a scripts for letting a cat follow your mouse cursor, you could adjust one to let a second cursor follow (jump around) your cursor. The page is calculating the position of the the second cursor, so it can also determine if an click event is successful or not.

If you can, please make it web based, you will reach a lot more people this way than asking them to install a program or activate flash or whatever there is.

user3934260
  • 135
  • 2
  • 1
    I do like this idea - mouse position could be recorded at any time interval via JavaScript. You could then plot out the movements (X-Y plane), and even get some basic statistics for a more 'valid' formula of 'tremor_randomness' for the Pointer Lock API solution or something similar. This would require a bit more work (just fetch X-Y position every 100 ms for 10 seconds, for example) and analysis, but would give you a much more *real* effect than simple randomization. For your cause, it may be worth it. – Chris Cirefice Aug 13 '14 at 13:59
11

Instead of trying to move the pointer, you could move the application (web page) instead. I wrote a simple html form that has some entry fields in it. When you move the mouse onto the form, the form moves.

You can see a demo of the moving form at jsfiddle. Try to click on one of the input fields to see the effect.

I used the jquery shake effect to achieve this. The javascript for the shake effect looks like this, and just causes the form to move up and down whenever the mouse is moved over it:

<script type="text/javascript">
    $(document).ready(function() {
        $("#toggle").hover(function () {
            $(this).effect("shake", { direction: "up", times: 1, distance: 40}, 1000);
        });
    });
</script>

Although the form only moves up and down, I think it has the desired effect. You can play with the parameters (direction, times, distance, as well as the un-named "1000" above) to tweak the form movement.

chue x
  • 18,573
  • 7
  • 56
  • 70
  • 3
    I thought about this myself, too, but while it's easier to implement, it doesn't show the "real" experience of a tremor. – Joshua Muheim Aug 13 '14 at 06:31
10

Why not use a hardware solution? There are certain mice out there that you can put weights in, like the Logitech G500. Instead of putting in a weight, put in a small oscillating motor that makes the mouse shake slightly. This also simulated the actual disorder more: it's not just the cursor that shakes, but the entire hand and mouse. And it also means you can show other software than websites.

Instead of a mouse with a weight slot, you can also just tape something to the mouse, but that's more noticeable.

Nzall
  • 3,439
  • 5
  • 29
  • 59
6

As you were thinking about doing it with a custom mouse driver I suppose a small program running on the PC would do either? If this is the case, here is a small snippet for C#, which infinitely moves the cursor randomly withing a range of plus minus 5px around the current cursor position. After each displacement the program waits 50 ms to 100 ms (not accurate!). The shakiness can be configured by adapting the values for the displacement and the pauses. I ran this in a console application and - depending on the values - it gave me quite a hard time stopping the program.

Random rand = new Random();

while(true)
{
    Cursor.Position = new Point() { X = Cursor.Position.X + rand.Next(11)-5, Y = Cursor.Position.Y + rand.Next(11)-5 };
    Thread.Sleep(rand.Next(50) + 50);
}
Paul Kertscher
  • 9,416
  • 5
  • 32
  • 57
6

Here is a windows version of my xdotool script that uses AutoIt. This was my first ever AutoIt script, and it took only a couple of minutes to write, so I'm sure it can be improved. Just save with the extension .au3 and run it with AutoIt (Run Script x86).

HotKeySet("{HOME}", "GStart")
HotKeySet("{PAUSE}", "Gpause")
HotKeySet("{ESC}", "Gexit")

While 1
    Sleep(100)
WEnd

Func Gstart()
While 1
    sleep(100)
    $pos = MouseGetPos()
    $x = $pos[0] + 10 - Random(0, 20, 1)
    $y = $pos[1] + 10 - Random(0, 20, 1)
    MouseMove($x,$y)
Wend
Endfunc


Func Gpause()
While 1
   sleep(100)
Wend
Endfunc

Func Gexit()
    MsgBox(0, "exit box", "Script exited")
    Exit 0
EndFunc

Controls

  • Home : Start simulation.
  • pause : Pause simulation.
  • Esc : Exit simulation.

Or use my compiled version from here.

technosaurus
  • 7,676
  • 1
  • 30
  • 52
5

You can't expect anyone to be able to hold their hands perfectly steady, so one thing you can consider is,

  1. Explain to users what you're doing and,
  2. Make the clickable elements on the demo page much smaller than normal.
  3. Increasing the mouse sensitivity on the example system to the maximum.

My reasoning is (caveat, I am not an expert in ux or medicine) by making the click-able elements smaller, you creates a similar problem for most people that a person afflicted with Parkinson's disease would face with an everyday web site.

jdphenix
  • 15,022
  • 3
  • 41
  • 74
  • This is an interesting idea, too. I for sure are planning to make the clickable elements quite small, anyways. – Joshua Muheim Aug 13 '14 at 06:26
  • 2
    I'm afraid most mouse users can control their device down to 1-2 pixels if they concentrate - e.g. the shaking of the hand is below 1 pixel with the mouse settings I use. So probably not a universal solution if you buttons are larger than 1-2 pixels... – Jonas Heidelberg Aug 13 '14 at 14:26
  • I'd add #3, bumping the mouse speed and click settings to max – Ryan B Aug 13 '14 at 18:46
  • It would make sense to have a sort of "automatic volume control" on the mouse, amplifying small movements while making larger ones be closer to "normal". – Hot Licks Aug 14 '14 at 15:10
4

You can use an old-age simulation suit, such as the one described in this article... I suspect the hand-tremors part is just a vibrating motor strapped around the wrist, plus some thick gloves to make the hands generally clumsy.

user3067860
  • 456
  • 4
  • 11
  • Thank you. Although this is very interesting, we probably won't have money and time to put every visitor into the suit. ;) – Joshua Muheim Aug 12 '14 at 15:27
  • 5
    Wouldn't this be better suited as a comment? – Selali Adobor Aug 13 '14 at 02:03
  • Well, I was a little bit confused about the javascript and html tags, but since the asker also suggested using special mouse drivers (and then mentioned tablets) it seems like other solutions are welcome. Once you take away the specific technology limitation, this is an answer. This really is the way researchers in this field are solving the problem of simulating age-related disability. I also think you could DIY relatively cheaply if you just want the tremors--one of those velcro wrist weights and a vibrating motor, shouldn't be too hard. – user3067860 Aug 13 '14 at 13:45
4
  • In your DIV, CSS-hide the cursor using cursor:none;
  • Create a .png Cursor image and move it (left, top) with jQ on mousemove
  • Randomize the .png margin-left and margin-top using a setTimeout (to make the re-positioning smooth use CSS3 transition or do it with jQ .animate()).

Note: The script cannot know if the hand is still on the mouse ;)

function rand(min, max) {return Math.random() * (max - min) + min;}

var $cursor = $('div img');

$('div').mousemove(function(e) {  // Make .png follow the mouse coordinates
  $cursor.css({
    left: e.pageX,
    top:e.pageY
  });
}).hover(function(e){
  $cursor.toggle(); // Show .png cursor as we enter the DIV
});

(function tremor(){ // Add tremor to .png image
  $cursor.css({
      marginLeft: rand(-15,15), // arm tremor
      marginTop:  rand(-30,30)  // hand contractions
  });
  setTimeout(tremor, rand(50,100));
}());
div{
  position:absolute;
  background:#eee;
  height:100%;
  width:100%;
  cursor:none;
}

div img{
  display:none;
  position:absolute;
  transition: margin 0.2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div><img src="https://i.stack.imgur.com/KwMGA.png"></div>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
2

The low-level parts of simulating the tremor are well answered by now. I will add something focusing on the kind of tremor to simulate:

Most answers implement a mouse cursor that is moving on a random path with some fixed maximal step width in X and Y direction.

This should work well enough for the use case of making it hard to hit a specific area like a button.

For the more general issue of simulating UI problems caused by a tremor from Parkinson's disease, it would be at least interesting to actually simulate the hand movements of this kind of tremor.
I suspect the random walk may not be a very good approximation.

It may be hard to get hold of real hand trace data of tremor movement of course, but there are certainly papers about analyzing this kind of tremor:

The paper Parametric Representation of Hand Movement in Parkinson’s Disease is about how to best plot 3D hand movement traces.
The paper is paywalled, but the preview on the top right, labeled "Look Inside >" on the book image, shows some interesting plots of different representations of hand trace data.

Volker Siegel
  • 3,277
  • 2
  • 24
  • 35