aa6e30f92e9a3a893d6c1124470b0d20e6f35fc6
[freeglut] / src / mswin / freeglut_state_mswin.c
1 /*
2  * freeglut_state_mswin.c
3  *
4  * The Windows-specific state query methods.
5  *
6  * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
7  * Written by John F. Fay, <fayjf@sourceforge.net>
8  * Creation date: Sun Jan 22, 2012
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #include <GL/freeglut.h>
29 #include "../Common/freeglut_internal.h"
30
31
32 extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
33                                      unsigned char layer_type );
34
35 /* 
36  * Helper functions for getting client area from the window rect
37  * and the window rect from the client area given the style of the window
38  * (or a valid window pointer from which the style can be queried).
39  */
40 extern RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside );
41 extern void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
42
43
44 /* The following include file is available from SGI but is not standard:
45  *   #include <GL/wglext.h>
46  * So we copy the necessary parts out of it to support the multisampling query
47  */
48 #define WGL_SAMPLES_ARB                0x2042
49
50
51
52 int fgPlatformGlutGet ( GLenum eWhat )
53 {
54     int returnValue ;
55     GLboolean boolValue ;
56
57     int nsamples = 0;
58
59     switch( eWhat )
60     {
61     case GLUT_WINDOW_NUM_SAMPLES:
62       glGetIntegerv(WGL_SAMPLES_ARB, &nsamples);
63       return nsamples;
64
65     /* Handle the OpenGL inquiries */
66     case GLUT_WINDOW_RGBA:
67 #if defined(_WIN32_WCE)
68       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
69 #else
70       glGetBooleanv ( GL_RGBA_MODE, &boolValue );
71       returnValue = boolValue ? 1 : 0;
72 #endif
73       return returnValue;
74     case GLUT_WINDOW_DOUBLEBUFFER:
75 #if defined(_WIN32_WCE)
76       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
77 #else
78       glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
79       returnValue = boolValue ? 1 : 0;
80 #endif
81       return returnValue;
82     case GLUT_WINDOW_STEREO:
83 #if defined(_WIN32_WCE)
84       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
85 #else
86       glGetBooleanv ( GL_STEREO, &boolValue );
87       returnValue = boolValue ? 1 : 0;
88 #endif
89       return returnValue;
90
91     case GLUT_WINDOW_RED_SIZE:
92       glGetIntegerv ( GL_RED_BITS, &returnValue );
93       return returnValue;
94     case GLUT_WINDOW_GREEN_SIZE:
95       glGetIntegerv ( GL_GREEN_BITS, &returnValue );
96       return returnValue;
97     case GLUT_WINDOW_BLUE_SIZE:
98       glGetIntegerv ( GL_BLUE_BITS, &returnValue );
99       return returnValue;
100     case GLUT_WINDOW_ALPHA_SIZE:
101       glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
102       return returnValue;
103     case GLUT_WINDOW_ACCUM_RED_SIZE:
104 #if defined(_WIN32_WCE)
105       returnValue = 0;  /* WinCE doesn't support this feature */
106 #else
107       glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
108 #endif
109       return returnValue;
110     case GLUT_WINDOW_ACCUM_GREEN_SIZE:
111 #if defined(_WIN32_WCE)
112       returnValue = 0;  /* WinCE doesn't support this feature */
113 #else
114       glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
115 #endif
116       return returnValue;
117     case GLUT_WINDOW_ACCUM_BLUE_SIZE:
118 #if defined(_WIN32_WCE)
119       returnValue = 0;  /* WinCE doesn't support this feature */
120 #else
121       glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
122 #endif
123       return returnValue;
124     case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
125 #if defined(_WIN32_WCE)
126       returnValue = 0;  /* WinCE doesn't support this feature */
127 #else
128       glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
129 #endif
130       return returnValue;
131     case GLUT_WINDOW_DEPTH_SIZE:
132       glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
133       return returnValue;
134
135     case GLUT_WINDOW_BUFFER_SIZE:
136       returnValue = 1 ;                                      /* ????? */
137       return returnValue;
138     case GLUT_WINDOW_STENCIL_SIZE:
139       returnValue = 0 ;                                      /* ????? */
140       return returnValue;
141
142     case GLUT_WINDOW_X:
143     case GLUT_WINDOW_Y:
144     case GLUT_WINDOW_WIDTH:
145     case GLUT_WINDOW_HEIGHT:
146     {
147         /*
148          *  There is considerable confusion about the "right thing to
149          *  do" concerning window  size and position.  GLUT itself is
150          *  not consistent between Windows and UNIX/X11; since
151          *  platform independence is a virtue for "freeglut", we
152          *  decided to break with GLUT's behaviour.
153          *
154          *  Under UNIX/X11, it is apparently not possible to get the
155          *  window border sizes in order to subtract them off the
156          *  window's initial position until some time after the window
157          *  has been created.  Therefore we decided on the following
158          *  behaviour, both under Windows and under UNIX/X11:
159          *  - When you create a window with position (x,y) and size
160          *    (w,h), the upper left hand corner of the outside of the
161          *    window is at (x,y) and the size of the drawable area  is
162          *    (w,h).
163          *  - When you query the size and position of the window--as
164          *    is happening here for Windows--"freeglut" will return
165          *    the size of the drawable area--the (w,h) that you
166          *    specified when you created the window--and the coordinates
167          *    of the upper left hand corner of the drawable
168          *    area--which is NOT the (x,y) you specified.
169          */
170
171         RECT winRect;
172
173         freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
174
175 #if defined(_WIN32_WCE)
176         GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
177 #else
178         winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
179 #endif /* defined(_WIN32_WCE) */
180
181         switch( eWhat )
182         {
183         case GLUT_WINDOW_X:      return winRect.left                ;
184         case GLUT_WINDOW_Y:      return winRect.top                 ;
185         case GLUT_WINDOW_WIDTH:  return winRect.right - winRect.left;
186         case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
187         }
188     }
189     break;
190
191     case GLUT_WINDOW_BORDER_WIDTH :
192     case GLUT_WINDOW_HEADER_HEIGHT :
193 #if defined(_WIN32_WCE)
194         return 0;
195 #else
196         {
197             DWORD windowStyle;
198
199             if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
200                 windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
201             else
202                 /* If no window, return sizes for a default window with title bar and border */
203                 windowStyle = WS_OVERLAPPEDWINDOW;
204             
205             switch( eWhat )
206             {
207             case GLUT_WINDOW_BORDER_WIDTH:
208                 {
209                     int xBorderWidth, yBorderWidth;
210                     fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
211                     return xBorderWidth;
212                 }
213             case GLUT_WINDOW_HEADER_HEIGHT:
214                 /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
215                 return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
216             }
217         }
218 #endif /* defined(_WIN32_WCE) */
219
220     case GLUT_DISPLAY_MODE_POSSIBLE:
221 #if defined(_WIN32_WCE)
222         return 0;
223 #else
224         return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
225                                     PFD_MAIN_PLANE );
226 #endif /* defined(_WIN32_WCE) */
227
228
229     case GLUT_WINDOW_FORMAT_ID:
230 #if !defined(_WIN32_WCE)
231         if( fgStructure.CurrentWindow != NULL )
232             return GetPixelFormat( fgStructure.CurrentWindow->Window.pContext.Device );
233 #endif /* defined(_WIN32_WCE) */
234         return 0;
235
236     default:
237         fgWarning( "glutGet(): missing enum handle %d", eWhat );
238         break;
239     }
240
241         return -1;
242 }
243
244
245 int fgPlatformGlutDeviceGet ( GLenum eWhat )
246 {
247     switch( eWhat )
248     {
249     case GLUT_HAS_KEYBOARD:
250         /*
251          * Win32 is assumed a keyboard, and this cannot be queried,
252          * except for WindowsCE.
253          *
254          * X11 has a core keyboard by definition, although it can
255          * be present as a virtual/dummy keyboard. For now, there
256          * is no reliable way to tell if a real keyboard is present.
257          */
258 #if defined(_WIN32_CE)
259         return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;
260 #   if FREEGLUT_LIB_PRAGMAS
261 #       pragma comment (lib,"Kbdui.lib")
262 #   endif
263
264 #else
265         return 1;
266 #endif
267
268     case GLUT_HAS_MOUSE:
269         /*
270          * MS Windows can be booted without a mouse.
271          */
272         return GetSystemMetrics( SM_MOUSEPRESENT );
273
274     case GLUT_NUM_MOUSE_BUTTONS:
275 #  if defined(_WIN32_WCE)
276         return 1;
277 #  else
278         return GetSystemMetrics( SM_CMOUSEBUTTONS );
279 #  endif
280
281     default:
282         fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
283         break;
284     }
285
286     /* And now -- the failure. */
287     return -1;
288 }
289
290
291 int fgPlatformGlutLayerGet( GLenum eWhat )
292 {
293     /*
294      * This is easy as layers are not implemented ;-)
295      *
296      * XXX Can we merge the UNIX/X11 and WIN32 sections?  Or
297      * XXX is overlay support planned?
298      */
299     switch( eWhat )
300     {
301
302     case GLUT_OVERLAY_POSSIBLE:
303 /*      return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
304                                    PFD_OVERLAY_PLANE ); */
305       return 0 ;
306
307     case GLUT_LAYER_IN_USE:
308         return GLUT_NORMAL;
309
310     case GLUT_HAS_OVERLAY:
311         return 0;
312
313     case GLUT_TRANSPARENT_INDEX:
314         /*
315          * Return just anything, which is always defined as zero
316          *
317          * XXX HUH?
318          */
319         return 0;
320
321     case GLUT_NORMAL_DAMAGED:
322         /* XXX Actually I do not know. Maybe. */
323         return 0;
324
325     case GLUT_OVERLAY_DAMAGED:
326         return -1;
327
328     default:
329         fgWarning( "glutLayerGet(): missing enum handle %d", eWhat );
330         break;
331     }
332
333     /* And fail. That's good. Programs do love failing. */
334     return -1;
335 }
336
337
338 /* MSwin does not currently have any Mode values? */
339 int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
340 {
341   *size = 0;
342   return NULL;
343 }