/* XEventPump.java -- Pumps events from X to AWT
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.awt.peer.x;

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.PaintEvent;
import java.awt.event.WindowEvent;
import java.util.HashMap;

import gnu.java.awt.ComponentReshapeEvent;
import gnu.x11.Atom;
import gnu.x11.Display;
import gnu.x11.event.ButtonPress;
import gnu.x11.event.ButtonRelease;
import gnu.x11.event.ClientMessage;
import gnu.x11.event.ConfigureNotify;
import gnu.x11.event.DestroyNotify;
import gnu.x11.event.Event;
import gnu.x11.event.Expose;
import gnu.x11.event.Input;
import gnu.x11.event.KeyPress;
import gnu.x11.event.KeyRelease;
import gnu.x11.event.MotionNotify;
import gnu.x11.event.PropertyNotify;
import gnu.x11.event.ResizeRequest;
import gnu.x11.event.UnmapNotify;

/**
 * Fetches events from X, translates them to AWT events and pumps them up
 * into the AWT event queue.
 *
 * @author Roman Kennke (kennke@aicas.com)
 */
public class XEventPump
  implements Runnable
{

  /**
   * The X Display from which we fetch and pump up events.
   */
  private Display display;

  /**
   * Maps X Windows to AWT Windows to be able to correctly determine the
   * event targets.
   */
  private HashMap windows;

  /**
   * Indicates if we are currently inside a drag operation. This is
   * set to the button ID when a button is pressed and to -1 (indicating
   * that no drag is active) when the mouse is released.
   */
  private int drag;

  /**
   * Creates a new XEventPump for the specified X Display.
   *
   * @param d the X Display
   */
  XEventPump(Display d)
  {
    display = d;
    windows = new HashMap();
    drag = -1;
    Thread thread = new Thread(this, "X Event Pump");
    thread.setDaemon(true);
    thread.start();
  }

  /**
   * The main event pump loop. This basically fetches events from the
   * X Display and pumps them into the system event queue.
   */
  public void run()
  {
    while (display.connected)
      {
        try
          {
            Event xEvent = display.next_event();
            handleEvent(xEvent);
          }
        catch (ThreadDeath death)
          {
            // If someone wants to kill us, let them.
            return;
          }
        catch (Throwable x)
          {
            System.err.println("Exception during event dispatch:");
            x.printStackTrace(System.err);
          }
      }
  }

  /**
   * Adds an X Window to AWT Window mapping. This is required so that the
   * event pump can correctly determine the event targets.
   *
   * @param xWindow the X Window
   * @param awtWindow the AWT Window
   */
  void registerWindow(gnu.x11.Window xWindow, Window awtWindow)
  {
    if (XToolkit.DEBUG)
      System.err.println("registering window id: " + xWindow.id);
    windows.put(new Integer(xWindow.id), awtWindow);
  }

  void unregisterWindow(gnu.x11.Window xWindow)
  {
    windows.remove(new Integer(xWindow.id));
  }

  private void handleButtonPress(ButtonPress event)
  {
    Integer key = new Integer(event.getEventWindowID());
    Window awtWindow = (Window) windows.get(key);

    // Create and post the mouse event.
    int button = event.detail();

    // AWT cannot handle more than 3 buttons and expects 0 instead.
    if (button >= gnu.x11.Input.BUTTON3)
      button = 0;
    drag = button;

    Component target =
      findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
    if(target == null)
      {
        target = awtWindow;
      }
    
    MouseEvent mp = new MouseEvent(target, MouseEvent.MOUSE_PRESSED,
                                   System.currentTimeMillis(),
                                   KeyboardMapping.mapModifiers(event.getState())
                                     | buttonToModifier(button),
                                   event.getEventX(), event.getEventY(),
                                   1, false, button);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mp);
  }
  
  private void handleButtonRelease(ButtonRelease event)
  {
    Integer key = new Integer(event.getEventWindowID());
    Window awtWindow = (Window) windows.get(key);

    int button = event.detail();
    
    // AWT cannot handle more than 3 buttons and expects 0 instead.
    if (button >= gnu.x11.Input.BUTTON3)
      button = 0;
    drag = -1;
    
    Component target =
      findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
    if(target == null)
      {
        target = awtWindow;
      }
    
    MouseEvent mr = new MouseEvent(target, MouseEvent.MOUSE_RELEASED,
                                   System.currentTimeMillis(),
                                   KeyboardMapping.mapModifiers(event.getState())
                                     | buttonToModifier(button),
                                   event.getEventX(), event.getEventY(),
                                   1, false, button);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mr);
  }
  
  
  private void handleMotionNotify(MotionNotify event)
  {
    Integer key = new Integer(event.getEventWindowID());
    Window awtWindow = (Window) windows.get(key);

    int button = event.detail();
    
    // AWT cannot handle more than 3 buttons and expects 0 instead.
    if (button >= gnu.x11.Input.BUTTON3)
      button = 0;

    MouseEvent mm = null;
    if (drag == -1)
      {
        mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_MOVED,
                            System.currentTimeMillis(),
                            KeyboardMapping.mapModifiers(event.getState())
                              | buttonToModifier(button),
                            event.getEventX(), event.getEventY(),
                            1, false);

      }
    else
      {
        mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_DRAGGED,
                            System.currentTimeMillis(),
                            KeyboardMapping.mapModifiers(event.getState())
                              | buttonToModifier(drag),
                            event.getEventX(), event.getEventY(),
                            1, false);
      }
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mm);
  }
   
  // FIME: refactor and make faster, maybe caching the event and handle
  // and/or check timing (timing is generated for PropertyChange)?
  private void handleExpose(Expose event)
  {
    Integer key = new Integer(event.window_id);
    Window awtWindow = (Window) windows.get(key);
    
    if (XToolkit.DEBUG)
      System.err.println("expose request for window id: " + key);
    
    Rectangle r = new Rectangle(event.x(), event.y(), event.width(),
                                event.height());
    // We need to clear the background of the exposed rectangle.
    assert awtWindow != null : "awtWindow == null for window ID: " + key;
     
    Graphics g = awtWindow.getGraphics();
    g.clearRect(r.x, r.y, r.width, r.height);
    g.dispose();
    
    XWindowPeer xwindow = (XWindowPeer) awtWindow.getPeer();
    Insets i = xwindow.insets();
    if (event.width() != awtWindow.getWidth() - i.left - i.right
        || event.height() != awtWindow.getHeight() - i.top - i.bottom)
      {
        int w = event.width();
        int h = event.height();
        int x = xwindow.xwindow.x;
        int y = xwindow.xwindow.y;
        
        if (XToolkit.DEBUG)
          System.err.println("Setting size on AWT window: " + w
                           + ", " + h + ", " + awtWindow.getWidth()
                           + ", " + awtWindow.getHeight());
        
        // new width and height
        xwindow.xwindow.width = w;
        xwindow.xwindow.height = h;
        
        // reshape the window
        ComponentReshapeEvent cre =
          new ComponentReshapeEvent(awtWindow, x, y, w, h);
        awtWindow.dispatchEvent(cre);
      }
  
    ComponentEvent ce =
      new ComponentEvent(awtWindow, ComponentEvent.COMPONENT_RESIZED);
    awtWindow.dispatchEvent(ce);
    
    PaintEvent pev = new PaintEvent(awtWindow, PaintEvent.UPDATE, r);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(pev);
  }
    
  private void handleDestroyNotify(DestroyNotify destroyNotify)
  {
    if (XToolkit.DEBUG)
      System.err.println("DestroyNotify event: " + destroyNotify);
    
    Integer key = new Integer(destroyNotify.event_window_id);
    Window awtWindow = (Window) windows.get(key);
    
    AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_CLOSED);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
  }
  
  private void handleClientMessage(ClientMessage clientMessage)
  {
    if (XToolkit.DEBUG)
      System.err.println("ClientMessage event: " + clientMessage);
    
    if (clientMessage.delete_window())
      {
        if (XToolkit.DEBUG)
          System.err.println("ClientMessage is a delete_window event");
        
        Integer key = new Integer(clientMessage.window_id);
        Window awtWindow = (Window) windows.get(key);
        
        AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
      }
  }
  
  private void handleEvent(Event xEvent)
  {
    if (XToolkit.DEBUG)
      System.err.println("fetched event: " + xEvent);
    
    switch (xEvent.code() & 0x7f)
    {
    case ButtonPress.CODE:
      this.handleButtonPress((ButtonPress) xEvent);
      break;
    case ButtonRelease.CODE:
      this.handleButtonRelease((ButtonRelease) xEvent); 
      break;
    case MotionNotify.CODE:
      this.handleMotionNotify((MotionNotify) xEvent); 
      break;
    case Expose.CODE:
      this.handleExpose((Expose) xEvent);
      break;
    case KeyPress.CODE:
    case KeyRelease.CODE:
      Integer key = new Integer(((Input) xEvent).getEventWindowID());
      Window awtWindow = (Window) windows.get(key);
      handleKeyEvent(xEvent, awtWindow);
      break;
    case DestroyNotify.CODE:
      this.handleDestroyNotify((DestroyNotify) xEvent);
      break;
    case ClientMessage.CODE:
      this.handleClientMessage((ClientMessage) xEvent);
      break;
    case PropertyNotify.CODE:
      key = new Integer (((PropertyNotify) xEvent).getWindowID());
      awtWindow = (Window) windows.get(key);
      AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_STATE_CHANGED);
      Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
      break;
    default:
      if (XToolkit.DEBUG)
        System.err.println("Unhandled X event: " + xEvent);
    }
  }

  /**
   * Handles key events from X.
   *
   * @param xEvent the X event
   * @param awtWindow the AWT window to which the event gets posted
   */
  private void handleKeyEvent(Event xEvent, Window awtWindow)
  {
    Input keyEvent = (Input) xEvent;
    int xKeyCode = keyEvent.detail();
    int xMods = keyEvent.getState();
    int keyCode = KeyboardMapping.mapToKeyCode(xEvent.display.input, xKeyCode,
                                               xMods);
    char keyChar = KeyboardMapping.mapToKeyChar(xEvent.display.input, xKeyCode,
                                                xMods);
    if (XToolkit.DEBUG)
      System.err.println("XEventPump.handleKeyEvent: " + xKeyCode + ", "
                         + xMods + ": " + ((int) keyChar) + ", " + keyCode);
    int awtMods = KeyboardMapping.mapModifiers(xMods);
    long when = System.currentTimeMillis();
    KeyEvent ke;
    if (keyEvent.code() == KeyPress.CODE)
      {
        ke = new KeyEvent(awtWindow, KeyEvent.KEY_PRESSED, when,
                          awtMods, keyCode,
                          KeyEvent.CHAR_UNDEFINED);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
        if (keyChar != KeyEvent.CHAR_UNDEFINED)
          {
            ke = new KeyEvent(awtWindow, KeyEvent.KEY_TYPED, when,
                              awtMods, KeyEvent.VK_UNDEFINED,
                              keyChar);
            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
          }
          
      }
    else
      {
        ke = new KeyEvent(awtWindow, KeyEvent.KEY_RELEASED, when,
                          awtMods, keyCode,
                          KeyEvent.CHAR_UNDEFINED);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
      }

  }

  /** Translates an X button identifier to the AWT's MouseEvent modifier
   *  mask. As the AWT cannot handle more than 3 buttons those return
   *  <code>0</code>.
   */
  static int buttonToModifier(int button)
  {
    switch (button)
    {
      case gnu.x11.Input.BUTTON1:
        return MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON1_MASK;
      case gnu.x11.Input.BUTTON2:
        return MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON2_MASK;
      case gnu.x11.Input.BUTTON3:
        return MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON3_MASK;
    }

    return 0;        
  }
  
  /**
   * Finds the heavyweight mouse event target.
   *
   * @param src the original source of the event
   *
   * @param pt the event coordinates
   *
   * @return the real mouse event target
   */
  private Component findMouseEventTarget(Component src, int x, int y)
  {
    Component found = null;
    if (src instanceof Container)
      {
        Container cont = (Container) src;
        int numChildren = cont.getComponentCount();
        for (int i = 0; i < numChildren && found == null; i++)
          {
            Component child = cont.getComponent(i);
            if (child != null && child.isVisible()
                && child.contains(x - child.getX(), y - child.getY()))
              {
                if (child instanceof Container)
                  {
                    Component deeper = findMouseEventTarget(child,
                                                            x - child.getX(),
                                                            y - child.getY());
                    if (deeper != null)
                      found = deeper;
                  }
                else if (! child.isLightweight())
                  found = child;
              }
          }
      }

    // Consider the source itself.
    if (found == null && src.contains(x, y) && ! src.isLightweight())
      found = src;

    return found;
  }
}
