// license:BSD-3-Clause // copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes //============================================================ // // input_sdlcommon.h - SDL Common code shared by SDL modules // // Note: this code is also used by the X11 input modules // //============================================================ #ifndef INPUT_SDLCOMMON_H_ #define INPUT_SDLCOMMON_H_ #include #include #include #include #define MAX_DEVMAP_ENTRIES 16 #define SDL_MODULE_EVENT_BUFFER_SIZE 5 // state information for a keyboard struct keyboard_state { INT32 state[0x3ff]; // must be INT32! INT8 oldkey[MAX_KEYS]; INT8 currkey[MAX_KEYS]; }; // state information for a mouse struct mouse_state { INT32 lX, lY; INT32 buttons[MAX_BUTTONS]; }; // state information for a joystick; DirectInput state must be first element struct joystick_state { SDL_Joystick *device; INT32 axes[MAX_AXES]; INT32 buttons[MAX_BUTTONS]; INT32 hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; INT32 balls[MAX_AXES]; }; struct device_map_t { struct { std::string name; int physical; } map[MAX_DEVMAP_ENTRIES]; int logical[MAX_DEVMAP_ENTRIES]; int initialized; }; //============================================================ // event_manager_t //============================================================ class sdl_event_subscriber { public: virtual ~sdl_event_subscriber() {} virtual void handle_event(SDL_Event &sdlevent) = 0; }; template class event_manager_t { protected: std::mutex m_lock; std::unordered_multimap m_subscription_index; event_manager_t() { } public: virtual ~event_manager_t() { } void subscribe(int* event_types, int num_event_types, TSubscriber *subscriber) { std::lock_guard scope_lock(m_lock); // Add the subscription for (int i = 0; i < num_event_types; i++) { m_subscription_index.emplace(event_types[i], subscriber); } } void unsubscribe(TSubscriber *subscriber) { std::lock_guard scope_lock(m_lock); // Loop over the entries and find ones that match our subscriber std::vector::iterator> remove; for (auto iter = m_subscription_index.begin(); iter != m_subscription_index.end(); ++iter) { if (iter->second == subscriber) remove.push_back(iter); } // remove those that matched for (int i = 0; i < remove.size(); i++) m_subscription_index.erase(remove[i]); } virtual void process_events(running_machine &machine) = 0; }; class sdl_window_info; class sdl_event_manager : public event_manager_t { private: bool m_mouse_over_window; bool m_has_focus; std::shared_ptr m_focus_window; sdl_event_manager() : m_mouse_over_window(true), m_has_focus(true), m_focus_window(nullptr) { } public: bool mouse_over_window() const { return m_mouse_over_window; } bool has_focus() const { return m_focus_window != nullptr; } std::shared_ptr focus_window() const { return m_focus_window; } static sdl_event_manager& instance() { static sdl_event_manager s_instance; return s_instance; } void process_events(running_machine &machine) override; private: void process_window_event(running_machine &machine, SDL_Event &sdlevent); }; //============================================================ // INLINE FUNCTIONS //============================================================ static inline int devmap_leastfree(device_map_t *devmap) { int i; for (i = 0; i < MAX_DEVMAP_ENTRIES; i++) { if (devmap->map[i].name.length() == 0) return i; } return -1; } static inline std::string remove_spaces(const char *s) { // Remove the spaces auto output = std::string(s); output.erase(std::remove_if(output.begin(), output.end(), isspace), output.end()); return output; } //============================================================ // devmap_init - initializes a device_map based on // an input option prefix and max number of devices //============================================================ static inline void devmap_init(running_machine &machine, device_map_t *devmap, const char *opt, int max_devices, const char *label) { int dev; char defname[20]; // The max devices the user specified, better not be bigger than the max the arrays can old assert(max_devices <= MAX_DEVMAP_ENTRIES); // Initialize the map to default uninitialized values for (dev = 0; dev < MAX_DEVMAP_ENTRIES; dev++) { devmap->map[dev].physical = -1; devmap->logical[dev] = -1; } devmap->initialized = 0; // populate the device map up to the max number of devices for (dev = 0; dev < max_devices; dev++) { const char *dev_name; // derive the parameter name from the option name and index. For instance: lightgun_index1 to lightgun_index8 sprintf(defname, "%s%d", opt, dev + 1); // Get the user-specified name that matches the parameter dev_name = machine.options().value(defname); // If they've specified a name and it's not "auto", treat it as a custom mapping if (dev_name && *dev_name && strcmp(dev_name, OSDOPTVAL_AUTO)) { // remove the spaces from the name store it in the index devmap->map[dev].name = remove_spaces(dev_name); osd_printf_verbose("%s: Logical id %d: %s\n", label, dev + 1, devmap->map[dev].name.c_str()); devmap->initialized = 1; } } } #endif