/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
 *
 * Pigment media rendering library
 *
 * Copyright © 2006, 2007, 2008 Fluendo Embedded S.L.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Loïc Molinari <loic@fluendo.com>
 */

#ifndef __PGM_EVENTS_H__
#define __PGM_EVENTS_H__

/* pgmevents.h and pgmviewport.h include eachother */
typedef struct _PgmEventAny          PgmEventAny;
typedef struct _PgmEventMotion       PgmEventMotion;
typedef struct _PgmEventButton       PgmEventButton;
typedef struct _PgmEventScroll       PgmEventScroll;
typedef struct _PgmEventKey          PgmEventKey;
typedef struct _PgmEventExpose       PgmEventExpose;
typedef struct _PgmEventConfigure    PgmEventConfigure;
typedef struct _PgmEventDnd          PgmEventDnd;
typedef struct _PgmEventState        PgmEventState;
typedef struct _PgmEventWin32Message PgmEventWin32Message;
typedef union  _PgmEvent             PgmEvent;

#include <glib-object.h>
#ifdef WIN32
#include <Windows.h>
#endif /* WIN32 */

G_BEGIN_DECLS

#define PGM_TYPE_EVENT (pgm_event_get_type ())

/**
 * PgmEventType:
 * @PGM_NOTHING: a special code to indicate a null event.
 * @PGM_MOTION_NOTIFY: the pointer has entered the window.
 * @PGM_BUTTON_PRESS: a mouse button has been pressed.
 * @PGM_DOUBLE_BUTTON_PRESS: a mouse button has been clicked 2 times in a short
 * period of time. Note that each click also generates a %PGM_BUTTON_PRESS
 * event.
 * @PGM_TRIPLE_BUTTON_PRESS: a mouse button has been clicked 3 times in a short
 * period of time. Note that each click also generates a %PGM_BUTTON_PRESS
 * event.
 * @PGM_BUTTON_PRESSURE: a mouse button pressure has changed.
 * @PGM_BUTTON_RELEASE: a mouse button has been released.
 * @PGM_KEY_PRESS: a key has been pressed.
 * @PGM_KEY_RELEASE: a key has been released.
 * @PGM_EXPOSE: the window has become visible and needs to be redrawn.
 * @PGM_CONFIGURE: the size or the position of the viewport has changed.
 * @PGM_DRAG_MOTION: the mouse has moved in the viewport while a drag is in
 * progress.
 * @PGM_DRAG_DROP: the mouse has dropped data onto the viewport.
 * @PGM_DRAG_LEAVE: the mouse has left the viewport while a drag is in progress.
 * @PGM_SCROLL: the scroll wheel was turned.
 * @PGM_STATE: the state of a viewport has changed.
 * @PGM_DELETE: the window manager has requested that the toplevel window be
 * destroyed, usually when the user clicks on a special icon in the title bar.
 * @PGM_WIN32_MESSAGE: a Win32 message has been received (Only used on Windows).
 *
 * Specifies the type of the event.
 */
typedef enum {
  PGM_NOTHING             = -1,
  PGM_MOTION_NOTIFY       = 0,
  PGM_BUTTON_PRESS        = 1,
  PGM_DOUBLE_BUTTON_PRESS = 2,
  PGM_TRIPLE_BUTTON_PRESS = 3,
  PGM_BUTTON_PRESSURE     = 4,
  PGM_BUTTON_RELEASE      = 5,
  PGM_KEY_PRESS           = 6,
  PGM_KEY_RELEASE         = 7,
  PGM_EXPOSE              = 8,
  PGM_CONFIGURE           = 9,
  PGM_DRAG_MOTION         = 10,
  PGM_DRAG_DROP           = 12,
  PGM_DRAG_LEAVE          = 13,
  PGM_SCROLL              = 14,
  PGM_STATE               = 15,
  PGM_DELETE              = 16,
  PGM_WIN32_MESSAGE       = 17
} PgmEventType;

