1 module d2d.window.windowevent;
2 
3 import d2d;
4 
5 import std.math : abs;
6 
7 /// Event structure on Window Events.
8 struct WindowEvent
9 {
10 	/// Types that can occur when WindowEvents are fired.
11 	enum Type
12 	{
13 		Undefined,
14 		/// Occurs when X button is clicked.
15 		Close,
16 		/// Occurs when window got resized.
17 		Resized,
18 		/// Occurs when window got moved.
19 		Moved,
20 		/// Occurs when window lost focus.
21 		LostFocus,
22 		/// Occurs when window gained focus again.
23 		GainedFocus,
24 		/// Occurs when `window.show` got called.
25 		Shown,
26 		/// Occurs when `window.hide` got called.
27 		Hidden,
28 		/// Occurs when the window minimizes.
29 		Minimized,
30 		/// Occurs when the window maximizes.
31 		Maximized,
32 		/// Occurs when the window restores from minimized/maximized state.
33 		Restored,
34 		/// Occurs when the user typed some text on the keyboard for text fields.
35 		TextEntered,
36 		/// Occurs when the user presses a key on the keyboard. Will fire repeatedly when held down.
37 		KeyPressed,
38 		/// Occurs when the user releases a key on the keyboard.
39 		KeyReleased,
40 		/// Occurs when the user scrolled.
41 		MouseWheelMoved,
42 		/// Occurs when the user pressed a mouse button.
43 		MouseButtonPressed,
44 		/// Occurs when the user released a mouse button.
45 		MouseButtonReleased,
46 		/// Occurs when the user moved the mouse.
47 		MouseMoved,
48 		/// Occurs when the mouse hovers over the window.
49 		MouseEntered,
50 		/// Occurs when the mouse no longer hovers over the window
51 		MouseLeft,
52 		/// Occurs when a button on a controller got pressed.
53 		ControllerButtonPressed,
54 		/// Occurs when a button on a controller got released.
55 		ControllerButtonReleased,
56 		/// Occurs when an axis on a controller got moved.
57 		ControllerAxis,
58 		/// Occurs when a controller connected.
59 		ControllerConnected,
60 		/// Occurs when a controller disconnected.
61 		ControllerDisconnected,
62 		/// Occurs when window is closing.
63 		Quit
64 	}
65 
66 	/// Type of this event.
67 	Type type;
68 
69 	union
70 	{
71 		/// x position in events.
72 		int x;
73 		/// width in events.
74 		int width;
75 	}
76 
77 	union
78 	{
79 		/// y position in events.
80 		int y;
81 		/// height in events.
82 		int height;
83 	}
84 	/// Relative mouse coordinates in Mouse events.
85 	int xrel, yrel;
86 	union
87 	{
88 		/// Mouse button in Mouse events.
89 		int mousebutton;
90 		/// Key in Controller and Keyboard events.
91 		int key;
92 		/// Axis id in ControllerAxis event.
93 		int axis;
94 	}
95 	/// Controller id in any Controller event.
96 	int controllerID;
97 	union
98 	{
99 		/// Axis value in ControllerAxis event.
100 		short axisValue;
101 		/// Non-zero if this is a key repeat.
102 		ubyte repeat;
103 	}
104 	/// Text contained in TextEntered event.
105 	string text;
106 
107 	/// Function for converting a SDL event to a WindowEvent
108 	void   fromSDL(const ref SDL_Event event)
109 	{
110 		switch (event.type)
111 		{
112 		case SDL_WINDOWEVENT:
113 			switch (event.window.event)
114 			{
115 			case SDL_WINDOWEVENT_SHOWN:
116 				type = Type.Shown;
117 				break;
118 			case SDL_WINDOWEVENT_HIDDEN:
119 				type = Type.Hidden;
120 				break;
121 			case SDL_WINDOWEVENT_MOVED:
122 				type = Type.Moved;
123 				x = event.window.data1;
124 				y = event.window.data2;
125 				break;
126 			case SDL_WINDOWEVENT_RESIZED:
127 				type = Type.Resized;
128 				x = event.window.data1;
129 				y = event.window.data2;
130 				break;
131 			case SDL_WINDOWEVENT_MINIMIZED:
132 				type = Type.Minimized;
133 				break;
134 			case SDL_WINDOWEVENT_MAXIMIZED:
135 				type = Type.Maximized;
136 				break;
137 			case SDL_WINDOWEVENT_RESTORED:
138 				type = Type.Restored;
139 				break;
140 			case SDL_WINDOWEVENT_ENTER:
141 				type = Type.MouseEntered;
142 				break;
143 			case SDL_WINDOWEVENT_LEAVE:
144 				type = Type.MouseLeft;
145 				break;
146 			case SDL_WINDOWEVENT_FOCUS_GAINED:
147 				type = Type.GainedFocus;
148 				break;
149 			case SDL_WINDOWEVENT_FOCUS_LOST:
150 				type = Type.LostFocus;
151 				break;
152 			case SDL_WINDOWEVENT_CLOSE:
153 				type = Type.Close;
154 				break;
155 			default:
156 				type = Type.Undefined;
157 				break;
158 			}
159 			break;
160 		case SDL_KEYDOWN:
161 			type = Type.KeyPressed;
162 			key = event.key.keysym.sym;
163 			repeat = event.key.repeat;
164 			break;
165 		case SDL_KEYUP:
166 			type = Type.KeyReleased;
167 			key = event.key.keysym.sym;
168 			repeat = event.key.repeat;
169 			break;
170 		case SDL_MOUSEWHEEL:
171 			type = Type.MouseWheelMoved;
172 			x = event.wheel.x;
173 			y = event.wheel.y;
174 			break;
175 		case SDL_MOUSEMOTION:
176 			type = Type.MouseMoved;
177 			x = event.motion.x;
178 			y = event.motion.y;
179 			xrel = event.motion.xrel;
180 			yrel = event.motion.yrel;
181 			break;
182 		case SDL_MOUSEBUTTONDOWN:
183 			type = Type.MouseButtonPressed;
184 			x = event.button.x;
185 			y = event.button.y;
186 			mousebutton = event.button.button;
187 			break;
188 		case SDL_MOUSEBUTTONUP:
189 			type = Type.MouseButtonReleased;
190 			x = event.button.x;
191 			y = event.button.y;
192 			mousebutton = event.button.button;
193 			break;
194 		case SDL_CONTROLLERDEVICEADDED:
195 			type = Type.ControllerConnected;
196 			controllerID = event.cdevice.which;
197 			SDL_GameControllerOpen(controllerID);
198 			break;
199 		case SDL_CONTROLLERDEVICEREMOVED:
200 			type = Type.ControllerDisconnected;
201 			controllerID = event.cdevice.which;
202 			break;
203 		case SDL_CONTROLLERBUTTONDOWN:
204 			type = Type.ControllerButtonPressed;
205 			controllerID = event.cbutton.which;
206 			key = event.cbutton.button;
207 			break;
208 		case SDL_CONTROLLERBUTTONUP:
209 			type = Type.ControllerButtonReleased;
210 			controllerID = event.cbutton.which;
211 			key = event.cbutton.button;
212 			break;
213 		case SDL_CONTROLLERAXISMOTION:
214 			type = Type.ControllerAxis;
215 			short value = event.caxis.value;
216 			if (value < -32_767)
217 				value = -32_767;
218 			if ((event.caxis.axis == 0 || event.caxis.axis == 1) && abs(value) < 7849)
219 			{
220 				value = 0;
221 			}
222 			if ((event.caxis.axis == 2 || event.caxis.axis == 3) && abs(value) < 8689)
223 			{
224 				value = 0;
225 			}
226 			if ((event.caxis.axis == 4 || event.caxis.axis == 5) && abs(value) < 30)
227 			{
228 				value = 0;
229 			}
230 			axis = event.caxis.axis;
231 			axisValue = value;
232 			break;
233 		case SDL_TEXTINPUT:
234 			type = Type.TextEntered;
235 			text = cast(string) fromStringz(event.text.text.ptr);
236 			break;
237 		case SDL_QUIT:
238 			type = Type.Quit;
239 			break;
240 		default:
241 			type = Type.Undefined;
242 			break;
243 		}
244 	}
245 }
246 
247 ///
248 unittest
249 {
250 	SDL_Event source;
251 	WindowEvent event;
252 	source.type = SDL_KEYDOWN;
253 	source.key.keysym.sym = 42;
254 	event.fromSDL(source);
255 
256 	assert(event.type == WindowEvent.Type.KeyPressed);
257 	assert(event.key == 42);
258 }
259 
260 ///
261 alias Event = WindowEvent;