I keep having to fix ARs that have to do with people mucking with the Cursor in non-UI processes. A couple years ago, Vassili Bykov (former VisualWorks hacker and my hero), put this excellent writeup together:
Cursors are typically used to show the current UI mode, or in other words some clue to how the application would interpret a click. For example, a paint application typically shows a magnifying glass cursor when clicking is interpreted as a zoom request, and some kind of a painting tool cursor when clicking is interpreted as painting with that tool.
The main point of this section is to point out a bad use of cursors which is unfortunately common in VisualWorks. Hopefully we'll get rid of it one day, and for now we should at least not perpetuate it.
It is the use of cursors to indicate background activity. This goes back to ST-80 use of read/write cursors to show disk activity. Back then, that was a legitimate use of cursors because reading/writing was a modal action. The system would become unresponsive, and the cursor would indicate that it's in a disk read mode.
VisualWorks does not enforce modality of input/output operations. As the result, we have situations when the system is responsive but the cursor is a twitching database disk pack because there is background database activity. That is wrong.
The cursor is a local indication device showing what will happen when the user clicks where the cursor is located. It must not change to show global information, such as to indicate a background database or other activity, if that activity doesn't affect current user interaction.
On the subject of hourglass cursors.
Everything said above applies to those. An hourglass cursor is an indication that the UI is in unresponsive mode. Being unresponsive is not the same as performing some activity, so applications should be careful not to show a global hourglass cursor when the activity is local and the rest of the UI is responsive.
Also, if the action that makes the UI unresponsive takes longer than a few seconds, an hourglass indication is not enough and the system should display a progress dialog with a (working!) Cancel button.
I really couldn't put it better myself. The cursor is a spatial feedback device, not a temporal one. The showWhile: pattern is one of the most deceptively attractive patterns for non-UI types, because it's quick and easy. It's a trap. Stay out of it.
It's instructive that we don't find the showWhile: pattern in other application development frameworks. It's not because they don't have blocks, one can get around that with start/end clauses. It's because this idea died a long time ago. We're playing catch up once again.
It's poor style to demand programmers eschew use of showWhile:, and yet not have a way to deal with existing call sites, or to give some feedback better than a hypnotizing whirly ball when the system is indeed unresponsive. The following describes a "back to the drawing board" design I worked up and prototyped about a year ago. The biggest problem with getting something like this integrated is that you have to change (read: remove code from) the VM, and the VM is no longer compatible with old images.
blockquote style="border:solid blue 2px; padding:4px;">We start by delineating between two different kinds of cursors. For now, we'll call them the busy cursor and the immediate cursor.
Immediate cursors are generally associated with spatial position of the mouse. They change as the mouse moves. They include changing the cursor as the mouse enters a view. Splitter controls are a good example. Most (all?) of the Cursor show invocations are of this sort.
Busy cursors are associated with a period where the UI is unresponsive, and it becomes necessary to give the user some feedback that things aren't just hung up. They generally show up after some period of inactivity, never immediately at the beginning of a computation. Examples of this are things like read and write cursors, or GC cursors. Cursor showWhile: calls tend to be of this type.
Both cursor types, must arbitrate a shared resource, the actual cursor itself.
The busy cursor will trump the immediate cursor. But only when the system is busy and has been so for a while. By busy we mean, that it's not responding to user input. Events are not being processed. Code that might change the cursor based on it's spatial position, is not running.
We can determine system business. For a given WindowManager, it is basically when the event loop has remained running without returning to fetch more events for a longer than desired time.
Requisite in this design, is setting the Cursor of a Window, rather than a system wide global cursor. This removes a bit of overhead and impedance mismatch on the VMs part. All 3 primary display platforms have facilities for associating Cursors with Windows. I have built versions of the VM that provide this support for both X11 and OSX, basically a single primitive to "set the cursor of a window."
When a WindowManager finds itself busy (because a watchdog process notes that it hasn't return back to grab or wait for more events in a while), it will set the cursor of it's windows to be the busy cursor. When it is unbusy, it will restore them to the cursor they believe they should have (known by an instance variable added to Window). When an immediate cursor is set, it is just a matter of setting the cursor of the window. So we associate the current busy cursor with the WindowManager, and the immediate cursor with the Window. The effective cursor is the immediate cursor, unless the window manager is busy.
The prototypes done for X11 and OSX actually make cursors quite "snappy". And allows, for example, one to have two workspaces, one which has a long running computation, and the other which is available for interaction. When the cursor comes over the long running one, it shows the busy cursor (execute for this case). But is normal for the other workspace.