/**
 * PgmModifierType:
 * @PGM_SHIFT_MASK: the Shift key.
 * @PGM_CAPSLOCK_MASK: the Caps Lock.
 * @PGM_CONTROL_MASK: the Control key.
 * @PGM_ALT_MASK: the Alt key.
 * @PGM_NUMLOCK_MASK: the Num Lock.
 *
 * A set of bit-flags to indicate the state of modifier keys. Typical modifier
 * keys are Shift, Control, Alt and CapsLock.
 */
typedef enum {
  PGM_SHIFT_MASK    = (1 << 0),
  PGM_CAPSLOCK_MASK = (1 << 1),
  PGM_CONTROL_MASK  = (1 << 2),
  PGM_ALT_MASK      = (1 << 3),
  PGM_NUMLOCK_MASK  = (1 << 4)
} PgmModifierType;

/**
 * PgmButtonType:
 * @PGM_BUTTON_LEFT: the left mouse button.
 * @PGM_BUTTON_MIDDLE: the middle mouse button.
 * @PGM_BUTTON_RIGHT: the right mouse button.
 *
 * The mouse button type.
 */
typedef enum {
  PGM_BUTTON_LEFT   = (1 << 0),
  PGM_BUTTON_MIDDLE = (1 << 1),
  PGM_BUTTON_RIGHT  = (1 << 2)
} PgmButtonType;

/**
 * PgmScrollDirection:
 * @PGM_SCROLL_UP: the scrolling in the upward direction.
 * @PGM_SCROLL_DOWN: the scrolling in the downward direction.
 *
 * The mouse wheel scrolling directions.
 */
typedef enum {
  PGM_SCROLL_UP,
  PGM_SCROLL_DOWN
} PgmScrollDirection;

/**
 * PgmViewportState:
 * @PGM_VIEWPORT_ICONIFIED: The viewport is minimized.
 *
 * Specifies the state of a viewport.
 */
typedef enum {
  PGM_VIEWPORT_ICONIFIED  = (1 << 0)
} PgmViewportState;

/**
 * PgmEventAny:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 *
 * Contains the fields which are common to all event structs. Any event
 * pointer can safely be cast to a pointer to a #PgmEventAny to access these
 * fields.
 */
struct _PgmEventAny {
  PgmEventType type;
  guint8       source;
};

/**
 * PgmEventMotion:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @time: the time of the event in milliseconds.
 * @x: the x coordinate of the pointer relative to the window.
 * @y: the y coordinate of the pointer relative to the window.
 * @pressure: the pressure force, set to 0 when not used with a touch screen.
 *
 * Generated when the pointer moves.
 */
struct _PgmEventMotion {
  PgmEventType type;
  guint8       source;
  guint32      time;
  gfloat       x, y;
  guint32      pressure;
};

/**
 * PgmEventButton:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @time: the time of the event in milliseconds.
 * @x: the x coordinate of the pointer relative to the window.
 * @y: the y coordinate of the pointer relative to the window.
 * @button: the button which was pressed or released.
 * @pressure: the pressure force, set to 0 when not used with a touch screen.
 *
 * Used for button press and button release events.
 */
struct _PgmEventButton {
  PgmEventType  type;
  guint8        source;
  guint32       time;
  gfloat        x, y;
  PgmButtonType button;
  guint32       pressure;
};

/**
 * PgmEventScroll:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @time: the time of the event in milliseconds.
 * @x: the x coordinate of the pointer relative to the window.
 * @y: the y coordinate of the pointer relative to the window.
 * @direction: the scroll wheel direction.
 *
 * Generated when the mouse wheel is turned.
 */
struct _PgmEventScroll {
  PgmEventType       type;
  guint8             source;
  guint32            time;
  gfloat             x, y;
  PgmScrollDirection direction;
};

/**
 * PgmEventKey:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @time: the time of the event in milliseconds.
 * @modifier: A bit-mask representing the state of the modifier keys (e.g.
 * Control, Shift and Alt), see #PgmModifierType.
 * @keyval: the key that was pressed or released. See the pgm/pgmkeysyms.h
 * header file for a complete list of Pigment key codes.
 * @hardware_keycode: the raw code of the key that was pressed or released.
 *
 * Describes a key press or key release event.
 */
struct _PgmEventKey {
  PgmEventType type;
  guint8       source;
  guint32      time;
  guint        modifier;
  guint        keyval;
  guint16      hardware_keycode;
};

