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