/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program 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 3 of the License, or * (at your option) any later version. * * This program 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 this program. If not, see . * */ #ifndef COMMON_EVENTS_H #define COMMON_EVENTS_H #include "common/keyboard.h" #include "common/queue.h" #include "common/rect.h" #include "common/noncopyable.h" #include "common/list.h" #include "common/singleton.h" namespace Common { /** * @defgroup common_events Events * @ingroup common * * @brief The types of events backends may generate. * * @todo Merge EVENT_LBUTTONDOWN, EVENT_RBUTTONDOWN and EVENT_WHEELDOWN; * likewise EVENT_LBUTTONUP, EVENT_RBUTTONUP, EVENT_WHEELUP. * To do that, we just have to add a field to the Event which * indicates which button was pressed. * @{ */ enum EventType { EVENT_INVALID = 0, /** A key was pressed, details in Event::kbd. */ EVENT_KEYDOWN = 1, /** A key was released, details in Event::kbd. */ EVENT_KEYUP = 2, /** The mouse moved, details in Event::mouse. */ EVENT_MOUSEMOVE = 3, EVENT_LBUTTONDOWN = 4, EVENT_LBUTTONUP = 5, EVENT_RBUTTONDOWN = 6, EVENT_RBUTTONUP = 7, EVENT_WHEELUP = 8, EVENT_WHEELDOWN = 9, EVENT_MBUTTONDOWN = 13, EVENT_MBUTTONUP = 14, EVENT_MAINMENU = 15, EVENT_RETURN_TO_LAUNCHER = 16, EVENT_MUTE = 17, EVENT_QUIT = 10, EVENT_SCREEN_CHANGED = 11, /** The input devices have changed, input-related configuration must be reapplied. */ EVENT_INPUT_CHANGED = 35, /** * The backend requests the AGI engine's predictive dialog to be shown. * * @todo Fingolfin suggests that it would be of better value to expand * on this notion by generalizing its use. For example the backend could * use events to ask for the save game dialog or to pause the engine. * An associated enumerated type can accomplish this. **/ EVENT_PREDICTIVE_DIALOG = 12, EVENT_CUSTOM_BACKEND_ACTION_START = 18, EVENT_CUSTOM_BACKEND_ACTION_END = 19, EVENT_CUSTOM_BACKEND_ACTION_AXIS = 34, EVENT_CUSTOM_ENGINE_ACTION_START = 20, EVENT_CUSTOM_ENGINE_ACTION_END = 21, EVENT_VIRTUAL_KEYBOARD = 22, EVENT_DROP_FILE = 23, EVENT_JOYAXIS_MOTION = 24, EVENT_JOYBUTTON_DOWN = 25, EVENT_JOYBUTTON_UP = 26, EVENT_CLIPBOARD_UPDATE = 27, EVENT_CUSTOM_BACKEND_HARDWARE = 28, EVENT_DEBUGGER = 29, /** * Additional mouse events, details in Event::mouse. * * Note that X1 and X2 are usually back and forward, however * this cannot be guaranteed on all platforms. */ EVENT_X1BUTTONDOWN = 30, EVENT_X1BUTTONUP = 31, EVENT_X2BUTTONDOWN = 32, EVENT_X2BUTTONUP = 33, /** ScummVM has gained or lost focus. */ EVENT_FOCUS_GAINED = 36, EVENT_FOCUS_LOST = 37 }; const int16 JOYAXIS_MIN = -32768; const int16 JOYAXIS_MAX = 32767; /** * Data structure for joystick events. */ struct JoystickState { /** The axis for EVENT_JOYAXIS_MOTION events. */ byte axis; /** The new axis position for EVENT_JOYAXIS_MOTION events. */ int16 position; /** * The button index for EVENT_JOYBUTTON_DOWN/UP events. * * Some of the button indices match well-known game controller * buttons. See JoystickButton. */ uint8 button; JoystickState() : axis(0), position(0), button(0) {} }; /** * The list of named buttons available from a joystick. */ enum JoystickButton { JOYSTICK_BUTTON_INVALID, JOYSTICK_BUTTON_A, JOYSTICK_BUTTON_B, JOYSTICK_BUTTON_X, JOYSTICK_BUTTON_Y, JOYSTICK_BUTTON_BACK, JOYSTICK_BUTTON_GUIDE, JOYSTICK_BUTTON_START, JOYSTICK_BUTTON_LEFT_STICK, JOYSTICK_BUTTON_RIGHT_STICK, JOYSTICK_BUTTON_LEFT_SHOULDER, JOYSTICK_BUTTON_RIGHT_SHOULDER, JOYSTICK_BUTTON_DPAD_UP, JOYSTICK_BUTTON_DPAD_DOWN, JOYSTICK_BUTTON_DPAD_LEFT, JOYSTICK_BUTTON_DPAD_RIGHT }; /** * The list of named axes available from a joystick. */ enum JoystickAxis { JOYSTICK_AXIS_LEFT_STICK_X, JOYSTICK_AXIS_LEFT_STICK_Y, JOYSTICK_AXIS_RIGHT_STICK_X, JOYSTICK_AXIS_RIGHT_STICK_Y, JOYSTICK_AXIS_LEFT_TRIGGER, JOYSTICK_AXIS_RIGHT_TRIGGER }; /** * The list named buttons available from a mouse. */ enum MouseButton { MOUSE_BUTTON_LEFT = 0, MOUSE_BUTTON_RIGHT = 1, MOUSE_BUTTON_MIDDLE = 2, MOUSE_WHEEL_UP = 3, MOUSE_WHEEL_DOWN = 4, MOUSE_BUTTON_X1 = 5, MOUSE_BUTTON_X2 = 6 }; /** Used by @ref ArtificialEventSource. */ typedef uint32 CustomEventType; /** * Data structure for an event. A pointer to an instance of Event * can be passed to pollEvent. */ struct Event { /** The type of the event. */ EventType type; /** * True if this is a key-down repeat event. * * Only valid for EVENT_KEYDOWN events. */ bool kbdRepeat; /** * Keyboard data; only valid for keyboard events (EVENT_KEYDOWN and * EVENT_KEYUP). For all other event types, content is undefined. */ KeyState kbd; /** * The mouse coordinates, in virtual screen coordinates. Only valid * for mouse events. * 'Virtual screen coordinates' refers to the coordinate system of the * screen area as defined by the most recent call to initSize(). */ Point mouse; /** Refers to an event generated by @ref ArtificialEventSource. */ CustomEventType customType; /** The path of the file or directory dragged to the ScummVM window. */ Common::String path; /** * Mouse movement since the last mouse movement event. */ Common::Point relMouse; /** * Joystick data; only valid for joystick events (EVENT_JOYAXIS_MOTION, * EVENT_JOYBUTTON_DOWN and EVENT_JOYBUTTON_UP). */ JoystickState joystick; Event() : type(EVENT_INVALID), kbdRepeat(false), customType(0) { } }; /** * Determine whether an event is a mouse event. * * Mouse events have valid mouse coordinates. */ bool isMouseEvent(const Event &event); /** * A source of Events. * * An example for this is OSystem, which provides events created by the system * and/or user. */ class EventSource { public: virtual ~EventSource(); /** * Query an event from the source. * * @param event Reference to the event struct where the event should be stored. * @retval true If an event was polled, false otherwise. */ virtual bool pollEvent(Event &event) = 0; /** * Check whether events from this source are allowed to be mapped. * * Possible event sources not allowing mapping are: the event recorder/player and/or * the EventManager, which allows user events to be pushed. * * By default, mapping is allowed for every event source. */ virtual bool allowMapping() const { return true; } }; /** * An artificial event source. This class is used as an event source, which is * made up by client-specific events. * * Example use cases for this are the Keymapper or the DefaultEventManager. */ class ArtificialEventSource : public EventSource { protected: Queue _artificialEventQueue; public: /** Put the specified event into the queue. */ void addEvent(const Event &ev) { _artificialEventQueue.push(ev); } bool pollEvent(Event &ev) { if (!_artificialEventQueue.empty()) { ev = _artificialEventQueue.pop(); return true; } else { return false; } } /** * By default, an artificial event source prevents its events * from being mapped. */ virtual bool allowMapping() const { return false; } }; /** * Object that catches and processes Events. * * An example for this is the Engine object - it catches events and processes them. */ class EventObserver { public: virtual ~EventObserver(); /** * Notify the observer of an incoming event. * * An observer is supposed to 'eat' the event, with returning true, when * it wants to prevent other observers from receiving the event. * A usage example here is the keymapper: * If it processes an Event, it should 'eat' it and create a new * event, which the EventDispatcher will then catch. * * @param event The event that is incoming. * @retval true If the event should not be passed to other observers, * false otherwise. */ virtual bool notifyEvent(const Event &event) = 0; /** * Notify the observer of pollEvent() query. */ virtual void notifyPoll() { } }; /** * A event mapper that maps events to others. * * An example for this is the Keymapper. */ class EventMapper { public: virtual ~EventMapper(); /** * Map an incoming event to one or more action events. */ virtual bool mapEvent(const Event &ev, List &mappedEvents) = 0; }; /** * Dispatch events from various sources to various observers. * * EventDispatcher uses a priority-based approach. Observers * with higher priority are notified before observers with * lower priority. Note that observers might 'eat' events, * and thus not all observers might be notified. * * Another speciality is the support for an event mapper that * will catch events and create new events out of them. This * mapper will be processed before an event is sent to the * observers. */ class EventDispatcher { public: EventDispatcher(); ~EventDispatcher(); /** * Attempt to catch events from the registered event * sources and dispatch them to the observers. * * This dispatches *all* events the sources offer. */ void dispatch(); /** * Clear all events currently in the event queue. * The cleared events are not dispatched and are simply discarded. */ void clearEvents(); /** * Register a new EventMapper with the dispatcher. */ void registerMapper(EventMapper *mapper, bool autoFree); /** * Unregister an EventMapper. * * This takes the "autoFree" flag passed to registerSource into account. */ void unregisterMapper(EventMapper *mapper); /** * Register a new EventSource with the Dispatcher. */ void registerSource(EventSource *source, bool autoFree); /** * Unregister an EventSource. * * This takes the "autoFree" flag passed to registerSource into account. */ void unregisterSource(EventSource *source); /** * Ignore some event sources and don't poll them. This is useful for e.g. the EventRecorder * where you don't want the other EventSource instances to interfer with the serialized events. */ void ignoreSources(bool ignore); /** * Register a new EventObserver with the Dispatcher. * * @param listenPolls If set, then all pollEvent() calls are passed to the observer. * Currently, it is used by keyMapper. */ void registerObserver(EventObserver *obs, uint priority, bool autoFree, bool listenPolls = false); /** * Unregister an EventObserver. * * This takes the "autoFree" flag passed to registerObserver into account. */ void unregisterObserver(EventObserver *obs); private: struct Entry { bool autoFree; bool ignore; }; struct MapperEntry : public Entry { EventMapper *mapper; }; List _mappers; struct SourceEntry : public Entry { EventSource *source; }; List _sources; struct ObserverEntry : public Entry { uint priority; EventObserver *observer; bool poll; }; List _observers; void dispatchEvent(const Event &event); void dispatchPoll(); }; class Keymap; class Keymapper; /** * The EventManager provides user input events to the client code. * In addition, it keeps track of the state of various input devices, * like keys, mouse position, and buttons. */ class EventManager : NonCopyable { public: virtual ~EventManager(); enum { LBUTTON = 1 << MOUSE_BUTTON_LEFT, RBUTTON = 1 << MOUSE_BUTTON_RIGHT }; /** * Initialize the event manager. * @note Called after graphics system has been set up. */ virtual void init() {} /** * Get the next event in the event queue. * @param event Point to an Event struct, which will be filled with the event data. * @retval true If an event was retrieved. */ virtual bool pollEvent(Event &event) = 0; /** * Push a "fake" event into the event queue. */ virtual void pushEvent(const Event &event) = 0; /** * Purge all unprocessed mouse events already in the event queue. */ virtual void purgeMouseEvents() = 0; /** * Purge all unprocessed keyboard events already in the event queue. */ virtual void purgeKeyboardEvents() = 0; /** Return the current mouse position. */ virtual Point getMousePos() const = 0; /** * Return a bitmask with the button states: * - bit 0: left button up=0, down=1 * - bit 1: right button up=0, down=1 */ virtual int getButtonState() const = 0; /** Get a bitmask with the current modifier state. */ virtual int getModifierState() const = 0; /** * Whether the application should terminate. Set to true if EVENT_QUIT was received. */ virtual int shouldQuit() const = 0; /** * Whether to return to the launcher. */ virtual int shouldReturnToLauncher() const = 0; /** * Reset the "return to launcher" flag (as returned shouldReturnToLauncher()) to false. * Used when we have returned to the launcher. */ virtual void resetReturnToLauncher() = 0; virtual void resetQuit() = 0; // Optional: check whether a given key is currently pressed ???? //virtual bool isKeyPressed(int keycode) = 0; // TODO: Keyboard repeat support? // TODO: Consider removing OSystem::getScreenChangeID and // replacing it by a generic getScreenChangeID method here /** Return the @ref Keymapper object. */ virtual Keymapper *getKeymapper() = 0; /** Return the global @ref Keymap object. */ virtual Keymap *getGlobalKeymap() = 0; enum { /** * Priority of the event manager. For now, it is lowest since it eats * *all* events. This might be changed in the future though. */ kEventManPriority = 0, /** * Priority of the event recorder. It must go after the event manager * in order to record events generated by it. */ kEventRecorderPriority = 1, /** * Priority of the remap dialog. It must go first to capture all * the events before they are consumed by other observers. */ kEventRemapperPriority = 999 }; /** * Return the underlying EventDispatcher. */ EventDispatcher *getEventDispatcher() { return &_dispatcher; } protected: EventDispatcher _dispatcher; }; /** * Wrap an event source so the key-down events are repeated while * keys are held down. * * Does not take ownership of the wrapped EventSource. */ EventSource *makeKeyboardRepeatingEventSource(EventSource *eventSource); /** @} */ } // End of namespace Common #endif