WaitNextEvent is the (in)famous API call in MacOS (pre OS X) which causes the app to surrender CPU time to other processes. MacOS event handling works by having apps call WaitNextEvent, at which point an EventRecord describing the next event for that app listed in the event queue is filled. A (very simplified) example:
EventRecord *event;

WaitNextEvent(everyEvent, event, 1, NULL);
switch(event->what) {
  // Put event handling routines here.
}

In order for MacOS's multitasking to work at all, every single application running must call WaitNextEvent each time it iterates its event loop. Some apps, of course, fail to do so. One such circumstance is when an app opts to use GetNextEvent, which has the same local results as WaitNextEvent, but it instead does not surrender CPU time to other apps, it simply records its own next event, and then proceeds to continue monopolizing the CPU. (This is the call programmers would have used before it was possible to open more than one application to begin with) An example would be a CPU intensive Photoshop plugin, a game, SETI@Home, or an emulator.

Some apps also might be primitive to the extent that they ignore event processing altogether and just run through their main subroutine, then terminate. During this time, nothing else can happen on the system. This is, in fact, a holdover from when MacOS was truly a single-process system. The unfortunate fact is that Apple just stuck a cheap hack in the API to support multitasking, rather than re-writing event and process handling from scratch.

Only with MacOS X is this system of event handling obsoleted in favor of Unix-style preemptive multitasking. It's amazing MacOS survived as long as it did with such a poor excuse for a multitasking environment.