summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/sdl/osdsdl.h
blob: c8ce167d69975dd721d8007286e8eee85ba32eed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert, R. Belmont
#ifndef MAME_OSD_SDL_OSDSDL_H
#define MAME_OSD_SDL_OSDSDL_H

#pragma once

#include "sdlopts.h"

#include "modules/lib/osdobj_common.h"
#include "modules/osdmodule.h"

#include <cassert>
#include <chrono>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <string>
#include <vector>


//============================================================
//  Defines
//============================================================

#define SDLMAME_LED(x)                  "led" #x

// read by sdlmame

#define SDLENV_DESKTOPDIM               "SDLMAME_DESKTOPDIM"
#define SDLENV_VMWARE                   "SDLMAME_VMWARE"

// set by sdlmame

#define SDLENV_VISUALID                 "SDL_VIDEO_X11_VISUALID"
#define SDLENV_VIDEODRIVER              "SDL_VIDEODRIVER"
#define SDLENV_AUDIODRIVER              "SDL_AUDIODRIVER"
#define SDLENV_RENDERDRIVER             "SDL_VIDEO_RENDERER"


//============================================================
//  TYPE DEFINITIONS
//============================================================

template <typename EventRecord, typename EventType>
class event_subscription_manager
{
public: // need extra public section for forward declaration
	class subscriber;

private:
	class impl
	{
	public:
		std::mutex m_mutex;
		std::unordered_multimap<EventType, subscriber *> m_subs;
	};

	std::shared_ptr<impl> m_impl;

protected:
	event_subscription_manager() : m_impl(new impl)
	{
	}

	~event_subscription_manager() = default;

	std::mutex &subscription_mutex()
	{
		return m_impl->m_mutex;
	}

	void dispatch_event(EventType const &type, EventRecord const &event)
	{
		auto const matches = m_impl->m_subs.equal_range(type);
		for (auto it = matches.first; matches.second != it; ++it)
			it->second->handle_event(event);
	}

public:
	class subscriber
	{
	public:
		virtual void handle_event(EventRecord const &event) = 0;

	protected:
		subscriber() = default;

		virtual ~subscriber()
		{
			unsubscribe();
		}

		template <typename T>
		void subscribe(event_subscription_manager &host, T &&types)
		{
			assert(!m_host.lock());
			assert(host.m_impl);

			m_host = host.m_impl;

			std::lock_guard<std::mutex> lock(host.m_impl->m_mutex);
			for (auto const &t : types)
				host.m_impl->m_subs.emplace(t, this);
		}

		void unsubscribe()
		{
			auto const host(m_host.lock());
			m_host.reset();
			if (host)
			{
				std::lock_guard<std::mutex> lock(host->m_mutex);
				auto it = host->m_subs.begin();
				while (host->m_subs.end() != it)
				{
					if (it->second == this)
						it = host->m_subs.erase(it);
					else
						++it;
				}
			}
		}

	private:
		std::weak_ptr<impl> m_host;
	};
};


union SDL_Event;

using sdl_event_manager = event_subscription_manager<SDL_Event, uint32_t>;


class sdl_window_info;

class sdl_osd_interface : public osd_common_t, public sdl_event_manager
{
public:
	// construction/destruction
	sdl_osd_interface(sdl_options &options);
	virtual ~sdl_osd_interface();

	// general overridables
	virtual void init(running_machine &machine) override;
	virtual void update(bool skip_redraw) override;
	virtual void input_update(bool relative_reset) override;
	virtual void check_osd_inputs() override;

	// input overridables
	virtual void customize_input_type_list(std::vector<input_type_entry> &typelist) override;

	virtual bool video_init() override;
	virtual bool window_init() override;

	virtual void video_exit() override;
	virtual void window_exit() override;

	// SDL-specific
	virtual bool has_focus() const override { return bool(m_focus_window); }
	void release_keys();
	bool should_hide_mouse();
	void process_events_buf();

	virtual sdl_options &options() override { return m_options; }

	virtual void process_events() override;

protected:
	virtual void build_slider_list() override;
	virtual void update_slider_list() override;

private:
	enum
	{
		MODIFIER_KEY_LCTRL = 0x01,
		MODIFIER_KEY_RCTRL = 0x02,
		MODIFIER_KEY_LSHIFT = 0x04,
		MODIFIER_KEY_RSHIFT = 0x08,

		MODIFIER_KEY_CTRL = MODIFIER_KEY_LCTRL | MODIFIER_KEY_RCTRL,
		MODIFIER_KEY_SHIFT = MODIFIER_KEY_LSHIFT | MODIFIER_KEY_RSHIFT
	};

	virtual void osd_exit() override;

	void extract_video_config();
	void output_oslog(const char *buffer);

	void process_window_event(SDL_Event const &event);
	void process_textinput_event(SDL_Event const &event);

	bool mouse_over_window() const { return m_mouse_over_window > 0; }
	template <typename T> sdl_window_info *focus_window(T const &event) const;

	sdl_options &m_options;
	sdl_window_info *m_focus_window;
	int m_mouse_over_window;
	uint8_t m_modifier_keys;

	std::chrono::steady_clock::time_point m_last_click_time;
	int m_last_click_x;
	int m_last_click_y;
};

//============================================================
//  sdlwork.c
//============================================================

extern int osd_num_processors;

#endif // MAME_OSD_SDL_OSDSDL_H