]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CIrrDeviceWin32.h
02c42b7e8cf6f0a8eea36833655426f8803aa876
[irrlicht.git] / source / Irrlicht / CIrrDeviceWin32.h
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 \r
5 #ifndef __C_IRR_DEVICE_WIN32_H_INCLUDED__\r
6 #define __C_IRR_DEVICE_WIN32_H_INCLUDED__\r
7 \r
8 #include "IrrCompileConfig.h"\r
9 #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_\r
10 \r
11 #include "CIrrDeviceStub.h"\r
12 #include "IrrlichtDevice.h"\r
13 #include "IImagePresenter.h"\r
14 \r
15 #define WIN32_LEAN_AND_MEAN\r
16 #include <windows.h>\r
17 #include <mmsystem.h> // For JOYCAPS\r
18 #include <windowsx.h>\r
19 #if !defined(GET_X_LPARAM)\r
20 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))\r
21 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))\r
22 #endif\r
23 \r
24 namespace irr\r
25 {\r
26         struct SJoystickWin32Control;\r
27 \r
28         class CIrrDeviceWin32 : public CIrrDeviceStub, video::IImagePresenter\r
29         {\r
30         friend struct SJoystickWin32Control;\r
31         public:\r
32 \r
33                 //! constructor\r
34                 CIrrDeviceWin32(const SIrrlichtCreationParameters& params);\r
35 \r
36                 //! destructor\r
37                 virtual ~CIrrDeviceWin32();\r
38 \r
39                 //! runs the device. Returns false if device wants to be deleted\r
40                 virtual bool run() _IRR_OVERRIDE_;\r
41 \r
42                 //! Cause the device to temporarily pause execution and let other processes to run\r
43                 // This should bring down processor usage without major performance loss for Irrlicht\r
44                 virtual void yield() _IRR_OVERRIDE_;\r
45 \r
46                 //! Pause execution and let other processes to run for a specified amount of time.\r
47                 virtual void sleep(u32 timeMs, bool pauseTimer) _IRR_OVERRIDE_;\r
48 \r
49                 //! sets the caption of the window\r
50                 virtual void setWindowCaption(const wchar_t* text) _IRR_OVERRIDE_;\r
51 \r
52                 //! returns if window is active. if not, nothing need to be drawn\r
53                 virtual bool isWindowActive() const _IRR_OVERRIDE_;\r
54 \r
55                 //! returns if window has focus\r
56                 virtual bool isWindowFocused() const _IRR_OVERRIDE_;\r
57 \r
58                 //! returns if window is minimized\r
59                 virtual bool isWindowMinimized() const _IRR_OVERRIDE_;\r
60 \r
61                 //! presents a surface in the client area\r
62                 virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0) _IRR_OVERRIDE_;\r
63 \r
64                 //! notifies the device that it should close itself\r
65                 virtual void closeDevice() _IRR_OVERRIDE_;\r
66 \r
67                 //! Notifies the device, that it has been resized\r
68                 /** Must be publis as it is called from free function (event handler) */\r
69                 void OnResized();\r
70 \r
71                 //! Sets if the window should be resizable in windowed mode.\r
72                 virtual void setResizable(bool resize=false) _IRR_OVERRIDE_;\r
73 \r
74                 //! Resize the render window.\r
75                 virtual void setWindowSize(const irr::core::dimension2d<u32>& size) _IRR_OVERRIDE_;\r
76 \r
77                 //! Minimizes the window.\r
78                 virtual void minimizeWindow() _IRR_OVERRIDE_;\r
79 \r
80                 //! Maximizes the window.\r
81                 virtual void maximizeWindow() _IRR_OVERRIDE_;\r
82 \r
83                 //! Restores the window size.\r
84                 virtual void restoreWindow() _IRR_OVERRIDE_;\r
85 \r
86                 //! Get the position of the window on screen\r
87                 virtual core::position2di getWindowPosition() _IRR_OVERRIDE_;\r
88 \r
89                 //! Activate any joysticks, and generate events for them.\r
90                 virtual bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo) _IRR_OVERRIDE_;\r
91 \r
92                 //! Set the current Gamma Value for the Display\r
93                 virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) _IRR_OVERRIDE_;\r
94 \r
95                 //! Get the current Gamma Value for the Display\r
96                 virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) _IRR_OVERRIDE_;\r
97 \r
98                 //! Remove all messages pending in the system message loop\r
99                 virtual void clearSystemMessages() _IRR_OVERRIDE_;\r
100 \r
101                 //! Get the device type\r
102                 virtual E_DEVICE_TYPE getType() const _IRR_OVERRIDE_\r
103                 {\r
104                         return EIDT_WIN32;\r
105                 }\r
106 \r
107                 //! Compares to the last call of this function to return double and triple clicks.\r
108                 //! \return Returns only 1,2 or 3. A 4th click will start with 1 again.\r
109                 virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) _IRR_OVERRIDE_\r
110                 {\r
111                         // we just have to make it public\r
112                         return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent );\r
113                 }\r
114 \r
115                 //! Switch to fullscreen\r
116                 bool switchToFullScreen();\r
117 \r
118                 // convert an Irrlicht texture to a windows cursor\r
119                 HCURSOR TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);\r
120 \r
121                 //! Implementation of the win32 cursor control\r
122                 class CCursorControl : public gui::ICursorControl\r
123                 {\r
124                 public:\r
125 \r
126                         CCursorControl(CIrrDeviceWin32* device, const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen);\r
127                         ~CCursorControl();\r
128 \r
129                         //! Changes the visible state of the mouse cursor.\r
130                         virtual void setVisible(bool visible) _IRR_OVERRIDE_\r
131                         {\r
132                                 CURSORINFO info;\r
133                                 info.cbSize = sizeof(CURSORINFO);\r
134                                 BOOL gotCursorInfo = GetCursorInfo(&info);\r
135                                 while ( gotCursorInfo )\r
136                                 {\r
137 #ifdef CURSOR_SUPPRESSED\r
138                                         // Since Windows 8 the cursor can be suppressed by a touch interface\r
139                                         if (visible && info.flags == CURSOR_SUPPRESSED)\r
140                                         {\r
141                                                 break;\r
142                                         }\r
143 #endif\r
144                                         if ( (visible && info.flags == CURSOR_SHOWING) || // visible\r
145                                                 (!visible && info.flags == 0 ) ) // hidden\r
146                                         {\r
147                                                 break;\r
148                                         }\r
149                                         // this only increases an internal\r
150                                         // display counter in windows, so it\r
151                                         // might have to be called some more\r
152                                         const int showResult = ShowCursor(visible);\r
153                                         // if result has correct sign we can\r
154                                         // stop here as well\r
155                                         if (( !visible && showResult < 0 ) ||\r
156                                                 (visible && showResult >= 0))\r
157                                                 break;\r
158                                         // yes, it really must be set each time\r
159                                         info.cbSize = sizeof(CURSORINFO);\r
160                                         gotCursorInfo = GetCursorInfo(&info);\r
161 \r
162 #ifdef CURSOR_SUPPRESSED\r
163                                         // Not sure if a cursor which we tried to hide still can be suppressed.\r
164                                         // I have no touch-display for testing this and MSDN doesn't describe it.\r
165                                         // But adding this check shouldn't hurt and might prevent an endless loop.\r
166                                         if (!visible && info.flags == CURSOR_SUPPRESSED)\r
167                                         {\r
168                                                 break;\r
169                                         }\r
170 #endif\r
171                                 }\r
172                                 IsVisible = visible;\r
173                         }\r
174 \r
175                         //! Returns if the cursor is currently visible.\r
176                         virtual bool isVisible() const _IRR_OVERRIDE_\r
177                         {\r
178                                 return IsVisible;\r
179                         }\r
180 \r
181                         //! Sets the new position of the cursor.\r
182                         virtual void setPosition(const core::position2d<f32> &pos) _IRR_OVERRIDE_\r
183                         {\r
184                                 setPosition(pos.X, pos.Y);\r
185                         }\r
186 \r
187                         //! Sets the new position of the cursor.\r
188                         virtual void setPosition(f32 x, f32 y) _IRR_OVERRIDE_\r
189                         {\r
190                                 if (!UseReferenceRect)\r
191                                         setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height));\r
192                                 else\r
193                                         setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight()));\r
194                         }\r
195 \r
196                         //! Sets the new position of the cursor.\r
197                         virtual void setPosition(const core::position2d<s32> &pos) _IRR_OVERRIDE_\r
198                         {\r
199                                 setPosition(pos.X, pos.Y);\r
200                         }\r
201 \r
202                         //! Sets the new position of the cursor.\r
203                         virtual void setPosition(s32 x, s32 y) _IRR_OVERRIDE_\r
204                         {\r
205                                 if (UseReferenceRect)\r
206                                 {\r
207                                         SetCursorPos(ReferenceRect.UpperLeftCorner.X + x,\r
208                                                                 ReferenceRect.UpperLeftCorner.Y + y);\r
209                                 }\r
210                                 else\r
211                                 {\r
212                                         RECT rect;\r
213                                         if (GetWindowRect(HWnd, &rect))\r
214                                                 SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY);\r
215                                 }\r
216 \r
217                                 CursorPos.X = x;\r
218                                 CursorPos.Y = y;\r
219                         }\r
220 \r
221                         //! Returns the current position of the mouse cursor.\r
222                         virtual const core::position2d<s32>& getPosition(bool updateCursor) _IRR_OVERRIDE_\r
223                         {\r
224                                 if ( updateCursor )\r
225                                         updateInternalCursorPosition();\r
226                                 return CursorPos;\r
227                         }\r
228 \r
229                         //! Returns the current position of the mouse cursor.\r
230                         virtual core::position2d<f32> getRelativePosition(bool updateCursor) _IRR_OVERRIDE_\r
231                         {\r
232                                 if ( updateCursor )\r
233                                         updateInternalCursorPosition();\r
234 \r
235                                 if (!UseReferenceRect)\r
236                                 {\r
237                                         return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,\r
238                                                 CursorPos.Y * InvWindowSize.Height);\r
239                                 }\r
240 \r
241                                 return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),\r
242                                                 CursorPos.Y / (f32)ReferenceRect.getHeight());\r
243                         }\r
244 \r
245                         //! Sets an absolute reference rect for calculating the cursor position.\r
246                         virtual void setReferenceRect(core::rect<s32>* rect=0) _IRR_OVERRIDE_\r
247                         {\r
248                                 if (rect)\r
249                                 {\r
250                                         ReferenceRect = *rect;\r
251                                         UseReferenceRect = true;\r
252 \r
253                                         // prevent division through zero and uneven sizes\r
254 \r
255                                         if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)\r
256                                                 ReferenceRect.LowerRightCorner.Y += 1;\r
257 \r
258                                         if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)\r
259                                                 ReferenceRect.LowerRightCorner.X += 1;\r
260                                 }\r
261                                 else\r
262                                         UseReferenceRect = false;\r
263                         }\r
264 \r
265                         /** Used to notify the cursor that the window was resized. */\r
266                         void OnResize(const core::dimension2d<u32>& size)\r
267                         {\r
268                                 WindowSize = size;\r
269                                 if (size.Width!=0)\r
270                                         InvWindowSize.Width = 1.0f / size.Width;\r
271                                 else\r
272                                         InvWindowSize.Width = 0.f;\r
273 \r
274                                 if (size.Height!=0)\r
275                                         InvWindowSize.Height = 1.0f / size.Height;\r
276                                 else\r
277                                         InvWindowSize.Height = 0.f;\r
278                         }\r
279 \r
280                         /** Used to notify the cursor that the window resizable settings changed. */\r
281                         void updateBorderSize(bool fullscreen, bool resizable)\r
282                         {\r
283                                 if (!fullscreen)\r
284                                 {\r
285                                         s32 paddingBorder = 0;\r
286                                         #ifdef SM_CXPADDEDBORDER\r
287                                                 paddingBorder = GetSystemMetrics(SM_CXPADDEDBORDER);\r
288                                         #endif\r
289 \r
290                                         if (resizable)\r
291                                         {\r
292                                                 BorderX = GetSystemMetrics(SM_CXSIZEFRAME) + paddingBorder;\r
293                                                 BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) + paddingBorder;\r
294                                         }\r
295                                         else\r
296                                         {\r
297                                                 BorderX = GetSystemMetrics(SM_CXDLGFRAME) + paddingBorder;\r
298                                                 BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME) + paddingBorder;\r
299                                         }\r
300                                 }\r
301                                 else\r
302                                 {\r
303                                         BorderX = BorderY = 0;\r
304                                 }\r
305                         }\r
306 \r
307 \r
308                         //! Sets the active cursor icon\r
309                         virtual void setActiveIcon(gui::ECURSOR_ICON iconId) _IRR_OVERRIDE_;\r
310 \r
311                         //! Gets the currently active icon\r
312                         virtual gui::ECURSOR_ICON getActiveIcon() const _IRR_OVERRIDE_\r
313                         {\r
314                                 return ActiveIcon;\r
315                         }\r
316 \r
317                         //! Add a custom sprite as cursor icon.\r
318                         virtual gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) _IRR_OVERRIDE_;\r
319 \r
320                         //! replace the given cursor icon.\r
321                         virtual void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) _IRR_OVERRIDE_;\r
322 \r
323                         //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.\r
324                         virtual core::dimension2di getSupportedIconSize() const _IRR_OVERRIDE_;\r
325 \r
326                         void update();\r
327 \r
328                 private:\r
329 \r
330                         //! Updates the internal cursor position\r
331                         void updateInternalCursorPosition()\r
332                         {\r
333                                 POINT p;\r
334                                 if (!GetCursorPos(&p))\r
335                                 {\r
336                                         DWORD xy = GetMessagePos();\r
337                                         p.x = GET_X_LPARAM(xy);\r
338                                         p.y = GET_Y_LPARAM(xy);\r
339                                 }\r
340 \r
341                                 if (UseReferenceRect)\r
342                                 {\r
343                                         CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X;\r
344                                         CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y;\r
345                                 }\r
346                                 else\r
347                                 {\r
348                                         RECT rect;\r
349                                         if (GetWindowRect(HWnd, &rect))\r
350                                         {\r
351                                                 CursorPos.X = p.x-rect.left-BorderX;\r
352                                                 CursorPos.Y = p.y-rect.top-BorderY;\r
353                                         }\r
354                                         else\r
355                                         {\r
356                                                 // window seems not to be existent, so set cursor to\r
357                                                 // a negative value\r
358                                                 CursorPos.X = -1;\r
359                                                 CursorPos.Y = -1;\r
360                                         }\r
361                                 }\r
362                         }\r
363 \r
364                         CIrrDeviceWin32* Device;\r
365                         core::position2d<s32> CursorPos;\r
366                         core::dimension2d<u32> WindowSize;\r
367                         core::dimension2d<f32> InvWindowSize;\r
368                         HWND HWnd;\r
369 \r
370                         s32 BorderX, BorderY;\r
371                         core::rect<s32> ReferenceRect;\r
372                         bool UseReferenceRect;\r
373                         bool IsVisible;\r
374 \r
375 \r
376                         struct CursorFrameW32\r
377                         {\r
378                                 CursorFrameW32() : IconHW(0) {}\r
379                                 CursorFrameW32(HCURSOR icon) : IconHW(icon) {}\r
380 \r
381                                 HCURSOR IconHW; // hardware cursor\r
382                         };\r
383 \r
384                         struct CursorW32\r
385                         {\r
386                                 CursorW32() {}\r
387                                 explicit CursorW32(HCURSOR iconHw, u32 frameTime=0) : FrameTime(frameTime)\r
388                                 {\r
389                                         Frames.push_back( CursorFrameW32(iconHw) );\r
390                                 }\r
391                                 core::array<CursorFrameW32> Frames;\r
392                                 u32 FrameTime;\r
393                         };\r
394 \r
395                         core::array<CursorW32> Cursors;\r
396                         gui::ECURSOR_ICON ActiveIcon;\r
397                         u32 ActiveIconStartTime;\r
398 \r
399                         void initCursors();\r
400                 };\r
401 \r
402                 //! returns the win32 cursor control\r
403                 CCursorControl* getWin32CursorControl();\r
404 \r
405         private:\r
406 \r
407                 //! create the driver\r
408                 void createDriver();\r
409 \r
410                 //! Process system events\r
411                 void handleSystemMessages();\r
412 \r
413                 void getWindowsVersion(core::stringc& version);\r
414 \r
415                 void resizeIfNecessary();\r
416 \r
417                 DWORD getWindowStyle(bool fullscreen, bool resizable) const;\r
418 \r
419                 HWND HWnd;\r
420 \r
421                 bool Resized;\r
422                 bool ExternalWindow;\r
423                 CCursorControl* Win32CursorControl;\r
424 \r
425                 SJoystickWin32Control* JoyControl;\r
426         };\r
427 \r
428 } // end namespace irr\r
429 \r
430 #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_\r
431 #endif // __C_IRR_DEVICE_WIN32_H_INCLUDED__\r