Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/freeglut/src/mswin/fg_window_mswin.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * fg_window_mswin.c | |
| 3 * | |
| 4 * The Windows-specific mouse cursor related stuff. | |
| 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 #define FREEGLUT_BUILDING_LIB | |
| 29 #include <GL/freeglut.h> | |
| 30 #include "../fg_internal.h" | |
| 31 | |
| 32 | |
| 33 /* The following include file is available from SGI but is not standard: | |
| 34 * #include <GL/wglext.h> | |
| 35 * So we copy the necessary parts out of it. | |
| 36 * XXX: should local definitions for extensions be put in a separate include file? | |
| 37 */ | |
| 38 typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); | |
| 39 | |
| 40 typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); | |
| 41 | |
| 42 #define WGL_DRAW_TO_WINDOW_ARB 0x2001 | |
| 43 #define WGL_ACCELERATION_ARB 0x2003 | |
| 44 #define WGL_SUPPORT_OPENGL_ARB 0x2010 | |
| 45 #define WGL_DOUBLE_BUFFER_ARB 0x2011 | |
| 46 #define WGL_COLOR_BITS_ARB 0x2014 | |
| 47 #define WGL_ALPHA_BITS_ARB 0x201B | |
| 48 #define WGL_DEPTH_BITS_ARB 0x2022 | |
| 49 #define WGL_STENCIL_BITS_ARB 0x2023 | |
| 50 #define WGL_FULL_ACCELERATION_ARB 0x2027 | |
| 51 | |
| 52 #define WGL_SAMPLE_BUFFERS_ARB 0x2041 | |
| 53 #define WGL_SAMPLES_ARB 0x2042 | |
| 54 | |
| 55 #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 | |
| 56 | |
| 57 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 | |
| 58 | |
| 59 #ifndef WGL_ARB_create_context | |
| 60 #define WGL_ARB_create_context 1 | |
| 61 #ifdef WGL_WGLEXT_PROTOTYPES | |
| 62 extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *); | |
| 63 #endif /* WGL_WGLEXT_PROTOTYPES */ | |
| 64 typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); | |
| 65 | |
| 66 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 | |
| 67 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 | |
| 68 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 | |
| 69 #define WGL_CONTEXT_FLAGS_ARB 0x2094 | |
| 70 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 | |
| 71 | |
| 72 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 | |
| 73 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 | |
| 74 | |
| 75 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 | |
| 76 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 | |
| 77 | |
| 78 #define ERROR_INVALID_VERSION_ARB 0x2095 | |
| 79 #define ERROR_INVALID_PROFILE_ARB 0x2096 | |
| 80 #endif | |
| 81 /* End of copying the necessary parts out of it. */ | |
| 82 | |
| 83 #ifdef WM_TOUCH | |
| 84 typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG); | |
| 85 static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF; | |
| 86 #endif | |
| 87 | |
| 88 | |
| 89 /* | |
| 90 * Setup the pixel format for a Win32 window | |
| 91 */ | |
| 92 | |
| 93 #if defined(_WIN32_WCE) | |
| 94 static wchar_t* fghWstrFromStr(const char* str) | |
| 95 { | |
| 96 int i,len=strlen(str); | |
| 97 wchar_t* wstr = (wchar_t*)malloc(2*len+2); | |
| 98 for(i=0; i<len; i++) | |
| 99 wstr[i] = str[i]; | |
| 100 wstr[len] = 0; | |
| 101 return wstr; | |
| 102 } | |
| 103 #endif /* defined(_WIN32_WCE) */ | |
| 104 | |
| 105 | |
| 106 static void fghFillContextAttributes( int *attributes ) { | |
| 107 int where = 0, contextFlags, contextProfile; | |
| 108 | |
| 109 ATTRIB_VAL( WGL_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion ); | |
| 110 ATTRIB_VAL( WGL_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion ); | |
| 111 | |
| 112 contextFlags = | |
| 113 fghMapBit( fgState.ContextFlags, GLUT_DEBUG, WGL_CONTEXT_DEBUG_BIT_ARB ) | | |
| 114 fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB ); | |
| 115 if ( contextFlags != 0 ) { | |
| 116 ATTRIB_VAL( WGL_CONTEXT_FLAGS_ARB, contextFlags ); | |
| 117 } | |
| 118 | |
| 119 contextProfile = | |
| 120 fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, WGL_CONTEXT_CORE_PROFILE_BIT_ARB ) | | |
| 121 fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ); | |
| 122 if ( contextProfile != 0 ) { | |
| 123 ATTRIB_VAL( WGL_CONTEXT_PROFILE_MASK_ARB, contextProfile ); | |
| 124 } | |
| 125 | |
| 126 ATTRIB( 0 ); | |
| 127 } | |
| 128 | |
| 129 static int fghIsExtensionSupported( HDC hdc, const char *extension ) { | |
| 130 const char *pWglExtString; | |
| 131 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetEntensionsStringARB = | |
| 132 (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); | |
| 133 if ( wglGetEntensionsStringARB == NULL ) | |
| 134 { | |
| 135 return FALSE; | |
| 136 } | |
| 137 pWglExtString = wglGetEntensionsStringARB( hdc ); | |
| 138 return ( pWglExtString != NULL ) && ( strstr(pWglExtString, extension) != NULL ); | |
| 139 } | |
| 140 | |
| 141 void fgNewWGLCreateContext( SFG_Window* window ) | |
| 142 { | |
| 143 HGLRC context; | |
| 144 int attributes[9]; | |
| 145 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; | |
| 146 | |
| 147 /* If nothing fancy has been required, leave the context as it is */ | |
| 148 if ( fghIsLegacyContextRequested() ) | |
| 149 { | |
| 150 return; | |
| 151 } | |
| 152 | |
| 153 wglMakeCurrent( window->Window.pContext.Device, window->Window.Context ); | |
| 154 | |
| 155 if ( !fghIsExtensionSupported( window->Window.pContext.Device, "WGL_ARB_create_context" ) ) | |
| 156 { | |
| 157 /* wglCreateContextAttribsARB not found, yet the user has requested the new context creation */ | |
| 158 fgWarning( "OpenGL >2.1 context requested but wglCreateContextAttribsARB is not available! Falling back to legacy context creation" ); | |
| 159 /* Legacy context already created at this point in WM_CREATE path of fgPlatformWindowProc, just return */ | |
| 160 return; | |
| 161 } | |
| 162 | |
| 163 /* new context creation */ | |
| 164 fghFillContextAttributes( attributes ); | |
| 165 | |
| 166 wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" ); | |
| 167 if ( wglCreateContextAttribsARB == NULL ) | |
| 168 { | |
| 169 /* wglCreateContextAttribsARB not found, yet the user has requested the new context creation */ | |
| 170 fgWarning( "OpenGL >2.1 context requested but wglCreateContextAttribsARB is not available! Falling back to legacy context creation" ); | |
| 171 /* Legacy context already created at this point in WM_CREATE path of fgPlatformWindowProc, just return */ | |
| 172 return; | |
| 173 } | |
| 174 | |
| 175 context = wglCreateContextAttribsARB( window->Window.pContext.Device, 0, attributes ); | |
| 176 if ( context == NULL ) | |
| 177 { | |
| 178 fghContextCreationError(); | |
| 179 } | |
| 180 | |
| 181 wglMakeCurrent( NULL, NULL ); | |
| 182 wglDeleteContext( window->Window.Context ); | |
| 183 window->Window.Context = context; | |
| 184 } | |
| 185 | |
| 186 #if !defined(_WIN32_WCE) | |
| 187 | |
| 188 static void fghFillPFD( PIXELFORMATDESCRIPTOR *ppfd, HDC hdc, unsigned char layer_type ) | |
| 189 { | |
| 190 int flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; | |
| 191 if ( fgState.DisplayMode & GLUT_DOUBLE ) { | |
| 192 flags |= PFD_DOUBLEBUFFER; | |
| 193 } | |
| 194 if ( fgState.DisplayMode & GLUT_STEREO ) { | |
| 195 flags |= PFD_STEREO; | |
| 196 } | |
| 197 | |
| 198 #if defined(_MSC_VER) | |
| 199 #pragma message( "fgSetupPixelFormat(): there is still some work to do here!" ) | |
| 200 #endif | |
| 201 | |
| 202 /* Specify which pixel format do we opt for... */ | |
| 203 ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR); | |
| 204 ppfd->nVersion = 1; | |
| 205 ppfd->dwFlags = flags; | |
| 206 | |
| 207 if( fgState.DisplayMode & GLUT_INDEX ) { | |
| 208 ppfd->iPixelType = PFD_TYPE_COLORINDEX; | |
| 209 ppfd->cRedBits = 0; | |
| 210 ppfd->cGreenBits = 0; | |
| 211 ppfd->cBlueBits = 0; | |
| 212 ppfd->cAlphaBits = 0; | |
| 213 } else { | |
| 214 ppfd->iPixelType = PFD_TYPE_RGBA; | |
| 215 ppfd->cRedBits = 8; | |
| 216 ppfd->cGreenBits = 8; | |
| 217 ppfd->cBlueBits = 8; | |
| 218 ppfd->cAlphaBits = ( fgState.DisplayMode & GLUT_ALPHA ) ? 8 : 0; | |
| 219 } | |
| 220 | |
| 221 ppfd->cColorBits = 24; | |
| 222 ppfd->cRedShift = 0; | |
| 223 ppfd->cGreenShift = 0; | |
| 224 ppfd->cBlueShift = 0; | |
| 225 ppfd->cAlphaShift = 0; | |
| 226 ppfd->cAccumBits = ( fgState.DisplayMode & GLUT_ACCUM ) ? 1 : 0; | |
| 227 ppfd->cAccumRedBits = 0; | |
| 228 ppfd->cAccumGreenBits = 0; | |
| 229 ppfd->cAccumBlueBits = 0; | |
| 230 ppfd->cAccumAlphaBits = 0; | |
| 231 | |
| 232 /* Hmmm, or 32/0 instead of 24/8? */ | |
| 233 ppfd->cDepthBits = 24; | |
| 234 ppfd->cStencilBits = 8; | |
| 235 | |
| 236 ppfd->cAuxBuffers = (BYTE) fghNumberOfAuxBuffersRequested(); | |
| 237 ppfd->iLayerType = layer_type; | |
| 238 ppfd->bReserved = 0; | |
| 239 ppfd->dwLayerMask = 0; | |
| 240 ppfd->dwVisibleMask = 0; | |
| 241 ppfd->dwDamageMask = 0; | |
| 242 | |
| 243 ppfd->cColorBits = (BYTE) GetDeviceCaps( hdc, BITSPIXEL ); | |
| 244 } | |
| 245 | |
| 246 static void fghFillPixelFormatAttributes( int *attributes, const PIXELFORMATDESCRIPTOR *ppfd ) | |
| 247 { | |
| 248 int where = 0; | |
| 249 | |
| 250 ATTRIB_VAL( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE ); | |
| 251 ATTRIB_VAL( WGL_SUPPORT_OPENGL_ARB, GL_TRUE ); | |
| 252 ATTRIB_VAL( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB ); | |
| 253 | |
| 254 ATTRIB_VAL( WGL_COLOR_BITS_ARB, ppfd->cColorBits ); | |
| 255 ATTRIB_VAL( WGL_ALPHA_BITS_ARB, ppfd->cAlphaBits ); | |
| 256 ATTRIB_VAL( WGL_DEPTH_BITS_ARB, ppfd->cDepthBits ); | |
| 257 ATTRIB_VAL( WGL_STENCIL_BITS_ARB, ppfd->cStencilBits ); | |
| 258 | |
| 259 ATTRIB_VAL( WGL_DOUBLE_BUFFER_ARB, ( fgState.DisplayMode & GLUT_DOUBLE ) != 0 ); | |
| 260 | |
| 261 if ( fgState.DisplayMode & GLUT_SRGB ) { | |
| 262 ATTRIB_VAL( WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE ); | |
| 263 } | |
| 264 | |
| 265 ATTRIB_VAL( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE ); | |
| 266 ATTRIB_VAL( WGL_SAMPLES_ARB, fgState.SampleNumber ); | |
| 267 ATTRIB( 0 ); | |
| 268 } | |
| 269 #endif | |
| 270 | |
| 271 GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly, | |
| 272 unsigned char layer_type ) | |
| 273 { | |
| 274 #if defined(_WIN32_WCE) | |
| 275 return GL_TRUE; | |
| 276 #else | |
| 277 PIXELFORMATDESCRIPTOR pfd; | |
| 278 PIXELFORMATDESCRIPTOR* ppfd = &pfd; | |
| 279 int pixelformat; | |
| 280 HDC current_hDC; | |
| 281 GLboolean success; | |
| 282 | |
| 283 if (checkOnly) | |
| 284 current_hDC = CreateDC(TEXT("DISPLAY"), NULL ,NULL ,NULL); | |
| 285 else | |
| 286 current_hDC = window->Window.pContext.Device; | |
| 287 | |
| 288 fghFillPFD( ppfd, current_hDC, layer_type ); | |
| 289 pixelformat = ChoosePixelFormat( current_hDC, ppfd ); | |
| 290 | |
| 291 /* windows hack for multismapling/sRGB */ | |
| 292 if ( ( fgState.DisplayMode & GLUT_MULTISAMPLE ) || | |
| 293 ( fgState.DisplayMode & GLUT_SRGB ) ) | |
| 294 { | |
| 295 HGLRC rc, rc_before=wglGetCurrentContext(); | |
| 296 HWND hWnd; | |
| 297 HDC hDC, hDC_before=wglGetCurrentDC(); | |
| 298 WNDCLASS wndCls; | |
| 299 | |
| 300 /* create a dummy window */ | |
| 301 ZeroMemory(&wndCls, sizeof(wndCls)); | |
| 302 wndCls.lpfnWndProc = DefWindowProc; | |
| 303 wndCls.hInstance = fgDisplay.pDisplay.Instance; | |
| 304 wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; | |
| 305 wndCls.lpszClassName = _T("FREEGLUT_dummy"); | |
| 306 RegisterClass( &wndCls ); | |
| 307 | |
| 308 hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.pDisplay.Instance, 0 ); | |
| 309 hDC=GetDC(hWnd); | |
| 310 SetPixelFormat( hDC, pixelformat, ppfd ); | |
| 311 | |
| 312 rc = wglCreateContext( hDC ); | |
| 313 wglMakeCurrent(hDC, rc); | |
| 314 | |
| 315 if ( fghIsExtensionSupported( hDC, "WGL_ARB_multisample" ) ) | |
| 316 { | |
| 317 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBProc = | |
| 318 (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB"); | |
| 319 if ( wglChoosePixelFormatARBProc ) | |
| 320 { | |
| 321 int attributes[100]; | |
| 322 int iPixelFormat; | |
| 323 BOOL bValid; | |
| 324 float fAttributes[] = { 0, 0 }; | |
| 325 UINT numFormats; | |
| 326 fghFillPixelFormatAttributes( attributes, ppfd ); | |
| 327 bValid = wglChoosePixelFormatARBProc(hDC, attributes, fAttributes, 1, &iPixelFormat, &numFormats); | |
| 328 | |
| 329 if ( bValid && numFormats > 0 ) | |
| 330 { | |
| 331 pixelformat = iPixelFormat; | |
| 332 } | |
| 333 } | |
| 334 } | |
| 335 | |
| 336 wglMakeCurrent( hDC_before, rc_before); | |
| 337 wglDeleteContext(rc); | |
| 338 ReleaseDC(hWnd, hDC); | |
| 339 DestroyWindow(hWnd); | |
| 340 UnregisterClass(_T("FREEGLUT_dummy"), fgDisplay.pDisplay.Instance); | |
| 341 } | |
| 342 | |
| 343 success = ( pixelformat != 0 ) && ( checkOnly || SetPixelFormat( current_hDC, pixelformat, ppfd ) ); | |
| 344 | |
| 345 if (checkOnly) | |
| 346 DeleteDC(current_hDC); | |
| 347 | |
| 348 return success; | |
| 349 #endif /* defined(_WIN32_WCE) */ | |
| 350 } | |
| 351 | |
| 352 | |
| 353 | |
| 354 void fgPlatformSetWindow ( SFG_Window *window ) | |
| 355 { | |
| 356 if ( window != fgStructure.CurrentWindow ) | |
| 357 { | |
| 358 if( fgStructure.CurrentWindow ) | |
| 359 ReleaseDC( fgStructure.CurrentWindow->Window.Handle, | |
| 360 fgStructure.CurrentWindow->Window.pContext.Device ); | |
| 361 | |
| 362 if ( window ) | |
| 363 { | |
| 364 window->Window.pContext.Device = GetDC( window->Window.Handle ); | |
| 365 wglMakeCurrent( | |
| 366 window->Window.pContext.Device, | |
| 367 window->Window.Context | |
| 368 ); | |
| 369 } | |
| 370 } | |
| 371 } | |
| 372 | |
| 373 | |
| 374 void fghGetDefaultWindowStyle(DWORD *flags) | |
| 375 { | |
| 376 if ( fgState.DisplayMode & GLUT_BORDERLESS ) | |
| 377 { | |
| 378 /* no window decorations needed, no-op */ | |
| 379 } | |
| 380 else if ( fgState.DisplayMode & GLUT_CAPTIONLESS ) | |
| 381 /* only window decoration is a border, no title bar or buttons */ | |
| 382 (*flags) |= WS_DLGFRAME; | |
| 383 else | |
| 384 /* window decoration are a border, title bar and buttons. */ | |
| 385 (*flags) |= WS_OVERLAPPEDWINDOW; | |
| 386 } | |
| 387 | |
| 388 /* Get window style and extended window style of a FreeGLUT window | |
| 389 * If the window pointer or the window handle is NULL, a fully | |
| 390 * decorated window (caption and border) is assumed. | |
| 391 */ | |
| 392 void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle ) | |
| 393 { | |
| 394 if (window && window->Window.Handle) | |
| 395 { | |
| 396 *windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); | |
| 397 *windowExStyle = GetWindowLong(window->Window.Handle, GWL_EXSTYLE); | |
| 398 } | |
| 399 else | |
| 400 { | |
| 401 *windowStyle = 0; | |
| 402 fghGetDefaultWindowStyle(windowStyle); | |
| 403 /* WindowExStyle==0 is fine/default, exStyle is currently only used for menu windows */ | |
| 404 *windowExStyle = 0; | |
| 405 } | |
| 406 } | |
| 407 | |
| 408 /* Computes position of corners of window Rect (outer position including | |
| 409 * decorations) based on the provided client rect and based on the style | |
| 410 * of the window in question. | |
| 411 * If posIsOutside is set to true, the input client Rect is taken to follow | |
| 412 * freeGLUT's window specification convention in which the top-left corner | |
| 413 * is at the outside of the window, while the size | |
| 414 * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable | |
| 415 * area. | |
| 416 */ | |
| 417 void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside ) | |
| 418 { | |
| 419 RECT windowRect = {0,0,0,0}; | |
| 420 CopyRect(&windowRect,clientRect); | |
| 421 | |
| 422 /* Get rect including non-client area */ | |
| 423 AdjustWindowRectEx(&windowRect,windowStyle,FALSE,windowExStyle); | |
| 424 | |
| 425 /* Move window right and down by non-client area extent on left and top, if wanted */ | |
| 426 if (posIsOutside) | |
| 427 { | |
| 428 windowRect.right += clientRect->left-windowRect.left; | |
| 429 windowRect.bottom += clientRect->top -windowRect.top; | |
| 430 windowRect.left = clientRect->left; | |
| 431 windowRect.top = clientRect->top; | |
| 432 } | |
| 433 | |
| 434 /* done, copy windowRect to output */ | |
| 435 CopyRect(clientRect,&windowRect); | |
| 436 } | |
| 437 | |
| 438 /* Computes position of corners of window Rect (outer position including | |
| 439 * decorations) based on the provided client rect and based on the style | |
| 440 * of the window in question. If the window pointer or the window handle | |
| 441 * is NULL, a fully decorated window (caption and border) is assumed. | |
| 442 * Furthermore, if posIsOutside is set to true, the input client Rect is | |
| 443 * taken to follow freeGLUT's window specification convention in which the | |
| 444 * top-left corner is at the outside of the window, while the size | |
| 445 * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable | |
| 446 * area. | |
| 447 */ | |
| 448 void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ) | |
| 449 { | |
| 450 DWORD windowStyle = 0, windowExStyle = 0; | |
| 451 fghGetStyleFromWindow(window,&windowStyle,&windowExStyle); | |
| 452 | |
| 453 fghComputeWindowRectFromClientArea_UseStyle(clientRect, windowStyle, windowExStyle, posIsOutside); | |
| 454 } | |
| 455 | |
| 456 /* Gets the rect describing the client area (drawable area) of the | |
| 457 * specified window. Output is position of corners of client area (drawable area) on the screen. | |
| 458 * Does not touch clientRect if window pointer or window handle is NULL. | |
| 459 * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable area. | |
| 460 * if posIsOutside is true, the output client Rect will follow freeGLUT's window | |
| 461 * specification convention in which the top-left corner is at the outside of | |
| 462 * the window, while the size (rect.right-rect.left,rect.bottom-rect.top) remains to be the | |
| 463 * size of the drawable area. | |
| 464 */ | |
| 465 void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ) | |
| 466 { | |
| 467 POINT topLeftClient = {0,0}; | |
| 468 | |
| 469 freeglut_return_if_fail((window && window->Window.Handle)); | |
| 470 | |
| 471 /* Get size of client rect */ | |
| 472 GetClientRect(window->Window.Handle, clientRect); | |
| 473 if (posIsOutside) | |
| 474 { | |
| 475 RECT windowRect; | |
| 476 /* Get position of outside of window, including decorations */ | |
| 477 GetWindowRect(window->Window.Handle,&windowRect); | |
| 478 /* Add top-left offset */ | |
| 479 OffsetRect(clientRect,windowRect.left,windowRect.top); | |
| 480 } | |
| 481 else | |
| 482 { | |
| 483 /* Get position of top-left of client area on the screen */ | |
| 484 ClientToScreen(window->Window.Handle,&topLeftClient); | |
| 485 /* Add top-left offset */ | |
| 486 OffsetRect(clientRect,topLeftClient.x,topLeftClient.y); | |
| 487 } | |
| 488 } | |
| 489 | |
| 490 | |
| 491 #if(WINVER >= 0x500) | |
| 492 typedef struct | |
| 493 { | |
| 494 int *x; | |
| 495 int *y; | |
| 496 const char *name; | |
| 497 } m_proc_t; | |
| 498 | |
| 499 static BOOL CALLBACK m_proc(HMONITOR mon, | |
| 500 HDC hdc, | |
| 501 LPRECT rect, | |
| 502 LPARAM data) | |
| 503 { | |
| 504 m_proc_t *dp=(m_proc_t *)data; | |
| 505 MONITORINFOEX info; | |
| 506 BOOL res; | |
| 507 info.cbSize=sizeof(info); | |
| 508 res=GetMonitorInfo(mon,(LPMONITORINFO)&info); | |
| 509 if( res ) | |
| 510 { | |
| 511 if( strcmp(dp->name,info.szDevice)==0 ) | |
| 512 { | |
| 513 *(dp->x)=info.rcMonitor.left; | |
| 514 *(dp->y)=info.rcMonitor.top; | |
| 515 return FALSE; | |
| 516 } | |
| 517 } | |
| 518 return TRUE; | |
| 519 } | |
| 520 | |
| 521 /* | |
| 522 * this function returns the origin of the screen identified by | |
| 523 * fgDisplay.pDisplay.DisplayName, and 0 otherwise. | |
| 524 * This is used in fgOpenWindow to open the gamemode window on the screen | |
| 525 * identified by the -display command line argument. The function should | |
| 526 * not be called otherwise. | |
| 527 */ | |
| 528 | |
| 529 static void get_display_origin(int *xp,int *yp) | |
| 530 { | |
| 531 *xp = 0; | |
| 532 *yp = 0; | |
| 533 | |
| 534 if( fgDisplay.pDisplay.DisplayName ) | |
| 535 { | |
| 536 m_proc_t st; | |
| 537 st.x=xp; | |
| 538 st.y=yp; | |
| 539 st.name=fgDisplay.pDisplay.DisplayName; | |
| 540 EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st); | |
| 541 } | |
| 542 } | |
| 543 #else | |
| 544 #pragma message( "-display parameter only works if compiled with WINVER >= 0x0500") | |
| 545 | |
| 546 static void get_display_origin(int *xp,int *yp) | |
| 547 { | |
| 548 *xp = 0; | |
| 549 *yp = 0; | |
| 550 | |
| 551 if( fgDisplay.pDisplay.DisplayName ) | |
| 552 { | |
| 553 fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500"); | |
| 554 } | |
| 555 } | |
| 556 #endif | |
| 557 | |
| 558 | |
| 559 | |
| 560 /* | |
| 561 * Opens a window. Requires a SFG_Window object created and attached | |
| 562 * to the freeglut structure. OpenGL context is created here. | |
| 563 */ | |
| 564 void fgPlatformOpenWindow( SFG_Window* window, const char* title, | |
| 565 GLboolean positionUse, int x, int y, | |
| 566 GLboolean sizeUse, int w, int h, | |
| 567 GLboolean gameMode, GLboolean isSubWindow ) | |
| 568 { | |
| 569 | |
| 570 WNDCLASS wc; | |
| 571 DWORD flags = 0; | |
| 572 DWORD exFlags = 0; | |
| 573 BOOL atom; | |
| 574 | |
| 575 /* Grab the window class we have registered on glutInit(): */ | |
| 576 atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc ); | |
| 577 FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found", | |
| 578 "fgOpenWindow" ); | |
| 579 | |
| 580 /* Determine window style flags*/ | |
| 581 if( gameMode ) | |
| 582 { | |
| 583 FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL, | |
| 584 "Game mode being invoked on a subwindow", | |
| 585 "fgOpenWindow" ); | |
| 586 | |
| 587 /* | |
| 588 * Set the window creation flags appropriately to make the window | |
| 589 * entirely visible: | |
| 590 */ | |
| 591 flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; | |
| 592 } | |
| 593 else | |
| 594 { | |
| 595 flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; | |
| 596 | |
| 597 /* | |
| 598 * There's a small difference between creating the top, child and | |
| 599 * menu windows | |
| 600 */ | |
| 601 if ( window->IsMenu ) | |
| 602 { | |
| 603 flags |= WS_POPUP; | |
| 604 exFlags |= WS_EX_TOOLWINDOW; | |
| 605 } | |
| 606 #if defined(_WIN32_WCE) | |
| 607 /* no decorations for windows CE */ | |
| 608 #else | |
| 609 /* if this is not a subwindow (child), set its style based on the requested window decorations */ | |
| 610 else if( window->Parent == NULL ) | |
| 611 fghGetDefaultWindowStyle(&flags); | |
| 612 #endif | |
| 613 else | |
| 614 /* subwindows always have no decoration, but are marked as a child window to the OS */ | |
| 615 flags |= WS_CHILD; | |
| 616 } | |
| 617 | |
| 618 /* determine window size and position */ | |
| 619 if( gameMode ) | |
| 620 { | |
| 621 /* if in gamemode, query the origin of specified by the -display | |
| 622 * command line parameter (if any) and offset the upper-left corner | |
| 623 * of the window so we create the window on that screen. | |
| 624 * The -display argument doesn't do anything if not trying to enter | |
| 625 * gamemode. | |
| 626 */ | |
| 627 int xoff=0, yoff=0; | |
| 628 get_display_origin(&xoff,&yoff); | |
| 629 x += xoff; | |
| 630 y += yoff; | |
| 631 } | |
| 632 if( !positionUse ) | |
| 633 { | |
| 634 x = CW_USEDEFAULT; | |
| 635 y = CW_USEDEFAULT; | |
| 636 } | |
| 637 if( !sizeUse ) | |
| 638 { | |
| 639 w = CW_USEDEFAULT; | |
| 640 h = CW_USEDEFAULT; | |
| 641 } | |
| 642 #if !defined(_WIN32_WCE) /* no decorations for windows CE, so nothing to do */ | |
| 643 else | |
| 644 { | |
| 645 RECT windowRect; | |
| 646 /* | |
| 647 * Update the window dimensions, taking the window decorations | |
| 648 * into account. FreeGLUT is to create the window with the | |
| 649 * topleft outside corner at (x,y) and with client area | |
| 650 * dimensions (w,h). | |
| 651 * note: don't need to do this when w=h=CW_USEDEFAULT, so in the | |
| 652 * if( sizeUse ) here is convenient. | |
| 653 */ | |
| 654 windowRect.left = x; | |
| 655 windowRect.top = y; | |
| 656 windowRect.right = x+w; | |
| 657 windowRect.bottom = y+h; | |
| 658 | |
| 659 fghComputeWindowRectFromClientArea_UseStyle(&windowRect,flags,exFlags,TRUE); | |
| 660 | |
| 661 /* NB: w and h are now width and height of window including non-client area! */ | |
| 662 w = windowRect.right - windowRect.left; | |
| 663 h = windowRect.bottom- windowRect.top; | |
| 664 } | |
| 665 #endif /* !defined(_WIN32_WCE) */ | |
| 666 | |
| 667 #if defined(_WIN32_WCE) | |
| 668 { | |
| 669 wchar_t* wstr = fghWstrFromStr(title); | |
| 670 | |
| 671 window->Window.Handle = CreateWindow( | |
| 672 _T("FREEGLUT"), | |
| 673 wstr, | |
| 674 WS_VISIBLE | WS_POPUP, | |
| 675 0,0, 240,320, | |
| 676 NULL, | |
| 677 NULL, | |
| 678 fgDisplay.pDisplay.Instance, | |
| 679 (LPVOID) window | |
| 680 ); | |
| 681 | |
| 682 free(wstr); | |
| 683 | |
| 684 SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON); | |
| 685 SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON); | |
| 686 SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR); | |
| 687 MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE); | |
| 688 ShowWindow(window->Window.Handle, SW_SHOW); | |
| 689 UpdateWindow(window->Window.Handle); | |
| 690 } | |
| 691 #else | |
| 692 window->Window.Handle = CreateWindowEx( | |
| 693 exFlags, | |
| 694 _T("FREEGLUT"), | |
| 695 title, | |
| 696 flags, | |
| 697 x, y, w, h, | |
| 698 (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle, | |
| 699 (HMENU) NULL, | |
| 700 fgDisplay.pDisplay.Instance, | |
| 701 (LPVOID) window | |
| 702 ); | |
| 703 #endif /* defined(_WIN32_WCE) */ | |
| 704 | |
| 705 /* WM_CREATE message got sent and was handled by window proc */ | |
| 706 | |
| 707 if( !( window->Window.Handle ) ) | |
| 708 fgError( "Failed to create a window (%s)!", title ); | |
| 709 | |
| 710 /* Store title */ | |
| 711 window->State.pWState.WindowTitle = strdup(title); | |
| 712 | |
| 713 #if !defined(_WIN32_WCE) | |
| 714 /* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */ | |
| 715 SetWindowLong(window->Window.Handle, GWL_STYLE, flags); | |
| 716 SetWindowPos(window->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); | |
| 717 #endif /* defined(_WIN32_WCE) */ | |
| 718 | |
| 719 /* Make a menu window always on top - fix Feature Request 947118 */ | |
| 720 if( window->IsMenu || gameMode ) | |
| 721 SetWindowPos( | |
| 722 window->Window.Handle, | |
| 723 HWND_TOPMOST, | |
| 724 0, 0, 0, 0, | |
| 725 SWP_NOMOVE | SWP_NOSIZE | |
| 726 ); | |
| 727 | |
| 728 /* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */ | |
| 729 #ifdef WM_TOUCH | |
| 730 if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF) | |
| 731 fghRegisterTouchWindow = (pRegisterTouchWindow)GetProcAddress(GetModuleHandle("user32"),"RegisterTouchWindow"); | |
| 732 if (fghRegisterTouchWindow) | |
| 733 fghRegisterTouchWindow( window->Window.Handle, TWF_FINETOUCH | TWF_WANTPALM ); | |
| 734 #endif | |
| 735 | |
| 736 #if defined(_WIN32_WCE) | |
| 737 ShowWindow( window->Window.Handle, SW_SHOW ); | |
| 738 #else | |
| 739 if (!window->IsMenu) /* Don't show window after creation if its a menu */ | |
| 740 { | |
| 741 BOOL iconic = fgState.ForceIconic && !gameMode && !isSubWindow; | |
| 742 ShowWindow( window->Window.Handle, | |
| 743 iconic ? SW_SHOWMINIMIZED : SW_SHOWNORMAL ); | |
| 744 } | |
| 745 #endif /* defined(_WIN32_WCE) */ | |
| 746 | |
| 747 ShowCursor( TRUE ); | |
| 748 } | |
| 749 | |
| 750 | |
| 751 /* | |
| 752 * Closes a window, destroying the frame and OpenGL context | |
| 753 */ | |
| 754 void fgPlatformCloseWindow( SFG_Window* window ) | |
| 755 { | |
| 756 /* Make sure we don't close a window with current context active */ | |
| 757 if( fgStructure.CurrentWindow == window ) | |
| 758 wglMakeCurrent( NULL, NULL ); | |
| 759 | |
| 760 /* | |
| 761 * Step through the list of windows. If the rendering context | |
| 762 * is not being used by another window, then we delete it. | |
| 763 */ | |
| 764 { | |
| 765 int used = FALSE ; | |
| 766 SFG_Window *iter ; | |
| 767 | |
| 768 for( iter = (SFG_Window *)fgStructure.Windows.First; | |
| 769 iter; | |
| 770 iter = (SFG_Window *)iter->Node.Next ) | |
| 771 { | |
| 772 if( ( iter->Window.Context == window->Window.Context ) && | |
| 773 ( iter != window ) ) | |
| 774 used = TRUE; | |
| 775 } | |
| 776 | |
| 777 if( ! used ) | |
| 778 wglDeleteContext( window->Window.Context ); | |
| 779 } | |
| 780 | |
| 781 DestroyWindow( window->Window.Handle ); | |
| 782 | |
| 783 /* clean up copied title text(s) */ | |
| 784 if (window->State.pWState.WindowTitle) | |
| 785 free(window->State.pWState.WindowTitle); | |
| 786 if (window->State.pWState.IconTitle) | |
| 787 free(window->State.pWState.IconTitle); | |
| 788 } | |
| 789 | |
| 790 /* | |
| 791 * Hide's specified window. For windows, currently only used | |
| 792 * to immediately hide menu windows... | |
| 793 */ | |
| 794 void fgPlatformHideWindow( SFG_Window* window ) | |
| 795 { | |
| 796 ShowWindow(window->Window.Handle, SW_HIDE); | |
| 797 } | |
| 798 | |
| 799 | |
| 800 /* | |
| 801 * Set the current window's title | |
| 802 */ | |
| 803 void fgPlatformGlutSetWindowTitle( const char* title ) | |
| 804 { | |
| 805 #ifdef _WIN32_WCE | |
| 806 { | |
| 807 wchar_t* wstr = fghWstrFromStr(title); | |
| 808 SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr ); | |
| 809 free(wstr); | |
| 810 } | |
| 811 #else | |
| 812 if (!IsIconic(fgStructure.CurrentWindow->Window.Handle)) | |
| 813 SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); | |
| 814 #endif | |
| 815 | |
| 816 /* Make copy of string to refer to later */ | |
| 817 if (fgStructure.CurrentWindow->State.pWState.WindowTitle) | |
| 818 free(fgStructure.CurrentWindow->State.pWState.WindowTitle); | |
| 819 fgStructure.CurrentWindow->State.pWState.WindowTitle = strdup(title); | |
| 820 } | |
| 821 | |
| 822 /* | |
| 823 * Set the current window's iconified title | |
| 824 */ | |
| 825 void fgPlatformGlutSetIconTitle( const char* title ) | |
| 826 { | |
| 827 #ifndef _WIN32_WCE | |
| 828 if (IsIconic(fgStructure.CurrentWindow->Window.Handle)) | |
| 829 SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); | |
| 830 #endif | |
| 831 | |
| 832 /* Make copy of string to refer to later */ | |
| 833 if (fgStructure.CurrentWindow->State.pWState.IconTitle) | |
| 834 free(fgStructure.CurrentWindow->State.pWState.IconTitle); | |
| 835 fgStructure.CurrentWindow->State.pWState.IconTitle = strdup(title); | |
| 836 } | |
| 837 | |
| 838 | |
| 839 /* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */ | |
| 840 | |
| 841 int FGAPIENTRY __glutCreateWindowWithExit( const char *title, void (__cdecl *exit_function)(int) ) | |
| 842 { | |
| 843 __glutExitFunc = exit_function; | |
| 844 return glutCreateWindow( title ); | |
| 845 } | |
| 846 |
