1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
4 // This device code is based on the original SDL device implementation
\r
5 // contributed by Shane Parker (sirshane).
\r
7 #ifndef __C_IRR_DEVICE_SDL_H_INCLUDED__
\r
8 #define __C_IRR_DEVICE_SDL_H_INCLUDED__
\r
10 #include "IrrCompileConfig.h"
\r
12 #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
\r
14 #include "IrrlichtDevice.h"
\r
15 #include "CIrrDeviceStub.h"
\r
16 #include "ICursorControl.h"
\r
18 #ifdef _IRR_EMSCRIPTEN_PLATFORM_
\r
19 #include <emscripten/html5.h>
\r
23 #include <SDL_syswm.h>
\r
30 class CIrrDeviceSDL : public CIrrDeviceStub
\r
35 CIrrDeviceSDL(const SIrrlichtCreationParameters& param);
\r
38 virtual ~CIrrDeviceSDL();
\r
40 //! runs the device. Returns false if device wants to be deleted
\r
41 bool run() override;
\r
43 //! pause execution temporarily
\r
44 void yield() override;
\r
46 //! pause execution for a specified time
\r
47 void sleep(u32 timeMs, bool pauseTimer) override;
\r
49 //! sets the caption of the window
\r
50 void setWindowCaption(const wchar_t* text) override;
\r
52 //! returns if window is active. if not, nothing need to be drawn
\r
53 bool isWindowActive() const override;
\r
55 //! returns if window has focus.
\r
56 bool isWindowFocused() const override;
\r
58 //! returns if window is minimized.
\r
59 bool isWindowMinimized() const override;
\r
61 //! returns color format of the window.
\r
62 video::ECOLOR_FORMAT getColorFormat() const override;
\r
64 //! notifies the device that it should close itself
\r
65 void closeDevice() override;
\r
67 //! Sets if the window should be resizable in windowed mode.
\r
68 void setResizable(bool resize=false) override;
\r
70 //! Minimizes the window.
\r
71 void minimizeWindow() override;
\r
73 //! Maximizes the window.
\r
74 void maximizeWindow() override;
\r
76 //! Restores the window size.
\r
77 void restoreWindow() override;
\r
79 //! Checks if the window is maximized.
\r
80 bool isWindowMaximized() const override;
\r
82 //! Checks if the Irrlicht window is running in fullscreen mode
\r
83 /** \return True if window is fullscreen. */
\r
84 bool isFullscreen() const override;
\r
86 //! Get the position of this window on screen
\r
87 core::position2di getWindowPosition() override;
\r
89 //! Activate any joysticks, and generate events for them.
\r
90 bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) override;
\r
92 //! Get the device type
\r
93 E_DEVICE_TYPE getType() const override
\r
100 //! Implementation of the linux cursor control
\r
101 class CCursorControl : public gui::ICursorControl
\r
105 CCursorControl(CIrrDeviceSDL* dev)
\r
106 : Device(dev), IsVisible(true)
\r
111 //! Changes the visible state of the mouse cursor.
\r
112 void setVisible(bool visible) override
\r
114 IsVisible = visible;
\r
116 SDL_ShowCursor( SDL_ENABLE );
\r
119 SDL_ShowCursor( SDL_DISABLE );
\r
123 //! Returns if the cursor is currently visible.
\r
124 bool isVisible() const override
\r
129 //! Sets the new position of the cursor.
\r
130 void setPosition(const core::position2d<f32> &pos) override
\r
132 setPosition(pos.X, pos.Y);
\r
135 //! Sets the new position of the cursor.
\r
136 void setPosition(f32 x, f32 y) override
\r
138 setPosition((s32)(x*Device->Width), (s32)(y*Device->Height));
\r
141 //! Sets the new position of the cursor.
\r
142 void setPosition(const core::position2d<s32> &pos) override
\r
144 setPosition(pos.X, pos.Y);
\r
147 //! Sets the new position of the cursor.
\r
148 void setPosition(s32 x, s32 y) override
\r
150 SDL_WarpMouseInWindow(Device->Window, x, y);
\r
152 if (SDL_GetRelativeMouseMode()) {
\r
153 // There won't be an event for this warp (details on libsdl-org/SDL/issues/6034)
\r
154 Device->MouseX = x;
\r
155 Device->MouseY = y;
\r
159 //! Returns the current position of the mouse cursor.
\r
160 const core::position2d<s32>& getPosition(bool updateCursor) override
\r
162 if ( updateCursor )
\r
167 //! Returns the current position of the mouse cursor.
\r
168 core::position2d<f32> getRelativePosition(bool updateCursor) override
\r
170 if ( updateCursor )
\r
172 return core::position2d<f32>(CursorPos.X / (f32)Device->Width,
\r
173 CursorPos.Y / (f32)Device->Height);
\r
176 void setReferenceRect(core::rect<s32>* rect=0) override
\r
180 virtual void setRelativeMode(bool relative) _IRR_OVERRIDE_
\r
182 // Only change it when necessary, as it flushes mouse motion when enabled
\r
183 if ( relative != SDL_GetRelativeMouseMode()) {
\r
185 SDL_SetRelativeMouseMode( SDL_TRUE );
\r
187 SDL_SetRelativeMouseMode( SDL_FALSE );
\r
191 void setActiveIcon(gui::ECURSOR_ICON iconId) override
\r
193 ActiveIcon = iconId;
\r
194 if (iconId > Cursors.size() || !Cursors[iconId]) {
\r
195 iconId = gui::ECI_NORMAL;
\r
196 if (iconId > Cursors.size() || !Cursors[iconId])
\r
199 SDL_SetCursor(Cursors[iconId].get());
\r
202 gui::ECURSOR_ICON getActiveIcon() const override
\r
209 void updateCursorPos()
\r
211 #ifdef _IRR_EMSCRIPTEN_PLATFORM_
\r
212 EmscriptenPointerlockChangeEvent pointerlockStatus; // let's hope that test is not expensive ...
\r
213 if ( emscripten_get_pointerlock_status(&pointerlockStatus) == EMSCRIPTEN_RESULT_SUCCESS )
\r
215 if ( pointerlockStatus.isActive )
\r
217 CursorPos.X += Device->MouseXRel;
\r
218 CursorPos.Y += Device->MouseYRel;
\r
219 Device->MouseXRel = 0;
\r
220 Device->MouseYRel = 0;
\r
224 CursorPos.X = Device->MouseX;
\r
225 CursorPos.Y = Device->MouseY;
\r
229 CursorPos.X = Device->MouseX;
\r
230 CursorPos.Y = Device->MouseY;
\r
232 if (CursorPos.X < 0)
\r
234 if (CursorPos.X > (s32)Device->Width)
\r
235 CursorPos.X = Device->Width;
\r
236 if (CursorPos.Y < 0)
\r
238 if (CursorPos.Y > (s32)Device->Height)
\r
239 CursorPos.Y = Device->Height;
\r
243 void initCursors();
\r
245 CIrrDeviceSDL* Device;
\r
246 core::position2d<s32> CursorPos;
\r
249 struct CursorDeleter {
\r
250 void operator()(SDL_Cursor *ptr) {
\r
252 SDL_FreeCursor(ptr);
\r
255 std::vector<std::unique_ptr<SDL_Cursor, CursorDeleter>> Cursors;
\r
256 gui::ECURSOR_ICON ActiveIcon;
\r
261 #ifdef _IRR_EMSCRIPTEN_PLATFORM_
\r
262 static EM_BOOL MouseUpDownCallback(int eventType, const EmscriptenMouseEvent * event, void* userData);
\r
263 static EM_BOOL MouseEnterCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
\r
264 static EM_BOOL MouseLeaveCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
\r
267 // Check if a key is a known special character with no side effects on text boxes.
\r
268 static bool keyIsKnownSpecial(EKEY_CODE key);
\r
270 // Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
\r
271 static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
\r
273 // Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
\r
274 void resetReceiveTextInputEvents();
\r
276 //! create the driver
\r
277 void createDriver();
\r
279 bool createWindow();
\r
281 void createKeyMap();
\r
283 void logAttributes();
\r
284 SDL_GLContext Context;
\r
285 SDL_Window *Window;
\r
287 #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
\r
288 core::array<SDL_Joystick*> Joysticks;
\r
291 s32 MouseX, MouseY;
\r
292 s32 MouseXRel, MouseYRel;
\r
293 u32 MouseButtonStates;
\r
302 SKeyMap(s32 x11, s32 win32)
\r
303 : SDLKey(x11), Win32Key(win32)
\r
310 bool operator<(const SKeyMap& o) const
\r
312 return SDLKey<o.SDLKey;
\r
316 core::array<SKeyMap> KeyMap;
\r
317 SDL_SysWMinfo Info;
\r
320 } // end namespace irr
\r
322 #endif // _IRR_COMPILE_WITH_SDL_DEVICE_
\r
323 #endif // __C_IRR_DEVICE_SDL_H_INCLUDED__
\r