/**
 * PgmEventExpose:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 *
 * Generated when a window becomes visible and needs to be redrawn.
 */
struct _PgmEventExpose {
  PgmEventType type;
  guint8       source;
};

/**
 * PgmEventConfigure:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @x: the new x coordinate of the window.
 * @y: the new y coordinate of the window.
 * @width: the new width of the viewport.
 * @height: the new height of the viewport.
 *
 * Generated when a viewport size or position has changed.
 */
struct _PgmEventConfigure {
  PgmEventType type;
  guint8       source;
  gint         x, y;
  gint         width, height;
};

/**
 * PgmEventDnd:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @time: the time of the event in milliseconds.
 * @x: the new x coordinate of the window.
 * @y: the new y coordinate of the window.
 * @uri: the list of URI as a #NULL-terminated array of strings.
 *
 * Describes a drag motion, drop, or leave event.
 */
struct _PgmEventDnd {
  PgmEventType   type;
  guint8         source;
  guint32        time;
  gfloat         x, y;
  gchar        **uri;
};

/**
 * PgmEventState:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @changed_mask: mask specifying what viewport flags have changed.
 * @state_mask: mask specifying the new viewport flags.
 *
 * Generated when the state of a viewport changes.
 */
struct _PgmEventState {
  PgmEventType     type;
  guint8           source;
  PgmViewportState changed_mask;
  PgmViewportState state_mask;
};

#ifdef WIN32
/**
 * PgmEventWin32Message:
 * @type: the type of the event.
 * @source: the source field that can be filled by applications to indicate the
 * source of the event (mouse, pen, remote control, etc).
 * @time: the time of the event in milliseconds.
 * @message: the Win32 message value.
 * @wparam: additional message information depending on the message value.
 * @lparam: additional message information depending on the message value.
 *
 * Describes a Win32 message.
 */
struct _PgmEventWin32Message {
  PgmEventType type;
  guint8       source;
  guint32      time;
  UINT         message;
  WPARAM       wparam;
  LPARAM       lparam;
};
#endif /* WIN32 */

/**
 * PgmEvent:
 *
 * <para>
 * The #PgmEvent struct contains a union of all of the event structs,
 * and allows access to the data fields in a number of ways.
 * </para>
 * <para>
 * The event type is always the first field in all of the event structs, and
 * can always be accessed with the following code, no matter what type of event
 * it is:
 * <informalexample>
 * <programlisting language="c">
 *   PgmEvent *event;  
 *   PgmEventType type;
 *   type = event->type;
 * </programlisting>
 * </informalexample>
 * </para>
 * <para>
 * To access other fields of the event structs, the pointer to the event can be
 * cast to the appropriate event struct pointer, or the union member name can be
 * used. For example if the event type is %PGM_BUTTON_PRESS then the x coordinate
 * of the button press can be accessed with:
 * <informalexample>
 * <programlisting language="c">
 *   PgmEvent *event;  
 *   gfloat x;
 *   x = ((PgmEventButton*) event)->x;
 * </programlisting>
 * </informalexample>
 * or with:
 * <informalexample>
 * <programlisting language="c">
 *   PgmEvent *event;  
 *   gfloat x;
 *   x = event->button.x;
 * </programlisting>
 * </informalexample>
 * </para>
 */
union _PgmEvent {
  PgmEventType         type;
  PgmEventAny          any;
  PgmEventMotion       motion;
  PgmEventButton       button;
  PgmEventScroll       scroll;
  PgmEventKey          key;
  PgmEventExpose       expose;
  PgmEventConfigure    configure;
  PgmEventDnd          dnd;
  PgmEventState        state;
#ifdef WIN32
  PgmEventWin32Message win32_message;
#endif /* WIN32 */
};

GType     pgm_event_get_type    (void);

PgmEvent *pgm_event_new         (PgmEventType type);
PgmEvent *pgm_event_copy        (PgmEvent *event);
void      pgm_event_free        (PgmEvent *event);

guint32   pgm_keyval_to_unicode (guint keyval) G_GNUC_CONST;

G_END_DECLS

#endif /* __PGM_EVENTS_H__ */
