FreeWRL / FreeX3D 4.3.0
fwWindow32.c
1/*
2
3 FreeWRL support library.
4 FreeWRL main window : win32 code.
5
6*/
7/* #define WIN32_LEAN_AND_MEAN 1*/
8
9
10
11#include <config.h>
12
13#if defined(_MSC_VER)
14
15#include <system.h>
16#include <display.h>
17#include <main/headers.h>
18#include <windows.h>
19#include <windowsx.h>
20#include <shlwapi.h>
21
22#include <internal.h>
23
24#include <libFreeWRL.h>
25#include <float.h>
26#include "common.h"
27#include <ui/statusbar.h>
28
29void fv_swapbuffers(freewrl_params_t * d);
30bool fv_create_and_bind_GLcontext(freewrl_params_t * d);
31BOOL fwDisplayChange();
32void fwCloseContext();
33
34
35#ifdef ANGLEPROJECT
36//gles2 and egl
37#include <GLES2/gl2.h>
38#include <EGL/egl.h>
40#define ES_WINDOW_RGB 0
42#define ES_WINDOW_ALPHA 1
44#define ES_WINDOW_DEPTH 2
46#define ES_WINDOW_STENCIL 4
48#define ES_WINDOW_MULTISAMPLE 8
49
50//static EGLDisplay eglDisplay;
51//static EGLContext eglContext;
52//static EGLSurface eglSurface;
53void fv_swapbuffers(freewrl_params_t * d){
54 eglSwapBuffers((EGLDisplay)d->display,(EGLSurface)d->surface);
55}
56EGLBoolean fwCreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
57 EGLContext* eglContext, EGLSurface* eglSurface,
58 EGLint attribList[])
59{
60 EGLint numConfigs;
61 EGLint majorVersion;
62 EGLint minorVersion;
63 EGLDisplay display;
64 EGLContext context;
65 EGLSurface surface;
66 EGLConfig config;
67 HDC dc;
68 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
69
70 // Get Display
71 dc = GetDC(hWnd);
72 //printf("hWnd=%d\n",hWnd);
73 //printf("dc=%d\n",dc);
74 display = eglGetDisplay(dc); //GetDC(hWnd));
75// printf("display=%d\n",display);
76 if ( display == EGL_NO_DISPLAY ){
77 display = eglGetDisplay(EGL_DEFAULT_DISPLAY); //win32 goes in here
78// printf("display2=%d\n",display);
79 }
80 if ( display == EGL_NO_DISPLAY )
81 {
82 printf("Ouch - EGL_NO_DISPLAY\n");
83 return EGL_FALSE;
84 }
85 // Initialize EGL
86 if ( !eglInitialize(display, &majorVersion, &minorVersion) )
87 {
88 char errbuf[64];
89 int ierr = eglGetError();
90 sprintf(errbuf,"%x",ierr); //0x3001 EGL_NOT_INITIALIZED
91 //note to developer: 1) have you compiled fwlibEGL.lib/dll and fwlibGLES2.lib/dll with same/compatible compiler (egl calls glesv2 for renderer)
92 //2) do you have d3dcompiler_47+.dll in your .exe directory? (or d3dcompiler_46.dll, _43, installed to system32 via SetupDirect.exe?)
93 //3) are you using an angleproject hacked by dug9 in Renderer.cpp L.56 to do a LoadLibrary loop after the GetModuleHandleEx loop:
94 //if (!mD3dCompilerModule){
95 // //OK not preloaded. So lets try and load one
96 // for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i){
97 // if( mD3dCompilerModule = LoadLibrary(d3dCompilerNames[i])){
98 // break;
99 printf("Ouch no eglInitialize %d %s\n",ierr,errbuf);
100 return EGL_FALSE;
101 }
102 // Get configs
103 if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
104 {
105 printf("Ouch no eglGetConfigs\n");
106 return EGL_FALSE;
107 }
108
109 // Choose config
110 if ( !eglChooseConfig(display, attribList, &config, 1, &numConfigs) )
111 {
112 return EGL_FALSE;
113 }
114
115 // Create a surface
116 surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);
117 if ( surface == EGL_NO_SURFACE )
118 {
119 return EGL_FALSE;
120 }
121
122 // Create a GL context
123 context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
124 if ( context == EGL_NO_CONTEXT )
125 {
126 return EGL_FALSE;
127 }
128
129 // Make the context current
130 if ( !eglMakeCurrent(display, surface, surface, context) )
131 {
132 return EGL_FALSE;
133 }
134
135 *eglDisplay = display;
136 *eglSurface = surface;
137 *eglContext = context;
138 return EGL_TRUE;
139}
140
141bool fv_create_and_bind_GLcontext(freewrl_params_t * d){
142 //modified
143 EGLDisplay eglDisplay;
144 EGLContext eglContext;
145 EGLSurface eglSurface;
146 EGLNativeWindowType eglWindow;
147 GLuint flags = ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_STENCIL;
148 EGLint attribList[] =
149 {
150 EGL_RED_SIZE, 8,
151 EGL_GREEN_SIZE, 8,
152 EGL_BLUE_SIZE, 8,
153 EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
154 EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 24 : EGL_DONT_CARE,
155 EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
156 EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
157 EGL_NONE
158 };
159
160 //if ( esContext == NULL )
161 //{
162 // return GL_FALSE;
163 //}
164
165 //esContext->width = width;
166 //esContext->height = height;
167
168 //if ( !WinCreate ( esContext, title) )
169 //{
170 // return GL_FALSE;
171 //}
172 eglWindow = (EGLNativeWindowType) d->winToEmbedInto;
173 if ( !fwCreateEGLContext (eglWindow, // d->winToEmbedInto,
174 &eglDisplay,
175 &eglContext,
176 &eglSurface,
177 attribList) )
178 {
179 printf("Ouch CreateEGLContext returns FALSE\n");
180 return GL_FALSE;
181 }
182 d->context = (void*)eglContext;
183 d->display = (void*)eglDisplay;
184 d->surface = (void*)eglSurface;
185 return GL_TRUE;
186
187}
188BOOL fwDisplayChange(){
189 return GL_FALSE;
190}
191void fwCloseContext(){
192}
193void fv_change_GLcontext(freewrl_params_t* d){
194 return; //stub for ANLGEPROJECT, EGL/GLES2, mobile which don't change context but need to link
195}
196
197#else //ANGLEPROJECT
198//desktop GL and wgl functions
199#include <display.h>
200#include <main/headers.h>
201#include <shlwapi.h>
202
203#include <internal.h>
204
205#include <float.h>
206#include "common.h"
207
208
209void fv_swapbuffers(freewrl_params_t * d)
210{
211 //HDC ghDC;
212 //ghDC = wglGetCurrentDC();
213 //SwapBuffers(ghDC);
214 SwapBuffers((HDC)d->display);
215}
216
217BOOL bSetupPixelFormat(HDC hdc)
218{
219 /* http://msdn.microsoft.com/en-us/library/dd318284(VS.85).aspx */
220 PIXELFORMATDESCRIPTOR pfd, *ppfd;
221 int pixelformat;
222
223 ppfd = &pfd;
224
225 memset(ppfd,0,sizeof(PIXELFORMATDESCRIPTOR));
226
227 ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
228 ppfd->nVersion = 1;
229 ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
230 if(gglobal()->display.shutterGlasses ==1)
231 ppfd->dwFlags |= PFD_STEREO;
232 ppfd->iLayerType = PFD_MAIN_PLANE;
233 ppfd->iPixelType = PFD_TYPE_RGBA; /* PFD_TYPE_COLORINDEX; */
234 ppfd->cColorBits = 24;
235 ppfd->cAlphaBits = 8;
236 ppfd->cDepthBits = 32;
237 //not using accum now, using color masks ppfd->cAccumBits = 64; /*need accum buffer for shader anaglyph - 8 bits per channel OK*/
238 ppfd->cStencilBits = 8;
239 ppfd->cAuxBuffers = 0;
240 ppfd->cAccumBits = 0;
241
242 /* pixelformat = ChoosePixelFormat(hdc, ppfd); */
243 if ( (pixelformat = ChoosePixelFormat(hdc, ppfd)) == 0 )
244 {
245 MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
246 return FALSE;
247 }
248
249 /* seems to fail stereo gracefully/quietly, allowing you to detect with glGetbooleanv(GL_STEREO,) in shared code
250 */
251 DescribePixelFormat(hdc, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), ppfd);
252 //printf("Depth Bits = %d\n",(int)(ppfd->cDepthBits));
253 //if(gglobal()->display.shutterGlasses > 0)
254 // printf("got stereo? = %d\n",(int)(ppfd->dwFlags & PFD_STEREO));
255 /**/
256 if (SetPixelFormat(hdc, pixelformat, ppfd) == FALSE)
257 {
258 MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
259 return FALSE;
260 }
261
262 return TRUE;
263}
264void fv_change_GLcontext(freewrl_params_t* d){
265 HDC hDC;
266 HGLRC hRC;
267 //HWND hWnd;
268 hDC = (HDC)d->display;
269 hRC = (HGLRC)d->context;
270 wglMakeCurrent(hDC, hRC);
271}
272
273bool fv_create_and_bind_GLcontext(freewrl_params_t* d)
274{
275
276 HDC hDC;
277 HGLRC hRC;
278 HWND hWnd;
279
280 /* create GL context */
281 //fwl_thread_dump();
282 //printf("starting createcontext32b\n");
283 hWnd = (HWND)d->winToEmbedInto;
284 hDC = GetDC(hWnd);
285 //printf("got hdc\n");
286 if (!bSetupPixelFormat(hDC))
287 printf("ouch - bSetupPixelFormat failed\n");
288 hRC = wglCreateContext(hDC);
289 //printf("created context\n");
290 /* bind GL context */
291
292 //fwl_thread_dump();
293 //width = tg->display.screenWidth;
294 //height = tg->display.screenHeight;
295 if (wglMakeCurrent(hDC, hRC)) {
296 //GetClientRect(hWnd, &rect);
297 //gglobal()->display.screenWidth = rect.right; /*used in mainloop render_pre setup_projection*/
298 //gglobal()->display.screenHeight = rect.bottom;
299 d->display = (void*)hDC;
300 d->context = (void*)hRC;
301 d->surface = hWnd;
302 return TRUE;
303 }
304 return FALSE;
305
306}
307BOOL fwDisplayChange(){
308 BOOL ret;
309 HWND hWnd;
310 HGLRC ghRC;
311 HDC ghDC;
312 ttglobal tg = gglobal();
313 hWnd = (HWND)((freewrl_params_t*)tg->display.params)->winToEmbedInto;
314
315 ghDC = GetDC(hWnd);
316 ret = bSetupPixelFormat(ghDC);
317 //printf("WM_DISPLAYCHANGE happening now\n");
318
319 /* ???? do we have to recreate an OpenGL context
320 when display mode changed ? */
321 if(ret){
322 ghRC = wglCreateContext(ghDC);
323 wglMakeCurrent(ghDC, ghRC);
324 }
325 return ret;
326}
327
328void fwCloseContext(){
329 HWND hWnd;
330 HGLRC ghRC;
331 HDC ghDC;
332 ttglobal tg = gglobal();
333 hWnd = (HWND)((freewrl_params_t *)tg->display.params)->winToEmbedInto;
334 ghRC = wglGetCurrentContext();
335 if (ghRC)
336 wglDeleteContext(ghRC);
337 ghDC = GetDC(hWnd);
338 if (ghDC)
339 ReleaseDC(hWnd, ghDC);
340}
341#endif //ANGLEPROJECT
342
343
344
345//HWND ghWnd; /* on a hunch I made these static so they are once per program */
346//HDC ghDC;
347//HGLRC ghRC;
348//
349//HWND fw_window32_hwnd()
350//{
351// return ghWnd;
352//}
353HWND fw_window32_hwnd(){
354 ttglobal tg = (ttglobal)gglobal();
355 return (HWND)((freewrl_params_t *)tg->display.params)->winToEmbedInto;
356}
357
358void fwl_do_keyPress(const char kp, int type);
359
360/* from Blender GHOST_SystemWin32.cpp: Key code values not found in winuser.h */
361#ifndef VK_MINUS
362#define VK_MINUS 0xBD
363#endif // VK_MINUS
364#ifndef VK_SEMICOLON
365#define VK_SEMICOLON 0xBA
366#endif // VK_SEMICOLON
367#ifndef VK_PERIOD
368#define VK_PERIOD 0xBE
369#endif // VK_PERIOD
370#ifndef VK_COMMA
371#define VK_COMMA 0xBC
372#endif // VK_COMMA
373#ifndef VK_QUOTE
374#define VK_QUOTE 0xDE
375#endif // VK_QUOTE
376#ifndef VK_BACK_QUOTE
377#define VK_BACK_QUOTE 0xC0
378#endif // VK_BACK_QUOTE
379#ifndef VK_SLASH
380#define VK_SLASH 0xBF
381#endif // VK_SLASH
382#ifndef VK_BACK_SLASH
383#define VK_BACK_SLASH 0xDC
384#endif // VK_BACK_SLASH
385#ifndef VK_EQUALS
386#define VK_EQUALS 0xBB
387#endif // VK_EQUALS
388#ifndef VK_OPEN_BRACKET
389#define VK_OPEN_BRACKET 0xDB
390#endif // VK_OPEN_BRACKET
391#ifndef VK_CLOSE_BRACKET
392#define VK_CLOSE_BRACKET 0xDD
393#endif // VK_CLOSE_BRACKET
394#ifndef VK_GR_LESS
395#define VK_GR_LESS 0xE2
396#endif // VK_GR_LESS
397
398
399
400static int oldx = 0, oldy = 0;
401//extern int shutterGlasses;
402
403int mouseX, mouseY;
404
405static short gcWheelDelta = 0;
406
407
408
409static bool m_fullscreen = false;
410static bool dualmonitor = false;
411static RECT smallrect;
412void setLastCursor();
413bool EnableFullscreen(int w, int h, int bpp)
414{
415#if defined(ENABLEFULLSCREEN)
416 /* adapted from http://www.gamedev.net/community/forums/topic.asp?topic_id=418397 */
417 /* normally I pass in bpp=32. If you set debugit=true below and do a run, you'll see the modes available */
418 /* CDS_FULLSCREEN
419 for dual-monitor the author warns to disable nVidia's nView (they hook
420 into changedisplaysettings but not changedisplaysettingsex)
421 one idea: don't do the ex on single monitors - set dualmonitor=false above.
422 Find out the name of the device this window - is on (this is for multi-monitor setups)
423 */
424 MONITORINFOEX monInfo;
425 LONG ret;
426 bool ok;
427 DWORD style, exstyle;
428 bool debugit;
429 DEVMODE dmode;
430 bool foundMode;
431 int i;
432 HWND ghWnd;
433 HMONITOR hMonitor;
434 //wglGetCurrent
435 hMonitor = MonitorFromWindow(ghWnd, MONITOR_DEFAULTTOPRIMARY);
436 memset(&monInfo, 0, sizeof(MONITORINFOEX));
437 monInfo.cbSize = sizeof(MONITORINFOEX);
438 GetMonitorInfo(hMonitor, (LPMONITORINFO)&monInfo);
439
440 /* Find the requested device mode */
441 foundMode = false;
442 memset(&dmode, 0, sizeof(DEVMODE));
443 dmode.dmSize = sizeof(DEVMODE);
444 debugit = false;
445 for(i=0 ; EnumDisplaySettings(monInfo.szDevice, i, &dmode) && !foundMode ; ++i)
446 {
447 foundMode = (dmode.dmPelsWidth==(DWORD)w) &&
448 (dmode.dmPelsHeight==(DWORD)h) &&
449 (dmode.dmBitsPerPel==(DWORD)bpp);
450 if(debugit)
451 ConsoleMessage("found w=%d h=%d bpp=%d\n",(int)dmode.dmPelsWidth, (int)dmode.dmPelsHeight, (int)dmode.dmBitsPerPel);
452 }
453 if(!foundMode || debugit )
454 {
455 ConsoleMessage("error: suitable display mode for w=%d h=%d bpp=%d not found\n",w,h,bpp);
456 GetWindowRect(ghWnd, &smallrect);
457 ConsoleMessage("window rect l=%d t=%d r=%d b=%d\n",smallrect.top,smallrect.left,smallrect.right,smallrect.bottom);
458 return false;
459 }
460 dmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
461
462 /* If we're switching from a windowed mode to this fullscreen
463 mode, save some information about the window so that it can
464 be restored when switching back to windowed mode
465 */
466 style=0, exstyle=0;
467 if(!m_fullscreen)
468 {
469 /* Save the current window position/size */
470 GetWindowRect(ghWnd, &smallrect);
471
472 /* Save the window style and set it for fullscreen mode */
473 style = GetWindowLongPtr(ghWnd, GWL_STYLE);
474 exstyle = GetWindowLongPtr(ghWnd, GWL_EXSTYLE);
475 SetWindowLongPtr(ghWnd, GWL_STYLE, style & (~WS_OVERLAPPEDWINDOW));
476 SetWindowLongPtr(ghWnd, GWL_EXSTYLE, exstyle | WS_EX_APPWINDOW | WS_EX_TOPMOST);
477 }
478
479 // Attempt to change the resolution
480 if(dualmonitor)
481 {
482 ret = ChangeDisplaySettingsEx(monInfo.szDevice, &dmode, NULL, CDS_FULLSCREEN, NULL);
483 }else{
484 ret = ChangeDisplaySettings(&dmode, CDS_FULLSCREEN);
485 }
486 //LONG ret = ChangeDisplaySettings(&dmode, CDS_FULLSCREEN);
487 ok = (ret == DISP_CHANGE_SUCCESSFUL);
488 if(ok) m_fullscreen = true;
489
490 /* If all was good resize & reposition the window
491 to match the new resolution on the correct monitor
492 */
493 if(ok)
494 {
495 /* We need to call GetMonitorInfo() again becase
496 // details may have changed with the resolution
497 */
498 GetMonitorInfo(hMonitor, (LPMONITORINFO)&monInfo);
499
500 /* Set the window's size and position so
501 // that it covers the entire screen
502 */
503 SetWindowPos(ghWnd, NULL, monInfo.rcMonitor.left, monInfo.rcMonitor.top, (int)w, (int)h,
504 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREPOSITION | SWP_NOZORDER);
505 }
506
507 /* If the attempt failed and we weren't already
508 // in fullscreen mode, restore the window styles
509 */
510 else if(!m_fullscreen)
511 {
512 SetWindowLongPtr(ghWnd, GWL_STYLE, style);
513 SetWindowLongPtr(ghWnd, GWL_EXSTYLE, exstyle);
514 }
515 return ok;
516#endif
517 return FALSE;
518}
519
520void DisableFullscreen()
521{
522#if defined(ENABLEFULLSCREEN)
523 if(m_fullscreen) {
524
525 /* Find out the name of the device this window
526 is on (this is for multi-monitor setups) */
527 MONITORINFOEX monInfo;
528 DWORD style,exstyle;
529 HMONITOR hMonitor;
530 HWND ghWnd;
531 hMonitor = MonitorFromWindow(ghWnd, MONITOR_DEFAULTTOPRIMARY);
532 memset(&monInfo, 0, sizeof(MONITORINFOEX));
533 monInfo.cbSize = sizeof(MONITORINFOEX);
534 GetMonitorInfo(hMonitor, (LPMONITORINFO)&monInfo);
535
536 /* Restore the display resolution */
537 ChangeDisplaySettingsEx(monInfo.szDevice, NULL, NULL, 0, NULL);
538 /*ChangeDisplaySettings(NULL, 0);*/
539
540 m_fullscreen = false;
541
542 /* Restore the window styles */
543 style = GetWindowLongPtr(ghWnd, GWL_STYLE);
544 exstyle = GetWindowLongPtr(ghWnd, GWL_EXSTYLE);
545 SetWindowLongPtr(ghWnd, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);
546 SetWindowLongPtr(ghWnd, GWL_EXSTYLE, exstyle & (~(WS_EX_APPWINDOW | WS_EX_TOPMOST)));
547
548 /* Restore the window size/position */
549 /*SetPosition(m_windowedX, m_windowedY);*/
550 /* SetSize(m_windowedWidth, m_windowedHeight); */
551 SetWindowPos(ghWnd , /* handle to window */
552 HWND_TOPMOST, /* placement-order handle */
553 smallrect.left, /* horizontal position */
554 smallrect.top, /* vertical position */
555 smallrect.right - smallrect.left, /* width */
556 smallrect.bottom - smallrect.top, /* height */
557 SWP_SHOWWINDOW /* window-positioning options); */
558 );
559 }
560#endif
561}
562
563
564static HCURSOR hSensor, hArrow;
565static HCURSOR cursor;
566void loadCursors()
567{
568 hSensor = LoadCursor(NULL,IDC_HAND); /* prepare sensor_cursor */
569 hArrow = LoadCursor( NULL, IDC_ARROW );
570}
571void updateCursorStyle0(int cstyle)
572{
573 if(!hSensor) loadCursors();
574 switch(cstyle){
575 case SCURSE:
576 SetCursor(hSensor); break;
577 case ACURSE:
578 SetCursor(hArrow); break;
579 case NCURSE:
580 SetCursor(NULL); break;
581 default:
582 SetCursor(hArrow);
583 }
584}
585/* values from WinUser.h */
586#define PHOME_KEY VK_HOME //0x24
587#define PPGDN_KEY VK_NEXT //0x22
588#define PLEFT_KEY VK_LEFT //0x25
589#define PEND_KEY VK_END //0x23
590#define PUP_KEY VK_UP //0x26
591#define PRIGHT_KEY VK_RIGHT //0x27
592#define PPGUP_KEY VK_PRIOR //0x21
593#define PDOWN_KEY VK_DOWN //0x28
594#define PF1_KEY VK_F1 //0x70
595#define PF2_KEY VK_F2 //0x71
596#define PF3_KEY VK_F3 //0x72
597#define PF4_KEY VK_F4 //0x73
598#define PF5_KEY VK_F5 //0x74
599#define PF6_KEY VK_F6 //0x75
600#define PF7_KEY VK_F7 //0x76
601#define PF8_KEY VK_F8 //0x77
602#define PF9_KEY VK_F9 //0x78
603#define PF10_KEY VK_F10 //0x79
604#define PF11_KEY VK_F11 //0x7a
605#define PF12_KEY VK_F12 //0x7b
606#define PALT_KEY VK_MENU //0x12
607#define PCTL_KEY VK_CONTROL //0x11
608#define PSFT_KEY VK_SHIFT //0x10
609#define PDEL_KEY VK_DELETE //0x2E //2E is DELETE
610#define PRTN_KEY VK_RETURN //0x0D //13
611#define PNUM0 VK_NUMPAD0
612#define PNUM1 VK_NUMPAD1
613#define PNUM2 VK_NUMPAD2
614#define PNUM3 VK_NUMPAD3
615#define PNUM4 VK_NUMPAD4
616#define PNUM5 VK_NUMPAD5
617#define PNUM6 VK_NUMPAD6
618#define PNUM7 VK_NUMPAD7
619#define PNUM8 VK_NUMPAD8
620#define PNUM9 VK_NUMPAD9
621#define PNUMDEC VK_DECIMAL
622
623/* from http://www.web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/index.html
624section 21.4.1
625Key Value
626Home 13
627End 14
628PGUP 15
629PGDN 16
630UP 17
631DOWN 18
632LEFT 19
633RIGHT 20
634F1-F12 1 to 12
635ALT,CTRL,SHIFT true/false
636*/
637//#define F1_KEY 1
638//#define F2_KEY 2
639//#define F3_KEY 3
640//#define F4_KEY 4
641//#define F5_KEY 5
642//#define F6_KEY 6
643//#define F7_KEY 7
644//#define F8_KEY 8
645//#define F9_KEY 9
646//#define F10_KEY 10
647//#define F11_KEY 11
648//#define F12_KEY 12
649//#define HOME_KEY 13
650//#define END_KEY 14
651//#define PGUP_KEY 15
652//#define PGDN_KEY 16
653//#define UP_KEY 17
654//#define DOWN_KEY 18
655//#define LEFT_KEY 19
656//#define RIGHT_KEY 20
657//#define ALT_KEY 30 /* not available on OSX */
658//#define CTL_KEY 31 /* not available on OSX */
659//#define SFT_KEY 32 /* not available on OSX */
660//#define DEL_KEY 0XFFFF /* problem: I'm insterting this back into the translated char stream so 0xffff too high to clash with a latin? */
661//#define RTN_KEY 13 //what about 10 newline?
662
663#define KEYPRESS 1
664#define KEYDOWN 2
665#define KEYUP 3
666
667int platform2web3dActionKeyWIN32(int platformKey)
668{
669 int key;
670
671 key = 0; //platformKey;
672 if(platformKey >= PF1_KEY && platformKey <= PF12_KEY)
673 key = platformKey - PF1_KEY + F1_KEY;
674 else
675 switch(platformKey)
676 {
677 case PHOME_KEY:
678 key = HOME_KEY; break;
679 case PEND_KEY:
680 key = END_KEY; break;
681 case PPGDN_KEY:
682 key = PGDN_KEY; break;
683 case PPGUP_KEY:
684 key = PGUP_KEY; break;
685 case PUP_KEY:
686 key = UP_KEY; break;
687 case PDOWN_KEY:
688 key = DOWN_KEY; break;
689 case PLEFT_KEY:
690 key = LEFT_KEY; break;
691 case PRIGHT_KEY:
692 key = RIGHT_KEY; break;
693 case PDEL_KEY:
694 key = DEL_KEY; break;
695 case PALT_KEY:
696 key = ALT_KEY; break;
697 case PCTL_KEY:
698 key = CTL_KEY; break;
699 case PSFT_KEY:
700 key = SFT_KEY; break;
701 case PNUM0:
702 key = NUM0; break;
703 case PNUM1:
704 key = NUM1; break;
705 case PNUM2:
706 key = NUM2; break;
707 case PNUM3:
708 key = NUM3; break;
709 case PNUM4:
710 key = NUM4; break;
711 case PNUM5:
712 key = NUM5; break;
713 case PNUM6:
714 key = NUM6; break;
715 case PNUM7:
716 key = NUM7; break;
717 case PNUM8:
718 key = NUM8; break;
719 case PNUM9:
720 key = NUM9; break;
721 case PNUMDEC:
722 key = NUMDEC; break;
723 default:
724 key = 0;
725 }
726 return key;
727}
728/* Print n as a binary number - scraped from www */
729void printbitssimple(int n) {
730 unsigned int i,j;
731 j=0;
732 i = 1<<(sizeof(n) * 8 - 1);
733 while (i > 0) {
734 if (n & i)
735 printf("1");
736 else
737 printf("0");
738 i >>= 1;
739 j++;
740 if(j%8 == 0) printf(" ");
741 }
742}
743
744static HWND last_key_hWnd = NULL;
745static int clipboard_functions_registered = 0;
746static void win32_clipboard_copy(char *str){
747 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016(v=vs.85).aspx
748
749 int len;
750 LPTSTR lptstrCopy;
751 HGLOBAL hglbCopy;
752 if (!OpenClipboard(last_key_hWnd))
753 return;
754 EmptyClipboard();
755
756 // If text is selected, copy it using the CF_TEXT format.
757 len = strlen(str);
758
759 if (!len) // zero length
760 {
761 CloseClipboard(); // selection
762 return;
763 }
764
765
766 hglbCopy = GlobalAlloc(GMEM_MOVEABLE,
767 (len + 1) * sizeof(TCHAR));
768 if (hglbCopy == NULL)
769 {
770 CloseClipboard();
771 return;
772 }
773
774 // Lock the handle and copy the text to the buffer.
775
776 lptstrCopy = GlobalLock(hglbCopy);
777 memcpy(lptstrCopy, str,
778 len * sizeof(TCHAR));
779 lptstrCopy[len] = (TCHAR) 0; // null character
780 GlobalUnlock(hglbCopy);
781
782 // Place the handle on the clipboard.
783
784 SetClipboardData(CF_TEXT, hglbCopy);
785 CloseClipboard();
786
787
788
789}
790static void win32_clipboard_paste() {
791 //CTRL-V == 22 == clipboard paste in win32
792 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016(v=vs.85).aspx
793 HGLOBAL hglb;
794 LPTSTR lptstr;
795 //paste
796 if (IsClipboardFormatAvailable(CF_TEXT)) {
797 if (OpenClipboard(last_key_hWnd)) {
798 hglb = GetClipboardData(CF_TEXT);
799 if (hglb != NULL)
800 {
801 lptstr = GlobalLock(hglb);
802 if (lptstr != NULL)
803 {
804 int m, len = strlen(lptstr);
805 for(m=0;m<len;m++)
806 if(lptstr[m] != 22) //prevent infinite recusion
807 fwl_do_rawKeyPress(lptstr[m],KEYPRESS);
808 GlobalUnlock(hglb);
809 }
810 }
811 CloseClipboard();
812 }
813 }
814}
815//touch >>
816// This function is used to return an index given an ID
817int GetContactIndex(int dwID, int *idLookup, int maxpoints){
818 //starting at index 1 (0 reserved for mouse)
819 for (int i=1; i < maxpoints; i++){
820 if (idLookup[i] == -1){
821 idLookup[i] = dwID;
822 return i;
823 }else{
824 if (idLookup[i] == dwID){
825 return i;
826 }
827 }
828 }
829 // Out of contacts
830 return -1;
831}
832//<< touch
833//gesture >>
834
835LRESULT DecodeGesture(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
836 // Create a structure to populate and retrieve the extra message info.
837 GESTUREINFO gi;
838
839 ZeroMemory(&gi, sizeof(GESTUREINFO));
840
841 gi.cbSize = sizeof(GESTUREINFO);
842
843 BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);
844 BOOL bHandled = FALSE;
845
846 if (bResult){
847 // now interpret the gesture
848 switch (gi.dwID){
849 case GID_ZOOM:
850 // Code for zooming goes here
851 bHandled = TRUE;
852 break;
853 case GID_PAN:
854 // Code for panning goes here
855 bHandled = TRUE;
856 break;
857 case GID_ROTATE:
858 // Code for rotation goes here
859 bHandled = TRUE;
860 break;
861 case GID_TWOFINGERTAP:
862 // Code for two-finger tap goes here
863 bHandled = TRUE;
864 break;
865 case GID_PRESSANDTAP:
866 // Code for roll over goes here
867 bHandled = TRUE;
868 break;
869 default:
870 // A gesture was not recognized
871 break;
872 }
873 }else{
874 DWORD dwErr = GetLastError();
875 if (dwErr > 0){
876 //MessageBoxW(hWnd, L"Error!", L"Could not retrieve a GESTUREINFO structure.", MB_OK);
877 }
878 }
879 //if (bHandled){
880 // return 0;
881 //}else{
882 // return DefWindowProc(hWnd, message, wParam, lParam);
883 //}
884 return 0;
885 }
886void onGestureNotify(HWND hWnd){
887 GESTURECONFIG config = { 0 };
888 config.dwWant =GC_ALLGESTURES | GC_ROTATE; // GC_ROTATE;
889 config.dwID = GID_ROTATE;
890 config.dwBlock = 0;
891
892 BOOL result = SetGestureConfig(
893 hWnd,
894 0,
895 1,
896 &config,
897 sizeof(GESTURECONFIG)
898 );
899
900}
901//<< gesture
902
903void fwl_set_clipboard_copy( void (*fn)(char *));
904void fwl_set_clipboard_paste( void (*fn));
905
906void statusbar_set_window_size(int width, int height);
907int statusbar_handle_mouse(int mev, int butnum, int mouseX, int mouseY);
908int fwl_hwnd_to_windex(void *hWnd);
909void fwl_setScreenDim1(int wi, int he, int itargetwindow);
910LRESULT CALLBACK PopupWndProc(
911 HWND hWnd,
912 UINT msg,
913 WPARAM wParam,
914 LPARAM lParam )
915{
916 PAINTSTRUCT ps;
917 LONG lRet = 1;
918 RECT rect;
919 //touch>>
920 UINT cInputs;
921 PTOUCHINPUT pInputs;
922 POINT ptInput;
923 //<<touch
924 int keyraw;
925 int mev;
926 int butnum;
927 int updown;
928 int actionKey;
929static int altState = 0;
930 int lkeydata;
931static int shiftState = 0;
932 HDC ghDC;
933 int windex;
934
935 mev = 0;
936 butnum = 0;
937 windex = fwl_hwnd_to_windex(hWnd); //sets it if doesn't exist
938 last_key_hWnd = hWnd; //for clpboard funcs above
939 if(!clipboard_functions_registered){
940 fwl_set_clipboard_paste(win32_clipboard_paste);
941 fwl_set_clipboard_copy(win32_clipboard_copy);
942 clipboard_functions_registered = 1;
943 }
944 //ghWnd = hWnd;
945 switch( msg ) {
946 case WM_CREATE:
947 //printf("wm_create\n");
948 //fv_create_GLcontext();
949 //fv_bind_GLcontext();
950 //((*LPCREATESTRUCT)lParam)->lpCreateParams;
951// fv_create_and_bind_GLcontext(hWnd);
952 break;
953
954 case WM_SIZE:
955 GetClientRect(hWnd, &rect);
956 //gglobal()->display.screenWidth = rect.right; /*used in mainloop render_pre setup_projection*/
957 //gglobal()->display.screenHeight = rect.bottom;
958 //resize_GL(rect.right, rect.bottom);
959//#ifdef STATUSBAR_HUD
960// statusbar_set_window_size(rect.right, rect.bottom);
961//#else
962// fwl_setScreenDim(rect.right, rect.bottom);
963//#endif
964 fwl_setScreenDim1(rect.right, rect.bottom, windex);
965 break;
966
967 case WM_DISPLAYCHANGE:
968 /*triggred when the display mode is changed ie changedisplaysettings window <> fullscreen
969 or how about if you drag a window onto a second monitor?
970 */
971 if(!fwDisplayChange())
972 PostQuitMessage(0);
973 //GetClientRect(hWnd, &rect);
974
975 break;
976
977 case WM_CLOSE:
978 //fwCloseContext();
979 //DestroyWindow (hWnd);
980 fwl_doQuit(__FILE__,__LINE__);
981 break;
982
983
984/**************************************************************\
985 * WM_PAINT: *
986\**************************************************************/
987
988 case WM_PAINT:
989
990 ghDC = BeginPaint( hWnd, &ps );
991 /*TextOut( ghDC, 10, 10, "Hello, Windows!", 13 ); */
992 EndPaint( hWnd, &ps );
993 break;
994
995/**************************************************************\
996 * WM_COMMAND: *
997\**************************************************************/
998
999 case WM_COMMAND:
1000 /*
1001 switch( wParam ) {
1002 case IDM_ABOUT:
1003 DialogBox( ghInstance, "AboutDlg", hWnd, (DLGPROC)
1004 AboutDlgProc );
1005 break;
1006 }
1007 */
1008 break;
1009
1010/**************************************************************\
1011 * WM_DESTROY: PostQuitMessage() is called *
1012\**************************************************************/
1013
1014 case WM_DESTROY:
1015 fwCloseContext();
1016
1017 PostQuitMessage (0);
1018 break;
1019
1020 case WM_KEYDOWN:
1021 case WM_KEYUP:
1022 /* raw keystrokes with UP and DOWN separate,
1023 used for fly navigation and KeySensor node */
1024 lkeydata = lParam;
1025 updown = KEYDOWN; //KeyPress;
1026 if(msg==WM_KEYUP) updown = KEYUP; //KeyRelease;
1027 if(updown==KeyPress)
1028 if(lkeydata & 1 << 30)
1029 break; //ignor - its an auto-repeat
1030 //altDown = lkeydata & 1 << 29; //alt key is pressed while the current key is pressed
1031 /*
1032 printf("KF_ALTDOWN");
1033 printbitssimple((int)KF_ALTDOWN);
1034 printf("\n");
1035 printf("lkeydata ");
1036 printbitssimple(lkeydata);
1037 printf(" %d %o %x \n",lkeydata,lkeydata,lkeydata);
1038 */
1039 /*
1040 printbitssimple(wParam); printf("\n");
1041 //altDown = lkeydata & KF_ALTDOWN;
1042 //#define KF_ALTDOWN 0x2000
1043 if(altState && !altDown) fwl_do_rawKeyPress(ALT_KEY,KEYUP + 10);
1044 if(!altState && altDown) fwl_do_rawKeyPress(ALT_KEY,KEYDOWN + 10);
1045 altState = altDown;
1046 */
1047 //kp = (char)wParam;
1048 keyraw = (int) wParam;
1049 if(keyraw == VK_OEM_1) keyraw = (int)';'; //US
1050 if(updown==KEYUP && keyraw == VK_DELETE)
1051 fwl_do_rawKeyPress(DEL_KEY,KEYPRESS);
1052 actionKey = platform2web3dActionKeyWIN32(keyraw);
1053 if(actionKey)
1054 fwl_do_rawKeyPress(actionKey,updown+10);
1055 else
1056 fwl_do_rawKeyPress(keyraw,updown);
1057
1058 //if(kp >= 'A' && kp <= 'Z' && shiftState ==0 ) kp = (char)tolower(wParam); //the F1 - F12 are small case ie y=121=F1
1059 //printf(" wParam %d %x\n",wParam, wParam);
1060 //x3d specs http://www.web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/index.html
1061 //section 21.4.1 has a table of KeySensor ActionKey values which we must map to at some point
1062 // http://msdn.microsoft.com/en-us/library/ms646268(VS.85).aspx windows keyboard messages
1063 //switch (wParam)
1064 //{
1065 // //case VK_LEFT: -- translation to web3d moved to platform2web3dActionKey(int platformKey)
1066 // // kp = 'j';//19;
1067 // // break;
1068 // //case VK_RIGHT:
1069 // // kp = 'l';//20;
1070 // // break;
1071 // //case VK_UP:
1072 // // kp = 'p';//17;
1073 // // break;
1074 // //case VK_DOWN:
1075 // // kp = ';';//18;
1076 // // break;
1077 // //case -70:
1078 // // kp = ';';
1079 // // break;
1080 // //case VK_SHIFT: //0x10
1081 // // if(updown==KeyPress) shiftState = 1;
1082 // // if(updown==KeyRelease) shiftState = 0;
1083 // //case VK_CONTROL: //0x11
1084 // //case VK_MENU: //ALT 0x12 - doesn't work like this: it alters the next key pressed
1085 // // break;
1086 // /*
1087 // case VK_OPEN_BRACKET:
1088 // printf("[");
1089 // // width, height, bpp of monitor
1090 // EnableFullscreen(1680,1050,32);
1091 // break;
1092 // case VK_CLOSE_BRACKET:
1093 // printf("]");
1094 // DisableFullscreen();
1095 // break;
1096 // */
1097 // case VK_OEM_1:
1098 // kp = ';'; //could be : or ; but tolower won't lowercase it, but returns same character if it can't
1099 // break;
1100 // default:
1101 // ///* we aren't using WCHAR so we will translate things like shift-/ to ? */
1102 // //{
1103 // // /* http://msdn.microsoft.com/en-us/library/ms646267(VS.85).aspx shows where to get the scan code */
1104 // // int k2; int i2; unsigned short k3;
1105 // // UINT scancode;
1106 // // //scancode = ((lParam << 8)>>8)>>16;
1107 // // scancode = lParam >>16;
1108 // // k2 = MapVirtualKeyEx(scancode,MAPVK_VSC_TO_VK,GetKeyboardLayout(0));
1109 // // k2 = MapVirtualKeyEx(k2,MAPVK_VK_TO_CHAR,NULL);
1110 // // if(k2) kp = k2;
1111 // // k3 = 0;
1112 // // i2 = ToAsciiEx(wParam,scancode,NULL,&k3,0,GetKeyboardLayout(0));
1113 // // if(i2>0)
1114 // // kp = k3;
1115 // //}
1116 // break;
1117 //}
1118 //fwl_do_rawKeyPressWIN32(keyraw, updown);
1119 break;
1120
1121 case WM_CHAR:
1122 /* fully translated char, with any SHIFT applied, and not a modifier key itself.
1123 used for keyboard commands to freewrl -except fly navigation-
1124 and web3d StringSensor node.
1125 */
1126 //kp = (char)wParam;
1127 //fwl_do_keyPress(kp,KeyChar);
1128 keyraw = (int) wParam;
1129 fwl_do_rawKeyPress(keyraw,KEYPRESS);
1130 break;
1131 /* Mouse events, processed */
1132 case WM_LBUTTONDOWN:
1133 butnum = 1;
1134 mev = ButtonPress;
1135 break;
1136 case WM_MBUTTONDOWN:
1137 butnum = 2;
1138 mev = ButtonPress;
1139 break;
1140 case WM_RBUTTONDOWN:
1141 butnum = 3;
1142 mev = ButtonPress;
1143 break;
1144 case WM_LBUTTONUP:
1145 butnum = 1;
1146 mev = ButtonRelease;
1147 break;
1148 case WM_MBUTTONUP:
1149 butnum = 2;
1150 mev = ButtonRelease;
1151 break;
1152 case WM_RBUTTONUP:
1153 butnum = 3;
1154 mev = ButtonRelease;
1155 break;
1156 case WM_MOUSEMOVE:
1157 {
1158 POINTS pz;
1159 pz= MAKEPOINTS(lParam);
1160 mouseX = pz.x;
1161 mouseY = pz.y;
1162 }
1163 mev = MotionNotify;
1164 break;
1165#ifndef WM_MOUSEWHEEL
1166#define WM_MOUSEWHEEL 0x020A
1167#endif
1168 case WM_MOUSEWHEEL:
1169 /* The WM_MOUSEWHEEL message is sent to the focus window
1170 * when the mouse wheel is rotated. The DefWindowProc
1171 * function propagates the message to the window's parent.
1172 * There should be no internal forwarding of the message,
1173 * since DefWindowProc propagates it up the parent chain
1174 * until it finds a window that processes it.
1175 * https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mousewheel
1176 */
1177 if(1) { //if(!(wParam & (MK_SHIFT | MK_CONTROL))) {
1178 int fwKeys, zDelta;
1179 fwKeys = GET_KEYSTATE_WPARAM(wParam);
1180 //we might not want wheel and MMB at the same time:
1181 // user might mean just MMB but accidently wheel it too
1182 //if(fwKeys & MK_MBUTTON) break;
1183 zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
1184 /* gcWheelDelta -= (short) HIWORD(wParam); windows snippet */
1185 //gcWheelDelta = (short) HIWORD(wParam);
1186 mev = MotionNotify;
1187 //linux convention
1188 butnum = 0;
1189 if( zDelta < 0 ) butnum = 4; //scroll wheel up (in linux)
1190 else if(zDelta > 0) butnum = 5; //scroll wheel down
1191 //printf("wheel %d \n",(int)zDelta);
1192 if(0){
1193 int xPos, yPos;
1194 fwKeys = GET_KEYSTATE_WPARAM(wParam);
1195 zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
1196 xPos = GET_X_LPARAM(lParam);
1197 yPos = GET_Y_LPARAM(lParam);
1198 printf("wheel delta %d CTRL=%c SHFT=%c xyPos %d %d BUT %c%c%c X%c%c\n",zDelta,
1199 fwKeys & MK_CONTROL ? 'C' : '_',
1200 fwKeys & MK_SHIFT ? 'S' : '_',
1201 //fwKeys & MK_ALT ? 'A' : '_', //doesnt work, and docs don't show it
1202 xPos, yPos,
1203 fwKeys & MK_LBUTTON ? 'L' : '_',
1204 fwKeys & MK_MBUTTON ? 'M' : '_',
1205 fwKeys & MK_RBUTTON ? 'R' : '_',
1206 fwKeys & MK_XBUTTON1 ? 'X' : '_',
1207 fwKeys & MK_XBUTTON2 ? 'X' : '_'
1208 );
1209 }
1210 }
1211 break;
1212
1213 //WM_TOUCH needs capable device and minimum windows 7 and one way to tell: is it x64 (we're in windows code) - that's vista and beyond. close enough,
1214 // although there are x86 versions of windows 8.1 etc.
1215//#if defined(_M_AMD64) || defined(_M_X64)
1216 // touch >>
1217 //https://docs.microsoft.com/en-us/windows/win32/wintouch/detecting-and-tracking-multiple-touch-points
1218 case WM_TOUCH:
1219 {
1220 #define MAXPOINTS 20
1221 static int idLookup[MAXPOINTS];
1222 static int initialized = 0;
1223 printf("got a WM_TOUCH index x y action\n");
1224 static TOUCHINPUT pInputs[MAXPOINTS]; //if you open multiple windows in the same (future?) freewrl instance, then this can't be static
1225 if(!initialized){
1226 initialized = 1;
1227 for(int i=0;i<MAXPOINTS;i++) idLookup[i] = -1;
1228 }
1229 cInputs = LOWORD(wParam);
1230 cInputs = min(20,cInputs);
1231 //pInputs = new TOUCHINPUT[cInputs];
1232 if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))){
1233 for (int i=0; i < (int)(cInputs); i++){
1234 int index, cursorStyle, touchAction;
1235 TOUCHINPUT ti = pInputs[i];
1236 index = GetContactIndex(ti.dwID,idLookup,MAXPOINTS);
1237 if (ti.dwID != 0 && index < MAXPOINTS){
1238 // Do something with your touch input handle
1239 ptInput.x = TOUCH_COORD_TO_PIXEL(ti.x);
1240 ptInput.y = TOUCH_COORD_TO_PIXEL(ti.y);
1241 ScreenToClient(hWnd, &ptInput);
1242 touchAction = MotionNotify;
1243 if (ti.dwFlags & TOUCHEVENTF_UP) touchAction = ButtonRecycle; //ButtonRelease;
1244 if (ti.dwFlags & TOUCHEVENTF_DOWN) touchAction = ButtonPress;
1245 if (ti.dwFlags & TOUCHEVENTF_UP){
1246 printf("touch up ID %d ",index);
1247 //points[index][0] = -1;
1248 //points[index][1] = -1;
1249 }else{
1250 printf("x %d y %d ID %d ",ptInput.x,ptInput.y,index);
1251 //points[index][0] = ptInput.x;
1252 //points[index][1] = ptInput.y;
1253 }
1254 printf("[%d %d %d %d]\n",index,ptInput.x,ptInput.y,touchAction);
1255 cursorStyle = fwl_handle_touch(touchAction, index, ptInput.x, ptInput.y, 0);
1256 }
1257 }
1258 }
1259 // If you handled the message and don't want anything else done with it, you can close it
1260 CloseTouchInputHandle((HTOUCHINPUT)lParam);
1261 //delete [] pInputs;
1262 break;
1263 }
1264 //<< touch
1265//#endif
1266 case WM_GESTURENOTIFY:
1267 onGestureNotify(hWnd);
1268 break;
1269
1270 case WM_GESTURE:
1271 {
1272 // https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-gestures
1273 // Insert handler code here to interpret the gesture.
1274 int iretg;
1275 iretg = DecodeGesture(hWnd, msg, wParam, lParam);
1276 printf("got a WM_GESTURE\n");
1277 break;
1278 }
1279 case WM_HSCROLL:
1280 case WM_VSCROLL:
1281 printf("got a WM_SCROLL\n");
1282 break;
1283
1284
1285 /* falls through to default ? */
1286
1287/**************************************************************\
1288 * Let the default window proc handle all other messages *
1289\**************************************************************/
1290
1291 default:
1292 return( DefWindowProc( hWnd, msg, wParam, lParam ));
1293 }
1294 if(mev)
1295 {
1296 /*void fwl_handle_aqua(const int mev, const unsigned int button, int x, int y);*/
1297 /* butnum=1 left butnum=3 right (butnum=2 middle, not used by freewrl) */
1298 int cursorStyle;
1299 cursorStyle = fwl_handle_mouse(mev, butnum, mouseX, mouseY, windex); /* ,gcWheelDelta); */
1300 updateCursorStyle0(cursorStyle);
1301 }
1302 return 0;
1303}
1304
1305int doEventsWin32A()
1306{
1307 static int eventcount = 0;
1308 MSG msg;
1309 do
1310 {
1311 while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
1312 {
1313 if (GetMessage(&msg, NULL, 0, 0) )
1314 {
1315 TranslateMessage(&msg);
1316 DispatchMessage(&msg);
1317 } else {
1318 return TRUE;
1319 }
1320
1321 }
1322 eventcount++;
1323 }while(0); /*eventcount < 1000);*/
1324 eventcount = 0;
1325 return FALSE;
1326}
1327void fwMessageLoop(){
1328 doEventsWin32A();
1329}
1330
1331void fv_setGeometry_from_cmdline(const char *gstring)
1332{
1333 int w,h,i;
1334 char *tok[2];
1335 freewrl_params_t *params;
1336 char *str = MALLOC(void *, sizeof(gstring)+1);
1337 strcpy(str,gstring);
1338 tok[0] = str;
1339 for(i=0;i<(int)strlen(gstring);i++)
1340 if(str[i] == 'x' || str[i] == 'X')
1341 {
1342 str[i] = '\0';
1343 tok[1] = &str[i+1];
1344 break;
1345 }
1346 sscanf(tok[0],"%d",&w);
1347 sscanf(tok[1],"%d",&h);
1348 params = (freewrl_params_t *)gglobal()->display.params;
1349 params->width = w;
1350 params->height = h;
1351 FREE(str);
1352
1353}
1354/*======== "VIRTUAL FUNCTIONS" ==============*/
1355
1356void setWindowTitle() //char *window_title)
1357{
1358 //XStoreName(Xdpy, Xwin, window_title);
1359 //XSetIconName(Xdpy, Xwin, window_title);
1360 //http://msdn.microsoft.com/en-us/library/ms633546(VS.85).aspx
1361 //SetWindowText(
1362 // __in HWND hWnd,
1363 // __in_opt LPCTSTR lpString);
1364 HWND ghWnd;
1365 //SetWindowText(ghWnd,fwl_getWindowTitle());
1366 ghWnd = (void*)((freewrl_params_t *)(gglobal()->display.params))->winToEmbedInto;
1367 if(ghWnd)
1368 SetWindowText(ghWnd,getWindowTitle()); //window_title);
1369}
1370
1374int fv_open_display()
1375{
1376 /* nothing to do */
1377 return TRUE;
1378}
1379
1380static char *wgetpath = NULL;
1381TCHAR szPath[MAX_PATH];
1382static int wgetpathLoaded = 0;
1383char *getWgetPath()
1384{
1385 if(!wgetpathLoaded)
1386 {
1387 if( !GetModuleFileName( NULL, &szPath[1], MAX_PATH ) )
1388 {
1389 printf("Cannot install service (%d)\n", GetLastError());
1390 return 0;
1391 }
1392 else
1393 {
1394 wgetpath = &szPath[1];
1395 PathRemoveFileSpec(wgetpath);
1396 PathAppend(wgetpath,"wget.exe");
1397 // c:\program files\ breaks up in the space so we "" around the path
1398 strcat(wgetpath,"\"");
1399 wgetpath = szPath;
1400 wgetpath[0] = '"';
1401 }
1402 }
1403 wgetpathLoaded = 1;
1404 return wgetpath;
1405}
1406
1410HWND create_main_window0(freewrl_params_t * d) //int argc, char *argv[])
1411{
1412 HINSTANCE hInstance;
1413 WNDCLASS wc;
1414 static int wc_defined = 0;
1415 DWORD wStyle = 0;
1416 HWND ghWnd;
1417 //RECT rect;
1418 int width, height, xpos, ypos, wnum;
1419 char appname[30];
1420 int haveTOUCH;
1421 int nCmdShow = SW_SHOW;
1422
1423 //printf("starting createWindow32\n");
1424 /* I suspect hInstance should be get() and passed in from the console program not get() in the dll, but .lib maybe ok */
1425 hInstance = (HANDLE)GetModuleHandle(NULL);
1426 //printf("hInstance=%p\n",hInstance);
1427 //gglobal()->display.window_title = "FreeWRL";
1428 //d->window_title = "FreeWRL";
1429
1430/* Blender Ghost
1431 WNDCLASS wc;
1432 wc.style= CS_HREDRAW | CS_VREDRAW;
1433 wc.lpfnWndProc= s_wndProc;
1434 wc.cbClsExtra= 0;
1435 wc.cbWndExtra= 0;
1436 wc.hInstance= ::GetModuleHandle(0);
1437 wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
1438
1439 if (!wc.hIcon) {
1440 ::LoadIcon(NULL, IDI_APPLICATION);
1441 }
1442 wc.hCursor = ::LoadCursor(0, IDC_ARROW);
1443 wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
1444 wc.lpszMenuName = 0;
1445 wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
1446
1447 // Use RegisterClassEx for setting small icon
1448 if (::RegisterClass(&wc) == 0) {
1449 success = GHOST_kFailure;
1450 }
1451*/
1452 //hSensor = LoadCursor(NULL,IDC_HAND); /* prepare sensor_cursor */
1453 //hArrow = LoadCursor( NULL, IDC_ARROW );
1454 //loadCursors();
1455
1456 if(!wc_defined){
1457 wc.lpszClassName = "FreeWrlAppClass";
1458 wc.lpfnWndProc = PopupWndProc; //MainWndProc;
1459 //wc.style = CS_VREDRAW | CS_HREDRAW; /* 0 CS_OWNDC | */
1460 wc.style = CS_OWNDC;
1461 wc.hInstance = hInstance;
1462 wc.hIcon = LoadIcon(wc.hInstance, "APPICON");
1463 if (!wc.hIcon) {
1464 wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
1465 }
1466 wc.hCursor = NULL; //hArrow;
1467 wc.hbrBackground = (HBRUSH)( COLOR_WINDOW+1 );
1468 wc.lpszMenuName = 0; /* "GenericAppMenu"; */
1469 wc.cbClsExtra = 0;
1470 wc.cbWndExtra = 0;
1471
1472 RegisterClass( &wc );
1473 wc_defined = TRUE;
1474 }
1475 //width = gglobal()->display.width + 8; //windows gui eats 4 on each side
1476 //height = gglobal()->display.height + 34; // and 26 for the menu bar
1477 width = d->width;
1478 height = d->height;
1479 xpos = d->xpos > -1 ? d->xpos : CW_USEDEFAULT;
1480 ypos = d->ypos > -1 ? d->ypos : CW_USEDEFAULT;
1481 strcpy(appname, "freeWRL");
1482 if (d->wnum > -1) {
1483 //future comparison testing app may need to differentiate between the multiple windows it launches
1484 //so in -g WxH+xpos+ypos_wnum the wnum would be a small int
1485 sprintf_s(appname, 30, "freeWRL%d", d->wnum);
1486 }
1487 if (!d->fullscreen){
1488 width += 8; //windows gui eats 4 on each side
1489 height += 34; // and 26 for the menu bar
1490 }
1491 wStyle = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION;
1492 wStyle |= WS_SIZEBOX; //makes it resizable
1493 wStyle |= WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
1494 //wStyle |= WS_EX_ACCEPTFILES; //drag & drop target (but needs OLE32.dll etc https://msdn.microsoft.com/en-us/library/windows/desktop/bb776905(v=vs.85).aspx
1495
1496 ghWnd = CreateWindowEx( WS_EX_APPWINDOW, "FreeWrlAppClass", appname, //"freeWRL",
1497 /* ghWnd = CreateWindow( "GenericAppClass", "Generic Application", */
1498 wStyle, //WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
1499 xpos,
1500 ypos,
1501 width,
1502 height,
1503 NULL,
1504 NULL,
1505 hInstance,
1506 (void*)gglobal()); //NULL);
1507 /* make sure window was created */
1508
1509 if (!ghWnd)
1510 return NULL;
1511
1512 //printf("made a window\n");
1513 haveTOUCH = 0;
1514//#if defined(_M_AMD64) || defined(_M_X64)
1515 // register the window for touch instead of gestures
1516 // needs to be windows7+
1517 {
1518 // https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
1519 // test for touch
1520 //int value = GetSystemMetrics(SM_DIGITIZER);
1521 //if (value & NID_READY){ /* stack ready */}
1522 //if (value & NID_MULTI_INPUT){
1523 /* digitizer is multitouch */
1524 //printf("Multitouch device found\n");
1525 //}
1526 //if (value & NID_INTEGRATED_TOUCH){ /* Integrated touch */}
1527 // TOUCHTYPE_MULTITOUCH == 2 TOUCHTYPE_GESTURE == 3
1528 if(d->touchtype == 2){
1529 RegisterTouchWindow(ghWnd, 0);
1530 haveTOUCH = 1;
1531 }
1532 //}
1533 }
1534//#endif
1535 //GetClientRect(ghWnd, &rect);
1536 ShowWindow( ghWnd, SW_SHOW); /* SW_SHOWNORMAL); /*nCmdShow );*/
1537 //printf("showed window\n");
1538 //d->winToEmbedInto = (long int)ghWnd;
1539
1540
1541 UpdateWindow(ghWnd);
1542 if (d->fullscreen){
1543 //stefan borderless, title-less
1544 LONG lExStyle;
1545 LONG lStyle = GetWindowLong(ghWnd, GWL_STYLE);
1546 lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
1547 SetWindowLong(ghWnd, GWL_STYLE, lStyle);
1548
1549 lExStyle = GetWindowLong(ghWnd, GWL_EXSTYLE);
1550 lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
1551 SetWindowLong(ghWnd, GWL_EXSTYLE, lExStyle);
1552
1553 SetWindowPos(ghWnd, HWND_TOP, d->xpos, d->ypos, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE);
1554 }
1555 //printf("updated window - leaving createwindow\n");
1556 //setWindowTitle00();
1557 //ShowCursor(0); //turns off hArrow, hHand cursors
1558 setArrowCursor();
1559 return ghWnd;
1560}
1561
1562int fv_create_main_window2(freewrl_params_t * d, freewrl_params_t *share) //int argc, char *argv[])
1563{
1564 loadCursors();
1565#ifdef _DEBUG
1566 MessageBoxA(d->winToEmbedInto,"You may now attach a debugger.1\n Press OK when you want to proceed.","dllfreeWRL plugin process(1)",MB_OK);
1567#endif
1568 if(!d->frontend_handles_display_thread){
1569 //printf("wintoembedinto 1=%d\n",d->winToEmbedInto);
1570 if( (long)(size_t)d->winToEmbedInto < 1) //INT_ID_UNDEFINED) sometimes 0 or -1
1571 d->winToEmbedInto = (long *)create_main_window0(d); //argc, argv);
1572 //printf("wintoembedinto 2=%d\n",d->winToEmbedInto);
1573 if( d->winToEmbedInto )
1574 {
1575 //HWND hWnd;
1577 //hWnd = (HWND)d->winToEmbedInto;
1578 //fv_create_GLcontext();
1579 //fv_bind_GLcontext();
1580 fv_create_and_bind_GLcontext(d);
1581#ifndef ANGLEPROJECT
1582 //remember, ANGLEPROJECT emulates GLES2 over directX, and lacks some desktop wgl functions like wglShareLists
1583 if(share)
1584 wglShareLists((HGLRC) share->context,(HGLRC) d->context);
1585#endif
1586 return TRUE;
1587 }
1588 return FALSE;
1589 }
1590 return TRUE;
1591}
1592
1593#ifdef HAVE_XINPUT
1594// windows xinput game controller
1595// https://docs.microsoft.com/en-us/windows/win32/xinput/xinput-game-controller-apis-portal
1596#include <xinput.h>
1597void poll_game_controllers(){
1598 DWORD dwResult;
1599 for (DWORD i=0; i< XUSER_MAX_COUNT; i++ )
1600 {
1601 XINPUT_STATE state;
1602 ZeroMemory( &state, sizeof(XINPUT_STATE) );
1603
1604 // Simply get the state of the controller from XInput.
1605 dwResult = XInputGetState( i, &state );
1606
1607 if( dwResult == ERROR_SUCCESS )
1608 {
1609 // Controller is connected
1610 static int once = 0;
1611 if(!once)
1612 printf("game controller connected!\n");
1613 once = 1;
1614
1615 }
1616 else
1617 {
1618 // Controller is not connected
1619 static int once = 0;
1620 if(!once)
1621 printf("no game controller\n");
1622 once = 1;
1623 }
1624 }
1625}
1626#else //HAVE_XINPUT
1627void poll_game_controllers(){}
1628#endif //HAVE_XINPUT
1629
1630
1631char *get_key_val(char *key);
1632#ifdef SSR_SERVER
1633void SSR_reply(void * tg);
1634void dequeue_SSR_request(void * tg);
1635static int run_ssr;
1636static run_ssr = FALSE;
1637
1638#endif
1639void initialize_ssr_server(){
1640#ifdef SSR_SERVER
1641 if(!run_ssr) {
1642 //if this is ssr server running, it does a few quirky things like doing slow looping
1643 char *running_ssr = get_key_val("SSR");
1644 if(running_ssr)
1645 if(!strcmp(running_ssr,"true"))
1646 run_ssr = TRUE;
1647 //printf("in desktop.c run_ssr = %d\n",run_ssr);
1648 }
1649#endif //SSR_SERVER
1650}
1651void poll_ssr_server(){
1652#ifdef SSR_SERVER
1653 if(run_ssr){
1654 SSR_reply(gglobal());
1655 dequeue_SSR_request(gglobal());
1656 }
1657#endif
1658}
1659
1660void platform_initialize_input_devices(){
1661 initialize_ssr_server();
1662
1663}
1664void platform_poll_input_devices(){
1665 //win32 message pump - works here for desktop freewrl and npapi, ActiveX plugins,
1666 // because those all use _DisplayThread here.
1667 // (winGLES2 project which uses EGL 'front end' has its own win32 message pump,
1668 // and doesn't call this _displayThread)
1669
1670 poll_ssr_server();
1671 fwMessageLoop();
1672 poll_game_controllers();
1673
1674}
1675
1676
1677#endif /* _MSC_VER */
Definition Viewer.h:141