public void read_and_dispatch_event () {
    Event first_event = display.next_event ();
   
    /* Race conditions: while reading an event of a window, the window may
     * have already unmapped or even destroyed. UnmapNotify or
     * DestroyNotify of the window may come later in the event queue,
     * or they are just being generated in the server and not yet reach our
     * queue.
     *
     * Solution: We MUST grab the server to halt further event generations
     * during processing events. Before acting on any event with {@link
     * #when(Event)}, we pull all events in the network and check for
     * <code>UnmapNotify</code> and <code>DestroyNotify</code>. 
     * Note we force X server to flush all pending events for us using the
     * technique described {@link Connection#pull_all_events() here}. We then
     * set {@link Client#early_unmapped} and {@link Client#early_destroyed}
     * accordingly. Event handling routines may check these client flags
     * and decide if they should abort the operations, as the window may
     * have already unmapped/destroyed.
     *
     * For example, {@link #when_key_press(KeyPress)} depends on the
     * visibility of a window and thus aborts the operations if the window
     * is already unmapped or destroyed. On the other hand, {@link
     * #when_property_notify(PropertyNotify)} depends only on the
     * liveness of a window and thus aborts the operations only when the
     * window is already destroyed.
     *
     * To street test the correctness of this method (or that of other
     * window manager), drag around any icon in Netscape so that Netscape
     * will quickly map, unmap, and destroy windows. For instance, remove
     * <code>display.check_error ();</code> here and run the test, Puppet
     * will produce an {@link Error#BAD_WINDOW} error.
     */
    display.grab_server ();
    
    display.check_error ();
    List other_events = display.in.pull_all_events ();
    
    for (Iterator it=other_events.iterator (); it.hasNext ();) {       
      Event event = (Event) it.next ();

      if (event.code () == DestroyNotify.CODE) {	
        Client client = (Client) Client.intern (display, 
          ((DestroyNotify) event).window_id);
        client.early_destroyed = true;

      } else if (event.code () == UnmapNotify.CODE) {
        Client client = (Client) Client.intern (display, 
          ((UnmapNotify) event).window_id);
        client.early_unmapped = true;
      }
    }


    when (first_event);    


    /* Grabbing server significantly hinders responsiveness of this
     * window manager. While we have to trade speed for correctness,
     * we can aggregate grabbing and ungrabbing by processing all events in
     * queue at once between grabbings.
     */
    for (Iterator it=other_events.iterator (); it.hasNext ();)
      when ((Event) it.next ());


    /* We must flush all requests before un-grabbing the server, so that
     * windows in the requests are guaranteed to be alive.
     */
    display.flush ();

    display.ungrab_server ();
  }