glutGet(GLUT_WINDOW_X) and glutGet(GLUT_WINDOW_Y) on a child window now
[freeglut] / src / mswin / fg_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 "../fg_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 #if defined(_WIN32_WCE)
51 #   include <Aygshell.h>
52 #   ifdef FREEGLUT_LIB_PRAGMAS
53 #       pragma comment( lib, "Aygshell.lib" )
54 #   endif
55 #endif /* defined(_WIN32_WCE) */
56
57
58
59 int fgPlatformGlutGet ( GLenum eWhat )
60 {
61     int returnValue ;
62     GLboolean boolValue ;
63
64     int nsamples = 0;
65
66     switch( eWhat )
67     {
68     case GLUT_WINDOW_NUM_SAMPLES:
69       glGetIntegerv(WGL_SAMPLES_ARB, &nsamples);
70       return nsamples;
71
72     /* Handle the OpenGL inquiries */
73     case GLUT_WINDOW_RGBA:
74 #if defined(_WIN32_WCE)
75       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
76 #else
77       glGetBooleanv ( GL_RGBA_MODE, &boolValue );
78       returnValue = boolValue ? 1 : 0;
79 #endif
80       return returnValue;
81     case GLUT_WINDOW_DOUBLEBUFFER:
82 #if defined(_WIN32_WCE)
83       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
84 #else
85       glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
86       returnValue = boolValue ? 1 : 0;
87 #endif
88       return returnValue;
89     case GLUT_WINDOW_STEREO:
90 #if defined(_WIN32_WCE)
91       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
92 #else
93       glGetBooleanv ( GL_STEREO, &boolValue );
94       returnValue = boolValue ? 1 : 0;
95 #endif
96       return returnValue;
97
98     case GLUT_WINDOW_RED_SIZE:
99       glGetIntegerv ( GL_RED_BITS, &returnValue );
100       return returnValue;
101     case GLUT_WINDOW_GREEN_SIZE:
102       glGetIntegerv ( GL_GREEN_BITS, &returnValue );
103       return returnValue;
104     case GLUT_WINDOW_BLUE_SIZE:
105       glGetIntegerv ( GL_BLUE_BITS, &returnValue );
106       return returnValue;
107     case GLUT_WINDOW_ALPHA_SIZE:
108       glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
109       return returnValue;
110     case GLUT_WINDOW_ACCUM_RED_SIZE:
111 #if defined(_WIN32_WCE)
112       returnValue = 0;  /* WinCE doesn't support this feature */
113 #else
114       glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
115 #endif
116       return returnValue;
117     case GLUT_WINDOW_ACCUM_GREEN_SIZE:
118 #if defined(_WIN32_WCE)
119       returnValue = 0;  /* WinCE doesn't support this feature */
120 #else
121       glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
122 #endif
123       return returnValue;
124     case GLUT_WINDOW_ACCUM_BLUE_SIZE:
125 #if defined(_WIN32_WCE)
126       returnValue = 0;  /* WinCE doesn't support this feature */
127 #else
128       glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
129 #endif
130       return returnValue;
131     case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
132 #if defined(_WIN32_WCE)
133       returnValue = 0;  /* WinCE doesn't support this feature */
134 #else
135       glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
136 #endif
137       return returnValue;
138     case GLUT_WINDOW_DEPTH_SIZE:
139       glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
140       return returnValue;
141
142     case GLUT_WINDOW_BUFFER_SIZE:
143       returnValue = 1 ;                                      /* TODO????? */
144       return returnValue;
145     case GLUT_WINDOW_STENCIL_SIZE:
146       returnValue = 0 ;                                      /* TODO????? */
147       return returnValue;
148
149     case GLUT_WINDOW_X:
150     case GLUT_WINDOW_Y:
151     case GLUT_WINDOW_WIDTH:
152     case GLUT_WINDOW_HEIGHT:
153     {
154         /*
155          *  There is considerable confusion about the "right thing to
156          *  do" concerning window  size and position.  GLUT itself is
157          *  not consistent between Windows and UNIX/X11; since
158          *  platform independence is a virtue for "freeglut", we
159          *  decided to break with GLUT's behaviour.
160          *
161          *  Under UNIX/X11, it is apparently not possible to get the
162          *  window border sizes in order to subtract them off the
163          *  window's initial position until some time after the window
164          *  has been created.  Therefore we decided on the following
165          *  behaviour, both under Windows and under UNIX/X11:
166          *  - When you create a window with position (x,y) and size
167          *    (w,h), the upper left hand corner of the outside of the
168          *    window is at (x,y) and the size of the drawable area  is
169          *    (w,h).
170          *  - When you query the size and position of the window--as
171          *    is happening here for Windows--"freeglut" will return
172          *    the size of the drawable area--the (w,h) that you
173          *    specified when you created the window--and the coordinates
174          *    of the upper left hand corner of the drawable
175          *    area--which is NOT the (x,y) you specified.
176          */
177
178         RECT winRect;
179
180         freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
181
182 #if defined(_WIN32_WCE)
183         GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
184 #else
185         winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
186         if (fgStructure.CurrentWindow->Parent && (eWhat==GLUT_WINDOW_X || eWhat==GLUT_WINDOW_Y))
187         {
188             /* For child window, we should return relative to upper-left
189              *  of parent's client area.
190              */
191             POINT topleft;
192             topleft.x = winRect.left;
193             topleft.y = winRect.top;
194
195             ScreenToClient(fgStructure.CurrentWindow->Parent->Window.Handle,&topleft);
196             winRect.left = topleft.x;
197             winRect.top  = topleft.y;
198         }
199 #endif /* defined(_WIN32_WCE) */
200
201         switch( eWhat )
202         {
203         case GLUT_WINDOW_X:      return winRect.left                ;
204         case GLUT_WINDOW_Y:      return winRect.top                 ;
205         case GLUT_WINDOW_WIDTH:  return winRect.right - winRect.left;
206         case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
207         }
208     }
209     break;
210
211     case GLUT_WINDOW_BORDER_WIDTH :
212     case GLUT_WINDOW_HEADER_HEIGHT :
213 #if defined(_WIN32_WCE)
214         return 0;
215 #else
216         {
217             DWORD windowStyle;
218
219             if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
220                 windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
221             else
222                 /* If no window, return sizes for a default window with title bar and border */
223                 windowStyle = WS_OVERLAPPEDWINDOW;
224             
225             switch( eWhat )
226             {
227             case GLUT_WINDOW_BORDER_WIDTH:
228                 {
229                     int xBorderWidth, yBorderWidth;
230                     fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
231                     return xBorderWidth;
232                 }
233             case GLUT_WINDOW_HEADER_HEIGHT:
234                 /* 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... */
235                 return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
236             }
237         }
238 #endif /* defined(_WIN32_WCE) */
239
240     case GLUT_DISPLAY_MODE_POSSIBLE:
241 #if defined(_WIN32_WCE)
242         return 0;
243 #else
244         return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
245                                     PFD_MAIN_PLANE );
246 #endif /* defined(_WIN32_WCE) */
247
248
249     case GLUT_WINDOW_FORMAT_ID:
250 #if !defined(_WIN32_WCE)
251         if( fgStructure.CurrentWindow != NULL )
252             return GetPixelFormat( fgStructure.CurrentWindow->Window.pContext.Device );
253 #endif /* defined(_WIN32_WCE) */
254         return 0;
255
256     default:
257         fgWarning( "glutGet(): missing enum handle %d", eWhat );
258         break;
259     }
260
261         return -1;
262 }
263
264
265 int fgPlatformGlutDeviceGet ( GLenum eWhat )
266 {
267     switch( eWhat )
268     {
269     case GLUT_HAS_KEYBOARD:
270         /*
271          * Win32 is assumed a keyboard, and this cannot be queried,
272          * except for WindowsCE.
273          */
274 #if defined(_WIN32_CE)
275         return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;
276 #   if FREEGLUT_LIB_PRAGMAS
277 #       pragma comment (lib,"Kbdui.lib")
278 #   endif
279
280 #else
281         return 1;
282 #endif
283
284     case GLUT_HAS_MOUSE:
285         /*
286          * MS Windows can be booted without a mouse.
287          */
288         return GetSystemMetrics( SM_MOUSEPRESENT );
289
290     case GLUT_NUM_MOUSE_BUTTONS:
291 #  if defined(_WIN32_WCE)
292         return 1;
293 #  else
294         return GetSystemMetrics( SM_CMOUSEBUTTONS );
295 #  endif
296
297     default:
298         fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
299         break;
300     }
301
302     /* And now -- the failure. */
303     return -1;
304 }
305
306 /*
307  * This is for querying the number of supported auxiliary or multisample
308  * buffers for a (the current?) display mode.
309  * see http://old.nabble.com/-GLX--glutGetModeValues-to13514723.html#a13514723
310  * Not currently implemented, but we should be able to query the relevant
311  * info using
312  * http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
313  * (if supported on the executing machine!)
314  */
315 int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
316 {
317   *size = 0;
318   return NULL;
319 }