Windows3 is non-preemptive. Its input system was designed around this fact; only one app is allowed to process input at one time. This makes synchronization of input related state very easy – there is only one copy of the state and it is globally shared throughout the system. It also makes input-ahead (mouse and keyboard) straight forward – input is assigned to an application as it is read out of a shared `system input queue'; that way who it is assigned to reflects the up-to-the-moment system state, thereby getting perfect `type-ahead'.
In order to read messages out of this queue in an orderly way and process them one at a time in a serialized fashion, the Win3 system only lets one application read from this system queue at a time – either the application which has the keyboard focus (for key messages), or the application the mouse event is for (for mouse messages). This model is simple, but the down side is that the input system essentially hangs if that chosen application is not reading input for some reason (internally hung, recalcing, repaginating, printing, floodfilling, saving a file, reading a file, waiting on device timeouts, etc). This means the user is cut off, cannot switch to other applications or use any other applications in any way.
This worked ok for Windows since it was non-preemptive. Apps that went into loops needed to call Yield anyway to let other apps run, so as long as they also check for and processed input in these loops, the system would run/ hobble along. Unfortunately the exact same input model was ported to PM, a preemptive environment, where it didn't hold up to user expectations of a true multitasking environment – it turned out to be unacceptable to expect developers to carry the brunt of this problem for the system by writing their apps so their input thread would always be ready to read input. Apps commonly aren't written this way, and certainly Windows apps are not.