1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 
11 #define tdmWindow_c
12 
13 #if defined(DX_NATIVE_WINDOWS)
14 
15 #define FLING_TIMEOUT 3
16 #define FLING_GNOMON_FEECHURE
17 
18 #include <windows.h>
19 #include <sys/types.h>
20 #include <stdio.h>
21 #include <math.h>
22 #include <time.h>
23 
24 #include "hwDeclarations.h"
25 #include "hwWindow.h"
26 #include "hwClientMessage.h"
27 #include "hwMatrix.h"
28 #include "hwMemory.h"
29 
30 #include "hwDebug.h"
31 #include "../../../VisualDX/dxexec/resource.h"
32 
33 #include <GL/gl.h>
34 #include <GL/glu.h>
35 
36 #include "opengl/hwPortOGL.h"
37 
38 #if defined(HAVE_CTYPE_H)
39 #include <ctype.h>
40 #else
41 extern int isdigit (int);
42 #endif
43 
44 extern int GLTEST();
45 
46 typedef struct _OGLWindowThreadParams
47 {
48     tdmChildGlobalP	globals;
49     HANDLE 			busy;
50     HANDLE			windowReady;
51     long   			threadID;
52     char   			*winName;
53 }
54 OGLWindowThreadParams;
55 
56 
57 /*
58  * Internal  Function Declarations
59  */
60 
61 static Error  _tdmResizeImage(WinP win) ;
62 Error  _tdmResizeWindow(WinP win, int w, int h, int *change) ;
63 static void   _tdmClearWindow(WinP win) ;
64 static void   _tdmCleanupChild(tdmChildGlobalP childGlobals) ;
65 int _dxfUIType(char *);
66 
67 static void
StartStroke(OGLWindow * oglw,int x0,int y0,int button)68 StartStroke(OGLWindow *oglw, int x0, int y0, int button)
69 {
70     tdmChildGlobalP globals = (tdmChildGlobalP)oglw->globals;
71     tdmStartStroke (globals->CrntInteractor, x0, y0, button, 0) ;
72 }
73 
74 static void
EndStroke(OGLWindow * oglw,WPARAM wParam,LPARAM lParam)75 EndStroke(OGLWindow *oglw, WPARAM wParam, LPARAM lParam)
76 {
77     tdmChildGlobalP globals = (tdmChildGlobalP)oglw->globals;
78     tdmInteractorReturn local;
79     int x, y;
80 
81     oglw->lastX = x = LOWORD(lParam);
82     oglw->lastY = y = HIWORD(lParam);
83 
84 
85     tdmEndStroke(globals->CrntInteractor, &local);
86 }
87 
88 static void
MousePoint(HWND hWnd,OGLWindow * oglw,WPARAM wParam,LPARAM lParam)89 MousePoint(HWND hWnd, OGLWindow *oglw, WPARAM wParam, LPARAM lParam)
90 {
91     tdmChildGlobalP globals = (tdmChildGlobalP)oglw->globals;
92     int l = wParam & MK_LBUTTON;
93     int m = wParam & MK_MBUTTON;
94     int r = wParam & MK_RBUTTON;
95     int c = wParam & MK_CONTROL;
96     int s = wParam & MK_SHIFT;
97     int x, y;
98 
99     oglw->lastX = x = LOWORD(lParam);
100     oglw->lastY = y = HIWORD(lParam);
101 
102     if (l)
103         tdmStrokePoint(globals->CrntInteractor, x, y, INTERACTOR_BUTTON_DOWN, 0);
104 
105     return;
106 }
107 
108 static void
ButtonUp(HWND hWnd,UINT msg,int which,WPARAM wParam,LPARAM lParam)109 ButtonUp(HWND hWnd, UINT msg, int which, WPARAM wParam, LPARAM lParam)
110 {
111     OGLWindow *oglw = GetOGLWPtr(hWnd);
112     if (oglw) {
113         tdmChildGlobalP globals = (tdmChildGlobalP)oglw->globals;
114         DEFGLOBALDATA(globals);
115         int dxEventMask = EVENT_MASK(globals->CrntInteractor);
116 
117         if (dxEventMask & which) {
118             if (CAN_RENDER) {
119                 ReleaseCapture();
120                 ReleaseMutex(LOCK);
121                 EndStroke(oglw, wParam, lParam);
122             }
123         } else
124             SendMessage(PARENT_WINDOW, msg, wParam, lParam);
125 
126         oglw->buttonState &= ~which;
127     }
128 
129     return;
130 }
131 
132 static void
ButtonDown(HWND hWnd,UINT msg,int which,WPARAM wParam,LPARAM lParam)133 ButtonDown(HWND hWnd, UINT msg, int which, WPARAM wParam, LPARAM lParam)
134 {
135     OGLWindow *oglw = GetOGLWPtr(hWnd);
136     if (oglw) {
137         tdmChildGlobalP globals = (tdmChildGlobalP)oglw->globals;
138         DEFGLOBALDATA(globals);
139         int dxEventMask = EVENT_MASK(globals->CrntInteractor);
140 
141         if (dxEventMask & which) {
142             if (CAN_RENDER) {
143                 SetCapture(hWnd);
144                 if (DXWaitForSignal(1, &LOCK) == WAIT_TIMEOUT)
145                     return;
146 
147                 StartStroke(oglw, LOWORD(lParam), HIWORD(lParam), wParam);
148             } else
149                 which = which;
150         } else
151             SendMessage(PARENT_WINDOW, msg, wParam, lParam);
152 
153         oglw->buttonState |= which;
154 
155     }
156 
157     return;
158 }
159 
160 
161 
162 static LONG WINAPI
ProcessWindowMessages(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)163 ProcessWindowMessages(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
164 {
165     static int buttonDown = 0;
166     static int pp = 0;
167 
168     if (msg == WM_CREATE) {
169         return DefWindowProc(hWnd, msg, wParam, lParam);
170     } else {
171         OGLWindow *oglw = GetOGLWPtr(hWnd);
172         if (oglw) {
173             tdmChildGlobalP globals = (tdmChildGlobalP)oglw->globals;
174             DEFGLOBALDATA(globals);
175             int dxEventMask = EVENT_MASK(globals->CrntInteractor);
176 
177             switch (msg) {
178             case WM_DESTROY:
179                 lParam = wParam;
180                 break;
181 
182             case WM_USER:
183                 wParam = lParam;
184                 break;
185 
186             case WM_KEYDOWN:
187                 if (! (dxEventMask & DXEVENT_KEYPRESS))
188                     SendMessage(PARENT_WINDOW, msg, wParam, lParam);
189                 else if (CAN_RENDER) {
190                     char keyState[256];
191                     char key[2];
192                     int n, i;
193                     GetKeyboardState(keyState);
194                     n = ToAscii(wParam, MapVirtualKey(wParam, 1),
195                                 keyState, &key, 0);
196                     if (n == 1)
197                         for (i = 0; i < (lParam & 0xffff); i++)
198                             tdmKeyStruck(globals->CrntInteractor,
199                                          oglw->lastX, oglw->lastY, key[0], 0);
200                 }
201                 break;
202 
203 
204             case WM_MOUSEMOVE: {
205                     int l, m, r;
206 
207                     l = (oglw->buttonState & DXEVENT_LEFT)   && (wParam & MK_LBUTTON);
208                     m = (oglw->buttonState & DXEVENT_MIDDLE) && (wParam & MK_MBUTTON);
209                     r = (oglw->buttonState & DXEVENT_RIGHT)  && (wParam & MK_RBUTTON);
210 
211                     if ((l && (dxEventMask & DXEVENT_LEFT)) ||
212                             (m && (dxEventMask & DXEVENT_MIDDLE)) ||
213                             (r && (dxEventMask & DXEVENT_RIGHT))) {
214                         if (CAN_RENDER)
215                             MousePoint(hWnd, oglw, wParam, lParam);
216                     } else
217                         SendMessage(PARENT_WINDOW, hWnd, wParam, lParam);
218                 }
219                 break;
220 
221 
222             case WM_SIZE: {
223                     if (oglw && oglw->globals) {
224                         DEFGLOBALDATA(oglw->globals);
225 
226                         if (MATRIX_STACK && OBJECT && CAMERA) {
227                             int flag;
228                             _dxfSetInteractorWindowSize(INTERACTOR_DATA, LOWORD(lParam), HIWORD(lParam));
229                             _tdmResizeWindow(LWIN, LOWORD(lParam), HIWORD(lParam), &flag);
230 
231                             if (flag && !buttonDown) {
232                                 DEFGLOBALDATA(oglw->globals);
233                                 _dxfDraw(oglw->globals, OBJECT, CAMERA, 1);
234                             }
235                         }
236 
237                     }
238                 }
239                 break;
240 
241             case WM_PAINT:
242                 if (! buttonDown) {
243                     DEFGLOBALDATA(oglw->globals);
244                     _dxfDraw(oglw->globals, OBJECT, CAMERA, 1);
245                 }
246                 break;
247 
248             case WM_LBUTTONUP:
249                 ButtonUp(hWnd, msg, DXEVENT_LEFT, wParam, lParam);
250                 buttonDown = 0;
251                 break;
252 
253             case WM_MBUTTONUP:
254                 ButtonUp(hWnd, msg, DXEVENT_MIDDLE, wParam, lParam);
255                 buttonDown = 0;
256                 break;
257 
258             case WM_RBUTTONUP:
259                 ButtonUp(hWnd, msg, DXEVENT_RIGHT, wParam, lParam);
260                 buttonDown = 0;
261                 break;
262 
263             case WM_LBUTTONDOWN:
264                 ButtonDown(hWnd, msg, DXEVENT_LEFT, wParam, lParam);
265                 buttonDown = 1;
266                 break;
267 
268             case WM_MBUTTONDOWN:
269                 ButtonDown(hWnd, msg, DXEVENT_MIDDLE, wParam, lParam);
270                 buttonDown = 1;
271                 break;
272 
273             case WM_RBUTTONDOWN:
274                 ButtonDown(hWnd, msg, DXEVENT_RIGHT, wParam, lParam);
275                 buttonDown = 1;
276                 break;
277             }
278 
279         }
280 
281         return DefWindowProc(hWnd, msg, wParam, lParam);
282     }
283 
284 }
285 
286 void
ProcessMessages(HWND hWnd)287 ProcessMessages(HWND hWnd)
288 {
289     MSG msg;
290     OGLWindow *oglw;
291 
292     while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
293         if (GetMessage(&msg, NULL, 0, 0) != TRUE)
294             ExitThread(0);
295 
296         if (msg.hwnd == hWnd)
297             ProcessWindowMessages(msg.message, hWnd, msg.wParam, msg.lParam);
298         else {
299             TranslateMessage(&msg);
300             DispatchMessage(&msg);
301         }
302     }
303 
304     oglw = GetOGLWPtr(hWnd);
305     if (! oglw)
306         return;
307 
308     if (oglw && oglw->globals && oglw->repaint) {
309         DEFGLOBALDATA(oglw->globals);
310         DEFPORT(PORT_HANDLE);
311         if (WaitForSingleObject(LOCK, 0) == WAIT_OBJECT_0) {
312             _dxfDraw(oglw->globals, OBJECT, CAMERA, 1);
313 
314             ReleaseMutex(LOCK);
315             oglw->repaint = 0;
316         }
317     }
318 }
319 
320 static LONG WINAPI
OGLWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)321 OGLWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
322 {
323     return 	ProcessWindowMessages(hWnd, msg, wParam, lParam);
324 }
325 
326 static char *oglWindowClassName;
327 static char *oglDefaultTitle = "Data Explorer";
328 static HINSTANCE OGLWindowClassRegistered = (HINSTANCE)0;
329 
330 static Error
_registerOGLWindowClass()331 _registerOGLWindowClass()
332 {
333     HINSTANCE hInstance;
334 
335     if (! DXGetWindowsInstance(&hInstance))
336         return ERROR;
337 
338     if (hInstance != OGLWindowClassRegistered) {
339         WNDCLASS wc;
340 
341         wc.style         = CS_HREDRAW | CS_VREDRAW;
342         wc.lpfnWndProc   = (WNDPROC)OGLWndProc;
343         wc.cbClsExtra    = 0;
344         wc.cbWndExtra    = sizeof(OGLWindow *);
345         wc.hInstance     = hInstance;
346         wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_STARTUP));
347         wc.hCursor       = NULL;
348         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
349         wc.lpszMenuName  = NULL;
350 
351 		if(oglWindowClassName)
352 			DXFree(oglWindowClassName);
353         oglWindowClassName = (char *)DXAllocate(strlen("DXOGLWin_") + 10);
354         sprintf(oglWindowClassName, "DXOGLWin_%d", (int)clock());
355 
356         wc.lpszClassName = oglWindowClassName;
357 
358         if (! RegisterClass(&wc)) {
359             LPVOID lpMsgBuf;
360 
361             FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
362                           NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
363                           (LPTSTR) &lpMsgBuf,0, NULL);
364 
365             fprintf(stderr, "RegisterClass failed: %s\n", lpMsgBuf);
366 
367             return ERROR;
368         }
369 
370         OGLWindowClassRegistered = hInstance;
371     }
372 
373     return OK;
374 }
375 
376 static BOOL
ChildSize(HWND kid,LPARAM arg)377 ChildSize(HWND kid, LPARAM arg)
378 {
379     RECT rect;
380     GetClientRect(kid, &rect);
381     fprintf(stderr, "0x%08lx t %d b %d l %d r %d\n",
382             (int)kid, rect.top, rect.bottom, rect.left, rect.right);
383 }
384 
385 static int
CreateOGLWindow(tdmChildGlobalP globals,char * winName)386 CreateOGLWindow(tdmChildGlobalP globals, char *winName)
387 {
388     DEFGLOBALDATA(globals) ;
389     DEFPORT(PORT_HANDLE);
390     HINSTANCE hInstance;
391     MSG msg;
392     int k;
393 
394     OGLWindow *oglw = (OGLWindow *)DXAllocateZero(sizeof(OGLWindow));
395 
396     static PIXELFORMATDESCRIPTOR pfd =
397         {
398             sizeof(PIXELFORMATDESCRIPTOR),
399             1,
400             PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
401             PFD_TYPE_RGBA,
402             24,
403             0, 0, 0,
404             0, 0, 0,
405             0, 0,
406             0, 0, 0, 0, 0,
407             32, 0, 0,
408             PFD_MAIN_PLANE,
409             0, 0, 0, 0
410         };
411     int nM;
412 
413     if (! DXGetWindowsInstance(&hInstance))
414         return ERROR;
415 
416     ENTRY(("_dxfCreateHWWindow(0x%x, \"%s\")",globals, winName));
417 
418     if (PARENT_WINDOW) {
419         DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN;
420         XWINID = CreateWindow(oglWindowClassName,
421                               winName, dwStyle,
422                               CW_USEDEFAULT, 0, PIXW, PIXH,
423                               PARENT_WINDOW, NULL, hInstance, NULL);
424     } else {
425         DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
426         XWINID = CreateWindow(oglWindowClassName,
427                               winName, dwStyle,
428                               CW_USEDEFAULT, 0, PIXW, PIXH,
429                               NULL, NULL, hInstance, NULL);
430     }
431 
432     if (! XWINID) {
433 		LPVOID lpMsgBuf;
434 		FormatMessage(
435 			FORMAT_MESSAGE_ALLOCATE_BUFFER |
436 			FORMAT_MESSAGE_FROM_SYSTEM |
437 			FORMAT_MESSAGE_IGNORE_INSERTS,
438 			NULL,
439 			GetLastError(),
440 			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
441 			(LPTSTR) &lpMsgBuf,
442 			0,
443 			NULL
444 			);
445 		DXSetError(ERROR_INTERNAL, lpMsgBuf);
446 		// Free the buffer.
447 		LocalFree( lpMsgBuf );
448         return ERROR;
449     }
450 
451     oglw->globals = globals;
452 
453     SetOGLWPtr(XWINID, oglw);
454 
455     _dxf_CREATE_WINDOW(globals, winName, PIXX, PIXY);
456 
457     ShowWindow(XWINID, 1);
458     UpdateWindow(XWINID);
459 	SetForegroundWindow(XWINID);
460 
461     return OK;
462 }
463 
464 
465 extern tdmParsedFormatT*
466     _tdmParseDisplayString (char *displayString,char** cacheIdP);
467 extern Error
468     _dxfDeleteParsedDisplayString(tdmParsedFormatT *pFormat);
469 
470 
471 void
_dxf_SetHardwareWindowsWindowActive(char * where,int active)472 _dxf_SetHardwareWindowsWindowActive(char *where, int active)
473 {
474     tdmParsedFormatT  *pFormat = NULL;
475     Private 	      cacheObject = NULL;
476     tdmChildGlobalP   globals = NULL;
477     char*		      cacheId = NULL;
478 
479     if (!(pFormat = _tdmParseDisplayString (where, &cacheId)))
480         goto error;
481     if(cacheObject = (Private) DXGetCacheEntry(cacheId, 0, 0)) {
482         globals = (tdmChildGlobalP) DXGetPrivateData(cacheObject);
483         if (globals) {
484             DEFGLOBALDATA(globals);
485             if (XWINID > 0)
486                 ShowWindow(XWINID, active ? SW_SHOW : SW_HIDE);
487         }
488 
489         DXDelete((dxObject)cacheObject);
490     }
491 
492 error:
493     if (cacheId)
494         tdmFree(cacheId);
495     if (pFormat)
496         _dxfDeleteParsedDisplayString(pFormat);
497     return;
498 }
499 
500 
501 Error
_dxfCreateHWWindow(tdmChildGlobalP globals,char * winName,Camera c)502 _dxfCreateHWWindow (tdmChildGlobalP globals, char *winName, Camera c)
503 {
504     DEFGLOBALDATA(globals);
505 
506     if (!_registerOGLWindowClass())
507         goto error;
508 
509     PARENT_WINDOW = _dxfConvertWinName(winName) ;
510     UI_TYPE = _dxfUIType(winName);
511     VISIBILITY = 0;
512     MAPPED = 0;
513 
514     CAN_RENDER = 0;
515 
516     if (c) {
517         DXGetCameraResolution(c, &PIXX, &PIXY);
518     } else {
519         PIXX = 640;
520         PIXY = 480;
521     }
522 
523     PIXW = PIXX;
524     PIXH = PIXY;
525 
526     MATRIX_STACK = _dxfCreateStack();
527     _dxfInitDXInteractors(globals);
528     _dxfSetInteractorWindowSize(INTERACTOR_DATA, PIXX, PIXY);
529 
530     CreateOGLWindow(globals, winName);
531 
532 
533     CAN_RENDER = 1;
534 
535     return OK;
536 
537 error:
538     return ERROR;
539 }
540 
541 static Error
_tdmResizeImage(WinP win)542 _tdmResizeImage (WinP win)
543 {
544     DEFWINDATA(win);
545     int camw, camh;
546 
547     ENTRY(("_tdmResizeImage (0x%x)", win));
548 
549     if (CAMERA) {
550         if (! DXGetCameraResolution (CAMERA, &camw, &camh))
551             DXErrorGoto (ERROR_INVALID_DATA, "#13530") ;
552     } else
553         if (! DXGetImageSize (OBJECT, &camw, &camh))
554             DXErrorGoto (ERROR_INVALID_DATA, "#13540") ;
555 #if 0
556 
557     _dxfSetInteractorWindowSize(INTERACTOR_DATA, camw, camh);
558 #endif
559 
560     return _tdmResizeWindow(win, camw, camh, NULL);
561 
562 error:
563     return ERROR ;
564 }
565 
566 
567 Error
_tdmResizeWindow(WinP win,int w,int h,int * winSizeChange)568 _tdmResizeWindow (WinP win, int w, int h, int *winSizeChange)
569 {
570     DEFWINDATA(win) ;
571     DEFPORT(PORT_HANDLE) ;
572     int camw, camh, changed
573     /*
574      *  If we're not already at correct size, resize.
575      */
576 
577     ENTRY(("_tdmResizeWindow (0x%x, %d, %d, 0x%x)",win, w, h, winSizeChange));
578 
579     changed = (PIXX != w || PIXY != h);
580     if (changed) {
581         if (winSizeChange)
582             *winSizeChange = 1;
583 
584         PIXX = w;
585         PIXY = h;
586     } else
587         if (winSizeChange)
588             *winSizeChange = 0;
589 
590 #if 0
591 
592     if (CAMERA) {
593         if (! DXGetCameraResolution (CAMERA, &camw, &camh))
594             DXErrorGoto (ERROR_INVALID_DATA, "#13530") ;
595     } else
596         if (! DXGetImageSize (OBJECT, &camw, &camh))
597             DXErrorGoto (ERROR_INVALID_DATA, "#13540") ;
598 
599 
600     if (changed || VIEWPORT_W != camw || VIEWPORT_H != camh) {
601 
602         _dxf_SET_VIEWPORT(PORT_CTX, 0, camw-1, h-camh, h-1);
603         _dxfSetViewport(MATRIX_STACK, 0, camw-1, h-camh, h-1);
604         _dxfInteractorViewChanged(INTERACTOR_DATA);
605         VIEWPORT_W = w;
606         VIEWPORT_H = h;
607     }
608 #else
609     DXSetResolution(CAMERA, w, ((double)h)/w);
610     _dxf_SET_VIEWPORT(PORT_CTX, 0, w-1, 0, h-1);
611     _dxfSetViewport(MATRIX_STACK, 0, w-1, 0, h-1);
612     _dxfInteractorViewChanged(INTERACTOR_DATA);
613     PIXX = VIEWPORT_W = w;
614     PIXY = VIEWPORT_H = h;
615 #endif
616 
617 
618     CORRECT_SIZE = TRUE ;
619 
620     return OK ;
621 
622 error:
623 
624     return ERROR ;
625 }
626 
627 
628 void
_dxfChangeBufferMode(WinP win,int mode)629 _dxfChangeBufferMode(WinP win, int mode)
630 {
631     DEFWINDATA(win);
632     DEFPORT(PORT_HANDLE);
633 
634     ENTRY(("_dxfChangeBufferMode(0x%x, %d)",win,mode));
635 
636     if (mode == DoubleBufferMode) {
637         if (BUFFER_MODE == SingleBufferMode) /* needs changing? */
638         {
639             _dxf_DOUBLE_BUFFER_MODE(PORT_CTX) ;
640             BUFFER_MODE = DoubleBufferMode ;
641         }
642     } else /* mode == SingleBufferMode */
643     {
644         if (BUFFER_MODE == DoubleBufferMode) /* needs changing? */
645         {
646             _tdmClearWindow(win) ;
647             _dxf_SINGLE_BUFFER_MODE(PORT_CTX) ;
648             BUFFER_MODE = SingleBufferMode ;
649         }
650     }
651 
652     EXIT((""));
653 }
654 
655 
656 static void
_tdmClearWindow(WinP win)657 _tdmClearWindow (WinP win)
658 {
659     DEFWINDATA(win) ;
660     DEFPORT(PORT_HANDLE) ;
661 
662     ENTRY(("_tdmClearWindow (0x%x)",win));
663 
664     _dxf_CLEAR_AREA (PORT_CTX, 0, PIXW - 1 , 0, PIXH - 1) ;
665 
666     EXIT((""));
667 }
668 
669 int
_dxfTrySaveBuffer(WinP win)670 _dxfTrySaveBuffer (WinP win)
671 {
672     return 0;
673 }
674 
675 int
_dxfTryRestoreBuffer(WinP win)676 _dxfTryRestoreBuffer (WinP win)
677 {
678     return 0;
679 }
680 
681 static void
_tdmCleanupChild(tdmChildGlobalP globals)682 _tdmCleanupChild (tdmChildGlobalP globals)
683 {
684     DEFGLOBALDATA(globals) ;
685     HWND tmpParentWindow = PARENT_WINDOW;
686 
687     ENTRY(("_tdmCleanupChild (0x%x)", globals));
688 
689     if (globals->cacheId) {
690         /*
691          *  DXRemove cache entry for this instance.  This will cause
692          *  _dxfEndRenderModule() to be invoked as a side effect, since it is
693          *  registered as the callback for the cache deletion.
694          */
695         PRINT(("cacheId exists, deleting cache entry")) ;
696         DXSetCacheEntry (0, CACHE_PERMANENT, globals->cacheId, 0, 0) ;
697 
698     }
699 
700     EXIT((""));
701 }
702 
703 
704 int
_dxfConvertWinName(char * winName)705 _dxfConvertWinName(char *winName)
706 {
707     int i ;
708 
709     /* ENTRY(("_dxfConvertWinName(\"%s\")",winName)); */
710 
711     for (i = strlen(winName)-1 ; i >= 0 ; i--)
712         if (!isdigit(winName[i]))
713             break;
714 
715     if (i == -1) {
716         /* no pound signs, all digits */
717         /* EXIT(("0")); */
718         return 0 ;
719         /* #X was
720          * } else if (winName[i] == '#' && (i !=0 && winName[i-1] == '#')) {
721          */
722     } else if ((winName[i] == '#' || winName[i] == 'X') && (i !=0 && winName[i-1] == '#')) {
723         /* 2 pound signs */
724         /* EXIT(("fill in this value")); */
725         return atoi(&winName[i+1]) ;
726     } else {
727         /* EXIT(("0")); */
728         return 0 ;
729     }
730 }
731 
732 int
_dxfUIType(char * winName)733 _dxfUIType(char *winName)
734 {
735 
736     int i ;
737 
738     for (i = strlen(winName)-1 ; i >= 0 ; i--)
739         if (!isdigit(winName[i]))
740             break;
741 
742     if (i > 0 && winName[i] == '#' && i !=0 && winName[i-1] == '#')
743         return DXD_DXUI;
744     else if (i > 0 && winName[i] == 'X' && i !=0 && winName[i-1] == '#')
745         return DXD_EXTERNALUI;
746     else
747         return DXD_NOUI;
748 }
749 /* #X end */
750 
751 
752 extern Field DXMakeImageFormat(int w, int h, char *format);
753 
754 Field
_dxfCaptureHardwareImage(tdmChildGlobalP globals)755 _dxfCaptureHardwareImage(tdmChildGlobalP globals)
756 {
757     DEFGLOBALDATA(globals) ;
758     DEFPORT(PORT_HANDLE) ;
759     Field image = NULL;
760     Array colors;
761 
762     image = DXMakeImageFormat(PIXW, PIXH, "BYTE");
763     if (! image)
764         goto error;
765 
766     colors = (Array)DXGetComponentValue(image, "colors");
767     if (! colors)
768         goto error;
769 
770     if (! _dxf_READ_IMAGE(LWIN, DXGetArrayData(colors)))
771         goto error;
772 
773     return image;
774 
775 error:
776     DXDelete((dxObject)image);
777     return NULL;
778 }
779 
780 /****************************** END WINDOWS *********************************/
781 #else /* DX_NATIVE_WINDOWS */
782 
783 #define FLING_TIMEOUT 3
784 #define FLING_GNOMON_FEECHURE
785 
786 /*
787 * Environment:		Risc System 6000
788 * Current Source:	$Source: /src/master/dx/src/exec/hwrender/hwWindow.c,v $
789 * Author:		Tim Murphy
790 *
791 */
792 
793 #include <sys/types.h>
794 #include <stdio.h>
795 #include <math.h>
796 #include <time.h>
797 #include <X11/Xlib.h>
798 #include <X11/Xatom.h>
799 #include <X11/Xutil.h>
800 
801 #if defined(HAVE_STRING_H)
802 #include <string.h>
803 #endif
804 
805 #if defined(HAVE_CTYPE_H)
806 #include <ctype.h>
807 #else
808 extern int isdigit (int);
809 #endif
810 
811 #include "hwDeclarations.h"
812 #include "hwWindow.h"
813 #include "hwClientMessage.h"
814 #include "hwMatrix.h"
815 #include "hwMemory.h"
816 
817 #include "hwDebug.h"
818 
819 /*
820 *  X Function Declarations.
821 */
822 
823 extern Bool
824     XCheckTypedWindowEvent(Display *, Window, int, XEvent *) ;
825 
826 #if 0
827 #ifdef DXD_WIN
828 extern void XPutBackEvent(Display *, XEvent *) ;
829 #else
830 extern XPutBackEvent(Display *, XEvent *) ;
831 #endif
832 #endif
833 
834 /*
835 * Internal  Function Declarations
836 */
837 
838 static Error
839 _tdmResizeImage(WinP win) ;
840 static Error
841 _tdmResizeWindow(WinP win, int w, int h, int *change) ;
842 static void
843 _tdmClearWindow(WinP win) ;
844 static void
845 _tdmCleanupChild(tdmChildGlobalP childGlobals) ;
846 static Window
847 _getTopLevelShell (Display *dpy, Window w) ;
848 
849 int _dxfUIType(char *);
850 extern Error _dxfDraw (void*, dxObject, Camera, int);
851 
852 
853 /*
854 *  These atoms are used by the window manager to notify us if we're about
855 *  to get killed (eg, evil user hits "close" item on Motif window menu).
856 */
857 
858 static Atom XA_WM_PROTOCOLS ;
859 static Atom XA_WM_DELETE_WINDOW ;
860 static Atom XA_GL_WINDOW_ID ;
861 
862 /* Other commuication Atoms */
863 extern struct atomRep _dxdtdmAtoms[];
864 
865 /*
866 *  X error handling
867 */
868 
869 static int _tdmXerror = 0 ;
870 
_dxfSetXError(Display * dpy,XErrorEvent * event)871 void _dxfSetXError (Display *dpy, XErrorEvent *event)
872 {
873     char buffer[128] ;
874     ENTRY(("_dxfSetXError(0x%x, 0x%x)",dpy, event));
875 
876     XGetErrorText (dpy, event->error_code, buffer, sizeof(buffer)) ;
877     /*
878     DXSetError (ERROR_INTERNAL, "#13490", buffer) ;
879     */
880 
881     EXIT(("X Error: %s", buffer));
882 }
883 
884 
_dxfXErrorHandler(Display * dpy,XErrorEvent * error)885 int _dxfXErrorHandler (Display *dpy, XErrorEvent *error)
886 {
887     ENTRY(("_dxfXErrorHandler (0x%x, 0x%x)",dpy, error));
888 
889     _dxfSetXError (dpy, error) ;
890     _tdmXerror = 1 ;
891 
892     EXIT(("1"));
893     return 1 ;
894 }
895 
_dxfCatchWinopenErrors(Display * dpy,XErrorEvent * rep)896 int _dxfCatchWinopenErrors (Display *dpy, XErrorEvent *rep)
897 {
898     /*
899     * We get this during winopen on 3.1.5.
900     */
901 
902     ENTRY(("_dxfCatchWinopenErrors (0x%x, 0x%x)",dpy, rep));
903 
904     if (rep->error_code == BadAccess) {
905         EXIT(("BadAccess error ignored"));
906         return 0 ;
907     }
908 
909     _dxfSetXError (dpy, rep) ;
910 
911     EXIT(("1"));
912     return 1 ;
913 }
914 
915 /*
916 *  This function creates a graphics window (if possible on this machine), and
917 *  attaches the resulting window id to the window that the UI created.
918 *
919 *  This function should only be called ONCE per tdmRender module instance.
920 *  It will create a graphics window each time.
921 */
922 
_dxfCreateWindow(tdmChildGlobalP globals,char * winName)923 Error _dxfCreateWindow (tdmChildGlobalP globals, char *winName)
924 {
925     XWindowAttributes attr ;
926     unsigned long eventMask ;
927     DEFGLOBALDATA(globals) ;
928     DEFPORT(PORT_HANDLE) ;
929     XWindowChanges xwc;
930 
931     ENTRY(("_dxfCreateWindow(0x%x, \"%s\")",globals, winName));
932 
933     /* ignore spurious errors generated by some environments */
934     XSetErrorHandler (_dxfCatchWinopenErrors) ;
935 
936     /* convert text representation of window id */
937     PARENT_WINDOW = _dxfConvertWinName(winName) ;
938     UI_TYPE = _dxfUIType(winName);
939 
940     /* Assume the window is obsured, we'll change this when we get a
941     * visibilityNotify event.
942     */
943     VISIBILITY = VisibilityFullyObscured ;
944 
945     /* set window size as uninitialized */
946     PIXW = -1 ;
947     PIXH = -1 ;
948 
949     /* Mark window as unmapped */
950     MAPPED = 0;
951 
952     /* create the graphics window */
953     if (PARENT_WINDOW) {
954         /* if there is a UI ... */
955         XGetWindowAttributes (DPY, PARENT_WINDOW, &attr) ;
956         PRINT(("Before _dxf_CREATE_WINDOW(UI)"));
957         if(!( XWINID =
958                     (Window)_dxf_CREATE_WINDOW (globals, winName,
959                                                 attr.width, attr.height)))
960             goto error;
961         PRINT(("After _dxf_CREATE_WINDOW"));
962     } else {
963         PRINT(("Before _dxf_CREATE_WINDOW (script)"));
964         if(!( XWINID =
965                     (Window)_dxf_CREATE_WINDOW (globals, winName, 640, 480)))
966             goto error;
967         PRINT(("\nAfter _dxf_CREATE_WINDOW"));
968     }
969 
970     /* #X
971     * if (PARENT_WINDOW)
972     */
973     if (DXUI) {
974         /*
975         *  UI is present.
976         *
977         *  Find the top level shell of the UI image window in order to
978         *  select for ConfigureNotify; otherwise, we don't get a
979         *  ConfigureNotify on window moves since our graphics window never
980         *  moves relative to its immediate parent.
981         *
982         *  We need to know when the window moves since some (broken?) X
983         *  servers neither copy the graphics window's pixels along with the
984         *  window nor send exposure events.
985         *
986         *  Also select for ConfigureNotify in the immediate parent
987         *  (wigWindow) of the graphics window in order to be informed when
988         *  the UI resizes the immediate parent in response to new camera
989         *  sizes from us.  We don't seem to receive this ConfigureNotify on
990         *  the top level shell.
991         */
992 
993         TOPLEVEL =
994             _getTopLevelShell (DPY, PARENT_WINDOW) ;
995 
996         if (TOPLEVEL)
997             XSelectInput (DPY,
998                           TOPLEVEL, StructureNotifyMask) ;
999         else
1000             /* Can't find top level UI shell */
1001             DXErrorGoto (ERROR_UNEXPECTED, "#13570") ;
1002 
1003         /* record initial placment of top level shell */
1004         XGetWindowAttributes (DPY, TOPLEVEL, &attr) ;
1005         PIXX = attr.x ;
1006         PIXY = attr.y ;
1007 
1008         /* reparent the graphics window */
1009         XReparentWindow (DPY,
1010                          XWINID,
1011                          PARENT_WINDOW,
1012                          DXD_HW_REPARENT_OFFSET_X,
1013                          DXD_HW_REPARENT_OFFSET_Y) ;
1014 
1015         /* select for ConfigureNotify on our new parent */
1016         XSelectInput (DPY,
1017                       PARENT_WINDOW, StructureNotifyMask | PropertyChangeMask) ;
1018 
1019         /* setup UI client message protocol */
1020         if (!_dxfInitCMProtocol(LWIN)) {
1021             PRINT(("UI client message protocol init failed")) ;
1022             DXErrorGoto (ERROR_INTERNAL, "#13580") ;
1023         }
1024 
1025         /* set mask for appropriate events on the graphics window */
1026         if (PIXDEPTH == 8)
1027             /* 8 bit display requires enter/leave window events for colormap */
1028             eventMask = VisibilityChangeMask | ExposureMask |
1029                         ButtonPressMask | ButtonReleaseMask |
1030                         EnterWindowMask | LeaveWindowMask | KeyPressMask;
1031         else
1032             eventMask = VisibilityChangeMask | ExposureMask |
1033                         ButtonPressMask | ButtonReleaseMask | KeyPressMask;
1034     }
1035     /* #X follows */
1036     else if (EXTERNALUI) {
1037         /*
1038         *  No UI.  Record initial placment of graphics window.  Set mask for
1039         *  ConfigureNotify on the graphics window along with the other events
1040         *  we need.
1041         */
1042 
1043         /* reparent the graphics window */
1044         XReparentWindow (DPY,
1045                          XWINID,
1046                          PARENT_WINDOW,
1047                          DXD_HW_REPARENT_OFFSET_X,
1048                          DXD_HW_REPARENT_OFFSET_Y) ;
1049 
1050         XGetWindowAttributes (DPY, XWINID, &attr) ;
1051         PIXX = attr.x ;
1052         PIXY = attr.y ;
1053 
1054         if (PIXDEPTH == 8)
1055             /* 8 bit display requires enter/leave window events for colormap */
1056             eventMask = VisibilityChangeMask | ExposureMask |
1057                         ButtonPressMask | ButtonReleaseMask |
1058                         EnterWindowMask | LeaveWindowMask |
1059                         StructureNotifyMask | KeyPressMask;
1060         else
1061             eventMask = VisibilityChangeMask | ExposureMask |
1062                         ButtonPressMask | ButtonReleaseMask |
1063                         StructureNotifyMask | KeyPressMask;
1064     }
1065     /* #X end */
1066     else {
1067         /*
1068         *  No UI.  Record initial placment of graphics window.  Set mask for
1069         *  ConfigureNotify on the graphics window along with the other events
1070         *  we need.
1071         */
1072 
1073         XGetWindowAttributes (DPY, XWINID, &attr) ;
1074         PIXX = attr.x ;
1075         PIXY = attr.y ;
1076 
1077         if (PIXDEPTH == 8)
1078             /* 8 bit display requires enter/leave window events for colormap */
1079             eventMask = VisibilityChangeMask | ExposureMask |
1080                         ButtonPressMask | ButtonReleaseMask |
1081                         EnterWindowMask | LeaveWindowMask |
1082                         StructureNotifyMask | KeyPressMask;
1083         else
1084             eventMask = VisibilityChangeMask | ExposureMask |
1085                         ButtonPressMask | ButtonReleaseMask |
1086                         StructureNotifyMask | KeyPressMask;
1087     }
1088 
1089     xwc.stack_mode = Below;
1090     XConfigureWindow(DPY, XWINID, CWStackMode, &xwc);
1091 
1092 
1093     /* this handler should handle errors from now on */
1094     XSetErrorHandler(_dxfXErrorHandler) ;
1095 
1096     /* get the window manager to inform us if it intends to kill our window */
1097     XA_WM_PROTOCOLS = XInternAtom (DPY, "WM_PROTOCOLS", 0) ;
1098     XA_WM_DELETE_WINDOW = XInternAtom (DPY, "WM_DELETE_WINDOW", 0) ;
1099     XA_GL_WINDOW_ID = XInternAtom (DPY, "GL_WINDOW_ID", 0) ;
1100     XChangeProperty (DPY,XWINID,
1101                      XA_WM_PROTOCOLS, XA_ATOM, 32, PropModeReplace,
1102                      (unsigned char *)&XA_WM_DELETE_WINDOW, 1) ;
1103 
1104     /* select the events we need on the graphics window */
1105     XSelectInput (DPY, XWINID, eventMask) ;
1106 
1107     /* create a software matrix stack to shadow hardware matrix stack */
1108     MATRIX_STACK = _dxfCreateStack() ;
1109 
1110 
1111     /* initialize hardware direct interactors */
1112     _dxfInitDXInteractors(globals) ;
1113 
1114     if (_tdmXerror) {
1115         PRINT(("X error occured")) ;
1116     }
1117 
1118     _tdmXerror = 0 ;
1119 
1120     EXIT(("OK"));
1121     return OK ;
1122 
1123 error:
1124 
1125     EXIT(("ERROR"));
1126     return ERROR ;
1127 }
1128 
1129 /*
1130 *  This is the currently defined resize behavior:
1131 *
1132 *  With the UI:
1133 *
1134 *  When the user changes the camera values the window will size to those
1135 *  dimensions and redraw.
1136 *
1137 *  When the user grabs the window corner the UI will update the camera and
1138 *  the window will resize to those dimensions and redraw, isotropically
1139 *  scaling for an appropriate fit.
1140 *
1141 *  Without the UI:
1142 *
1143 *  When the user changes the camera values the window will size to those
1144 *  dimensions and redraw, scaling the image isotropically.
1145 *
1146 *  When the user grabs the window corner the window will resize, and as
1147 *  much of the image as will fit will be moved to the upper left corner
1148 *  of the new window.  The Camera will remain unchanged.  The window will
1149 *  automatically resize to the camera dimensions if Display is called
1150 *  again.
1151 */
1152 
1153 static Error
_tdmResizeImage(WinP win)1154 _tdmResizeImage (WinP win)
1155 {
1156     DEFWINDATA(win);
1157     Window RootReturn ;
1158     int XReturn, YReturn, camw, camh, dummy ;
1159     unsigned int BorderWidthReturn, DepthReturn ;
1160     unsigned int wigW, wigH ;
1161 
1162     ENTRY(("_tdmResizeImage (0x%x)", win));
1163 
1164     if (CAMERA) {
1165         if (! DXGetCameraResolution (CAMERA, &camw, &camh))
1166             /* unable to get camera resolution */
1167             DXErrorGoto (ERROR_DATA_INVALID, "#13530") ;
1168     } else
1169         /* assume we have been given an image */
1170         if (! DXGetImageSize (OBJECT, &camw, &camh))
1171             /* unable to get image resolution */
1172             DXErrorGoto (ERROR_DATA_INVALID, "#13540") ;
1173 
1174     PRINT (("DX object resolution: %dx%d", camw, camh));
1175 
1176     /* #X was
1177     * if (PARENT_WINDOW)
1178     */
1179     if (DXUI)	/* if there is a UI ... */
1180     {
1181         XGetGeometry(DPY, PARENT_WINDOW, &RootReturn, &XReturn, &YReturn,
1182                      &wigW, &wigH, &BorderWidthReturn, &DepthReturn) ;
1183 
1184         PRINT(("parent window size: %dx%d", wigW, wigH));
1185 
1186         /*
1187         *  If the image resolution and the widget window size are the same,
1188         *  just get resizeWindow to set the graphics window to that size .
1189         */
1190 
1191         if (camw == wigW && camh == wigH)
1192             _tdmResizeWindow (win, wigW, wigH, &dummy) ;
1193         else
1194         {
1195             /*
1196             *  Else get the UI to make the widget size and resolution agree.
1197             *  We'll get the graphics window to agree when we get the configure
1198             *  notify on the widget window.
1199             */
1200 
1201             tdmMessageData data ;
1202 
1203             /*
1204             CORRECT_SIZE = FALSE ;
1205             */
1206 
1207             data.l[0] = camw ;
1208             data.l[1] = camh ;
1209 
1210             PRINT(("notifying UI of current resolution")) ;
1211             _dxfSendClientMessage (DPY, PARENT_WINDOW, XA_Integer, &data) ;
1212         }
1213     }
1214     else /* No UI ... */
1215     {
1216         /*
1217         *  Make sure the saved window size is correct for the GLwindow
1218         *  then resize.
1219         */
1220 
1221         XGetGeometry (DPY, XWINID, &RootReturn, &XReturn, &YReturn,
1222                       (unsigned int *)&PIXW, (unsigned int *)&PIXH,
1223                       &BorderWidthReturn, &DepthReturn) ;
1224 
1225         PRINT(("graphics window size: %dx%d", PIXW, PIXH));
1226 
1227         _dxfSetInteractorWindowSize (INTERACTOR_DATA, camw, camh) ;
1228         if (camw != PIXW || camh != PIXH) {
1229             DEFWINDATA(win) ;
1230             DEFPORT(PORT_HANDLE) ;
1231             _dxf_SET_WINDOW_SIZE (win, camw, camh) ;
1232         }
1233 
1234         _tdmResizeWindow (win, camw, camh, &dummy) ;
1235     }
1236 
1237     if (_tdmXerror)
1238         goto error ;
1239 
1240     EXIT(("OK"));
1241     return OK ;
1242 
1243 error:
1244     _tdmXerror = 0 ;
1245 
1246     EXIT(("ERROR"));
1247     return ERROR ;
1248 }
1249 
1250 
1251 static Error
_tdmResizeWindow(WinP win,int w,int h,int * winSizeChange)1252 _tdmResizeWindow (WinP win, int w, int h, int *winSizeChange)
1253 {
1254     int camw, camh ;
1255     DEFWINDATA(win) ;
1256     DEFPORT(PORT_HANDLE) ;
1257 
1258     /*
1259     *  If we're not already at correct size, resize.
1260     */
1261 
1262     ENTRY(("_tdmResizeWindow (0x%x, %d, %d, 0x%x)",win, w, h, winSizeChange));
1263 
1264     if (w != PIXW || h != PIXH) {
1265         /*
1266         * If we have a UI set the GL window to the new size.
1267         * For script we only do this when we resizeImage.
1268         */
1269 
1270         /* #X was
1271         * if (PARENT_WINDOW)
1272         */
1273         if (DXUI)	/* if there is a UI ... */
1274         {
1275             _dxf_SET_WINDOW_SIZE (win, w, h) ;
1276             _dxfSetInteractorWindowSize (INTERACTOR_DATA, w, h) ;
1277         }
1278 
1279         PIXW = w ;
1280         PIXH = h ;
1281 
1282         _tdmClearWindow(win) ;
1283         *winSizeChange = 1 ;
1284     } else
1285         *winSizeChange = 0 ;
1286 
1287     if (CAMERA) {
1288         if (! DXGetCameraResolution (CAMERA, &camw, &camh))
1289             /* unable to get camera resolution */
1290             DXErrorGoto (ERROR_DATA_INVALID, "#13530") ;
1291     } else
1292         if (! DXGetImageSize (OBJECT, &camw, &camh))
1293             /* unable to get image resolution */
1294             DXErrorGoto (ERROR_DATA_INVALID, "#13540") ;
1295 
1296     PRINT(("current DX resolution: %dx%d", camw, camh));
1297     PRINT(("current viewport: %dx%d", VIEWPORT_W, VIEWPORT_H));
1298 
1299     if (*winSizeChange || VIEWPORT_W != camw || VIEWPORT_H != camh) {
1300         _dxf_SET_VIEWPORT (PORT_CTX, 0, camw-1, h-camh, h-1) ;
1301         _dxfSetViewport (MATRIX_STACK, 0, camw-1, h-camh, h-1) ;
1302         /* !!!! check for increment view_state twice !!!! */
1303         _dxfInteractorViewChanged(INTERACTOR_DATA) ;
1304         VIEWPORT_W = camw ;
1305         VIEWPORT_H = camh ;
1306     }
1307 
1308     if (_tdmXerror)
1309         goto error ;
1310     CORRECT_SIZE = TRUE ;
1311 
1312     EXIT(("OK"));
1313     return OK ;
1314 
1315 error:
1316     _tdmXerror = 0 ;
1317 
1318     EXIT(("ERROR"));
1319     return ERROR ;
1320 }
1321 
1322 /*
1323 *  _dxfProcessEvents() is invoked in two ways: 1) from tdmRender() in
1324 *  response to a new DX object, camera, or render option; and 2) as a
1325 *  callback in response to input on the file associated with the X
1326 *  display connection.
1327 */
1328 
1329 extern int _dxf_ExIsExecuting();
1330 
checkDestroy(Display * d,XEvent * ev,char * arg)1331 static Bool checkDestroy(Display *d, XEvent *ev, char *arg)
1332 {
1333     return (ev->type == DestroyNotify);
1334 }
1335 
1336 Error
_dxfProcessEvents(int fd,tdmChildGlobalP globals,int flags)1337 _dxfProcessEvents (int fd, tdmChildGlobalP globals, int flags)
1338 {
1339     Display *dpy ;
1340     XEvent ev ;
1341     unsigned int mask;
1342     int doRedraw, winSizeChange ;
1343     tdmInteractorReturn R ;
1344     XWindowAttributes attr;
1345     static Time lasttime = 0 ;
1346     DEFGLOBALDATA(globals) ;
1347     DEFPORT(PORT_HANDLE) ;
1348     int dxEventMask = EVENT_MASK(globals->CrntInteractor);
1349     Window eventWindow;
1350 
1351     if (fd != -1)
1352         DEBUG_MARKER("_dxfProcessEvents ENTRY");
1353     ENTRY(("_dxfProcessEvents (%d, 0x%x)",fd, globals));
1354 
1355     /*
1356     * Look ahead for destroy event
1357     */
1358     if (XCheckIfEvent(DPY, &ev, checkDestroy, NULL)) {
1359         DXMessage("Found destroy notify... cleaning up");
1360         GL_WINDOW = FALSE;
1361         _tdmCleanupChild(globals) ;
1362         goto done;
1363     }
1364 
1365     dpy = DPY ;
1366 
1367     /* assume we don't need to refresh image */
1368     doRedraw = FALSE ;
1369 
1370     if (fd == -1) {
1371 
1372         /* remap window if unmapped */
1373         if (! MAPPED) {
1374             XEvent event;
1375 
1376             PRINT(("mapping window %d", XWINID));
1377             if(DXUI) {
1378                 XChangeProperty(DPY,PARENT_WINDOW,
1379                                 XA_GL_WINDOW_ID,
1380                                 XA_GL_WINDOW_ID,
1381                                 32,
1382                                 PropModeReplace,
1383                                 (unsigned char*)&XWINID,
1384                                 1);
1385                 for((*(XPropertyEvent*)&event).state = !PropertyDelete;
1386                         (*(XPropertyEvent*)&event).state != PropertyDelete;) {
1387                     /* wait for UI to respond before starting to draw */
1388                     XWindowEvent (DPY, PARENT_WINDOW,
1389                                   PropertyChangeMask, &event) ;
1390                 }
1391             }
1392             /* #X follows */
1393             else if (EXTERNALUI) {
1394                 /* map the graphics window */
1395                 XMapWindow (DPY, PARENT_WINDOW) ;
1396                 XMapWindow (DPY, XWINID) ;
1397                 if (STEREOSYSTEMMODE >= 0) {
1398                     if (XWINID != LEFTWINDOW)
1399                         XMapWindow (DPY, LEFTWINDOW) ;
1400                     if (XWINID != RIGHTWINDOW)
1401                         XMapWindow (DPY, RIGHTWINDOW) ;
1402                 }
1403             }
1404             /* #X end */
1405             else {
1406                 /* map the graphics window */
1407                 XMapWindow (DPY, XWINID) ;
1408                 if (STEREOSYSTEMMODE >= 0) {
1409                     if (XWINID != LEFTWINDOW)
1410                         XMapWindow (DPY, LEFTWINDOW) ;
1411                     if (XWINID != RIGHTWINDOW)
1412                         XMapWindow (DPY, RIGHTWINDOW) ;
1413                 } else
1414                     XWindowEvent (DPY, XWINID, ExposureMask, &event) ;
1415 
1416                 /* wait for pending requests to be processed by X
1417                 * before graphics output
1418                 */
1419             }
1420             XSync (DPY, False) ;
1421 
1422             MAPPED = 1 ;
1423         }
1424 
1425         doRedraw = 1;
1426         /* adjust graphics window image size to camera image size if necessary */
1427         _tdmResizeImage(LWIN) ;
1428     }
1429 
1430     /*
1431     *  Loop while events pending or until UI responds to new camera size with
1432     *  a ConfigureNotify.
1433     */
1434 
1435     while (XPending(dpy) || !CORRECT_SIZE) {
1436 #if defined(DXD_HW_WINDOW_DESTRUCTION_CHECK)
1437         /*
1438         *  Check to ensure graphics window still exists.  On some
1439         *  architectures (SGI/GL) the graphics window dies without
1440         *  notification and breaks the connection to the DX server on the
1441         *  next graphics API call.
1442         */
1443         XSync(dpy, False);
1444         GL_WINDOW = XGetWindowAttributes(dpy,XWINID,&attr);
1445 #else
1446 /*  set the global variable to TRUE on all other arch. */
1447 GL_WINDOW = TRUE;
1448 #endif
1449 
1450         XNextEvent(dpy, &ev) ;
1451         switch (ev.type) {
1452         case KeyPress:
1453             if (flags || !_dxf_ExIsExecuting()) {
1454                 PRINT (("KeyPress")) ;
1455                 if (!CORRECT_SIZE)
1456                     continue ;
1457 
1458                 if (! (dxEventMask & DXEVENT_KEYPRESS)) {
1459                     Window tmp = ev.xany.window;
1460                     ev.xany.window = PARENT_WINDOW;
1461                     XSendEvent(dpy, PARENT_WINDOW, True, 0, &ev);
1462                     ev.xany.window = tmp;
1463                 } else {
1464                     char buf[32];
1465                     XLookupString(&(ev.xkey), buf, 32, NULL, NULL);
1466                     if (buf[0])
1467                         tdmKeyStruck(globals->CrntInteractor, ev.xkey.x, ev.xkey.y, buf[0], ev.xkey.state);
1468                 }
1469             }
1470             break;
1471 
1472         case ConfigureNotify:
1473             PRINT (("ConfigureNotify"));
1474             if (DXUI) {
1475                 /*
1476                 *  UI case: ConfigureNotify selected on top level shell and
1477                 *  the immediate parent.
1478                 */
1479                 winSizeChange = 0 ;
1480                 if (ev.xconfigure.window == PARENT_WINDOW) {
1481                     /* check for size changes on the immediate parent only */
1482                     XWindowAttributes attr ;
1483 
1484                     XGetWindowAttributes (dpy, PARENT_WINDOW, &attr) ;
1485                     _tdmResizeWindow (LWIN, attr.width,
1486                                       attr.height, &winSizeChange) ;
1487                 }
1488             } else
1489                 /*  #X comment changed
1490                 *  Script or external UI case: ConfigureNotify selected
1491                 * on graphics window.
1492                 */
1493                 _tdmResizeWindow (LWIN, ev.xconfigure.width,
1494                                   ev.xconfigure.height, &winSizeChange) ;
1495 
1496             /*
1497             *  If no window size change, check for movement.  We have to do
1498             *  this since some (broken) X servers neither copy the
1499             *  graphics window's pixels nor generate an exposure event on
1500             *  movement.
1501             *
1502             *  HP and IBM handle this correctly.  Need to check on Sun and SGI
1503             */
1504 #if !(DXD_HW_XSERVER_MOVE_OK)
1505 
1506             if (!winSizeChange &&
1507                     (ev.xconfigure.x != PIXX ||
1508                      ev.xconfigure.y != PIXY)) {
1509                 doRedraw = TRUE ;
1510                 PIXX = ev.xconfigure.x ;
1511                 PIXY = ev.xconfigure.y ;
1512             }
1513 #endif
1514             break ;
1515 
1516         case ClientMessage:
1517             PRINT (("ClientMessage")) ;
1518             /* check for window manager kill using ICCC protocol */
1519             if (ev.xclient.message_type == XA_WM_PROTOCOLS) {
1520                 PRINT (("window manager kill")) ;
1521                 GL_WINDOW = FALSE;
1522                 _tdmCleanupChild(globals) ;
1523                 goto done ;
1524             }
1525 #if 1
1526             /* #X was
1527             * if (PARENT_WINDOW &&
1528             */
1529             else if (DXUI &&
1530                      ev.xclient.message_type == ATOM(GLDestroyWindow)) {
1531 
1532                 _tdmCleanupChild(globals);
1533                 goto done;
1534             }
1535 #endif
1536             /* #X was
1537             * if (PARENT_WINDOW)
1538             */
1539             else if (DXUI)
1540                 _dxfReceiveClientMessage
1541                 (globals, (XClientMessageEvent *) &ev, &doRedraw) ;
1542             break ;
1543 
1544         case ButtonPress:
1545             XSetInputFocus(DPY, XWINID, RevertToPointerRoot, CurrentTime);
1546             eventWindow = ev.xbutton.window;
1547             if (flags || !_dxf_ExIsExecuting()) {
1548                 PRINT (("ButtonPress")) ;
1549                 if (!CORRECT_SIZE)
1550                     continue ;
1551 
1552                 if ((ev.xbutton.button == Button1 && !(dxEventMask & DXEVENT_LEFT)) ||
1553                         (ev.xbutton.button == Button2 && !(dxEventMask & DXEVENT_MIDDLE)) ||
1554                         (ev.xbutton.button == Button3 && !(dxEventMask & DXEVENT_RIGHT))) {
1555                     XSendEvent(dpy, PARENT_WINDOW, True, 0, &ev);
1556                 } else {
1557                     if (ev.xbutton.time - lasttime < 350) {
1558                         PRINT(("DoubleClick")) ;
1559 
1560                         lasttime = 0 ;
1561                         tdmDoubleClick (globals->CrntInteractor,
1562                                         ev.xbutton.x, ev.xbutton.y, &R) ;
1563 
1564                         /* #X was
1565                         * if (PARENT_WINDOW)
1566                         */
1567                         if (DXUI)
1568                             _dxfSendInteractorData
1569                             (globals, globals->CrntInteractor, &R) ;
1570                     } else {
1571                         /* sample mouse pointer to drive interactor */
1572                         time_t t0, t1 ;
1573                         Window windummy ;
1574                         int n, idummy, x, y, x0, y0, xlast, ylast, dx, dy, button ;
1575 
1576                         n = 0 ;
1577                         t0 = time(0) ;
1578                         x0 = xlast = ev.xbutton.x ;
1579                         y0 = ylast = ev.xbutton.y ;
1580                         button = ev.xbutton.button ;
1581                         lasttime = ev.xbutton.time ;
1582 
1583                         tdmStartStroke (globals->CrntInteractor, x0, y0, button, ev.xbutton.state) ;
1584                         XQueryPointer (dpy, eventWindow, &windummy, &windummy,
1585                                        &idummy, &idummy, &x, &y, &mask) ;
1586 
1587                         /* keep going until a button-up */
1588                         while (mask &
1589                                 (Button1Mask | Button2Mask | Button3Mask |
1590                                  Button4Mask | Button5Mask)) {
1591                             /* maintain a count to compute average fling deltas */
1592                             if (x != xlast || y != ylast) {
1593                                 xlast = x ;
1594                                 ylast = y ;
1595                                 n++ ;
1596                             }
1597 
1598                             tdmStrokePoint (globals->CrntInteractor, x, y, INTERACTOR_BUTTON_DOWN, mask) ;
1599                             XQueryPointer (dpy, eventWindow, &windummy, &windummy,
1600                                            &idummy, &idummy, &x, &y, &mask) ;
1601                         }
1602 
1603                         if (!_dxf_isFlagsSet(_dxf_SERVICES_FLAGS(),
1604                                              SF_FLING)) {
1605                             /*
1606                             * If user has not asked for FLING (via export of undocumented
1607                             * env variable)... behave normally.
1608                             */
1609                             XCheckWindowEvent (dpy, eventWindow, ButtonReleaseMask, &ev) ;
1610                             tdmStrokePoint (globals->CrntInteractor,
1611                                             ev.xbutton.x, ev.xbutton.y, INTERACTOR_BUTTON_UP, ev.xbutton.state) ;
1612                         } else {
1613                             /* See if fling conditions have been met */
1614                             t1 = time(0) ;
1615                             dx = n ? (x - x0) / n : 0 ;
1616                             dy = n ? (y - y0) / n : 0 ;
1617 
1618                             if ((dx != 0 || dy != 0) &&
1619 #ifndef FLING_GNOMON_FEECHURE
1620                                     globals->executeOnChange &&
1621 #endif
1622                                     (t1 - t0 < FLING_TIMEOUT) &&
1623                                     (x<0 || y<0 || x>PIXW || y>PIXH) &&
1624                                     ((button == 2 &&
1625                                       (globals->CrntInteractor == globals->RoamGroup ||
1626                                        globals->CrntInteractor == globals->CursorGroup)) ||
1627                                      (button != 3 &&
1628                                       (globals->CrntInteractor == globals->RotateGroup)))) {
1629                                 PRINT(("flinging...")) ;
1630                                 while (!XCheckWindowEvent (dpy,
1631                                                            eventWindow,
1632                                                            ButtonPressMask,
1633                                                            &ev)) {
1634                                     xlast += dx ;
1635                                     ylast += dy ;
1636                                     tdmStrokePoint (globals->CrntInteractor, xlast, ylast, INTERACTOR_BUTTON_DOWN, ev.xbutton.state) ;
1637                                 }
1638                             } else {
1639                                 /*
1640                                 * if not, behave normally.
1641                                 */
1642                                 XCheckWindowEvent (dpy, eventWindow, ButtonReleaseMask, &ev) ;
1643                                 if (ev.xbutton.x != x || ev.xbutton.y != y)
1644                                     tdmStrokePoint (globals->CrntInteractor,
1645                                                     ev.xbutton.x, ev.xbutton.y, INTERACTOR_BUTTON_UP, ev.xbutton.state) ;
1646                             }
1647                         }
1648 
1649                         _dxfSendInteractorData (globals, globals->CrntInteractor, 0) ;
1650                     }
1651                 }
1652             }
1653             break ;
1654 
1655         case VisibilityNotify:
1656             PRINT(("VisibilityNotify")) ;
1657             VISIBILITY = ev.xvisibility.state ;
1658             break ;
1659 
1660         case Expose:
1661             PRINT (("Expose")) ;
1662             doRedraw = TRUE ;
1663             break ;
1664 
1665         case EnterNotify:
1666             /* we only receive this event from 8-bit windows */
1667             PRINT (("EnterNotify")) ;
1668             XInstallColormap (dpy, CLRMAP) ;
1669             XFlush(dpy) ;
1670             break ;
1671 
1672         case LeaveNotify:
1673             /* we only receive this event from 8-bit windows */
1674             PRINT (("LeaveNotify")) ;
1675             XUninstallColormap (dpy, CLRMAP) ;
1676             XFlush(dpy) ;
1677             break ;
1678 
1679         case DestroyNotify:
1680             PRINT (("DestroyNotify")) ;
1681             if(ev.xdestroywindow.window == TOPLEVEL)
1682                 break;
1683             GL_WINDOW = FALSE;
1684             _tdmCleanupChild(globals) ;
1685             goto done ;
1686             break ;
1687 
1688         default:
1689             PRINT(("ignored event %d", ev.type)) ;
1690             break ;
1691         }
1692     }
1693 
1694     if (OBJECT_TAG != DXGetObjectTag(OBJECT) ||
1695             CAMERA_TAG != DXGetObjectTag((dxObject)CAMERA))
1696         SAVE_BUF_VALID = FALSE ;
1697 
1698 #if defined(DXD_HW_WINDOW_DESTRUCTION_CHECK)
1699 
1700     if (GL_WINDOW)
1701 #endif
1702 
1703         if (doRedraw) {
1704             /*
1705             *  If the window needs to be refreshed, lets try to do it from
1706             *  the saved buffer, or if that fails, redraw.
1707             */
1708             PRINT(("refreshing image")) ;
1709             /*
1710 #if defined(sgi)
1711             if (GL_WINDOW)
1712             zclear();
1713 #endif
1714             */
1715 #if 0
1716 
1717             if (CAMERA)
1718 #endif
1719 
1720             {
1721                 /* otherwise, redo final approximation pass */
1722                 if (! _dxfTryRestoreBuffer(LWIN))
1723                 {
1724                     PRINT(("no backing store, regenerating image"));
1725 #if 0
1726 
1727                     _tdmClearWindow(LWIN) ;
1728 #endif
1729 
1730                     if(!(_dxfDraw (globals, OBJECT, CAMERA, 1)))
1731                         goto error;
1732 
1733                     if ( _dxfTrySaveBuffer(LWIN)) {
1734                         SAVEBUFOBJECTTAG = OBJECT_TAG;
1735                         SAVEBUFCAMERATAG = CAMERA_TAG;
1736                     }
1737 
1738                     /*
1739                     *  Redraw any defined interactor echos.  The echos can't
1740                     *  be saved by _dxfTrySaveBuffer() since they are updated
1741                     *  more frequently than once per rendering pass.
1742                     */
1743 
1744                     _dxfRedrawInteractorEchos(INTERACTOR_DATA) ;
1745                 }
1746             }
1747 
1748             /* tell the UI that we're ready */
1749             /*
1750             * #X was
1751             * if ((fd == -1) && PARENT_WINDOW)
1752             */
1753             if ((fd == -1) && DXUI)
1754                 _dxfConnectUI(LWIN) ;
1755 
1756             /*
1757             XXX do we still need this ? TJM
1758             YYY I'm not sure for the UI case, but I don't think so otherwise.
1759             It causes unnecessary event looping in external UI cases.
1760             I've changed it to ONLY do it if its the DX UI.  GDA
1761             */
1762             /* hack to force client messages through immediately */
1763             if (DXUI)
1764                 _dxfSendClientMessage (dpy, XWINID, POKE_CONNECTION, 0) ;
1765         }
1766 
1767 done:
1768     if (_tdmXerror)
1769         goto error ;
1770 
1771     EXIT(("OK"));
1772     if (fd != -1)
1773         DEBUG_MARKER("_dxfProcessEvents EXIT");
1774     return OK ;
1775 
1776 error:
1777     _tdmXerror = 0 ;
1778 
1779     EXIT(("ERROR"));
1780     if (fd != -1)
1781         DEBUG_MARKER("_dxfProcessEvents EXIT");
1782     return ERROR ;
1783 }
1784 
1785 #if 0
1786 typedef struct argbS
1787 {
1788     char a, b, g, r;
1789 }
1790 argbT,*argbP;
1791 
1792 
1793 void *_dxfOutputRGB(WinP win, Field i)
1794 {
1795     DEFWINDATA(win);
1796     int x, y, n, r, g, b;
1797     int w, h;
1798     RGBColor *pixels;
1799     RGBColor *from;
1800 
1801     ENTRY(("_dxfOutputRGB(0x%x, 0x%x)", win, i));
1802 
1803     /* the next two can be static as they are only set once */
1804     /* (all subsequent child processes will merely read them) */
1805     static int firsttime = 1;
1806     static unsigned char gamma[256];
1807 
1808     if (!i) {
1809         /* no image received for rendering */
1810         DXSetError (ERROR_UNEXPECTED, "#13500" ) ;
1811         EXIT(("no image"));
1812         return NULL ;
1813     }
1814 
1815     /* increment reference count here, decrement in _dxfEndSWRenderPass() */
1816     DXReference((dxObject)i) ;
1817 
1818     if (DXGetObjectClass ((dxObject)(i)) != CLASS_FIELD) {
1819         /* invalid image received */
1820         DXSetError (ERROR_BAD_CLASS, "#13510") ;
1821         EXIT(("invalid image"));
1822         return NULL ;
1823     }
1824 
1825     if (! DXGetImageSize (i, &w, &h)) {
1826         /* could not get image size */
1827         DXSetError (ERROR_INTERNAL, "#13520");
1828         EXIT(("could not get image size"));
1829         return NULL ;
1830     }
1831 
1832     pixels = DXGetPixels(i) ;
1833     if (! pixels) {
1834         DXWarning ("#5170") ;   /* no pixels found in image */
1835         EXIT(("no pixles"));
1836         return NULL ;
1837     }
1838 
1839     n = PIXW * PIXH * sizeof(argbT);
1840     if (n != SW_BUF_SIZE) {
1841         if (SW_BUF)
1842             tdmFree(SW_BUF) ;
1843         SW_BUF = (void *) NULL;
1844         SW_BUF = (void *) tdmAllocateLocal(n);
1845         if (!SW_BUF) {
1846             SW_BUF_SIZE = 0;
1847             EXIT(("malloc failed"));
1848             return NULL;
1849         } else
1850             SW_BUF_SIZE = n;
1851     }
1852 
1853     /* create the gamma ramp */
1854     if (firsttime) {
1855         /* create the map -- code adapted from BuildXColorMap in display.c */
1856         int i;
1857 
1858         for (i=0; i<256; i++)
1859             gamma[i] = sqrt(i/256.0)*256.0;
1860         firsttime = 0;
1861     }
1862 
1863     /* work around an sgi compiler bug */
1864 #define CLAMP(p) (p=(p<0?0:p), p=(p>255?255:p))
1865 
1866     /* convert from XY to linear index */
1867 #define INDX(x,y) (y*w + x)
1868 
1869     for (y=0; y<h; y++) {
1870         from = pixels + y * w;
1871         for (x=0; x<w; x++) {
1872             /* it should be possible to simplify this, but every time I try to
1873             some of the high levels overflow and wrap to 0 */
1874             r = 255*from[x].r;
1875             g = 255*from[x].g;
1876             b = 255*from[x].b;
1877             r = gamma[CLAMP(r)];
1878             g = gamma[CLAMP(g)];
1879             b = gamma[CLAMP(b)];
1880             ((argbP) SW_BUF)[INDX(x,y)].r = CLAMP(r);
1881             ((argbP) SW_BUF)[INDX(x,y)].g = CLAMP(g);
1882             ((argbP) SW_BUF)[INDX(x,y)].b = CLAMP(b);
1883         }
1884     }
1885 
1886     /*
1887     * Mark buffer as current, and draw it.
1888     */
1889     SW_BUF_CURRENT = TRUE;
1890     _dxfSWImageDraw(win);
1891 
1892     EXIT((""));
1893 }
1894 
1895 void
1896 _dxfSWImageDraw (WinP win)
1897 {
1898     int camw, camh ;
1899     DEFWINDATA(win);
1900     DEFPORT(PORT_HANDLE);
1901 
1902     ENTRY(("_dxfSWImageDraw(0x%x)", win));
1903 
1904     _dxfChangeBufferMode (win, SingleBufferMode) ;
1905 
1906     if (CAMERA)
1907         DXGetCameraResolution (CAMERA, &camw, &camh) ;
1908     else
1909         DXGetImageSize (OBJECT, &camw, &camh) ;
1910 
1911     if (camw < PIXW)
1912         _dxf_CLEAR_AREA (PORT_CTX, camw, PIXW - 1, 0, PIXH - 1) ;
1913 
1914     if (camh < PIXH)
1915         _dxf_CLEAR_AREA (PORT_CTX, 0, PIXW - 1, 0, PIXH - (camh+1)) ;
1916 
1917     _dxf_WRITE_PRECISE_RENDERING (win, camw, camh) ;
1918 
1919     EXIT((""));
1920 }
1921 #endif
1922 
1923 void
_dxfChangeBufferMode(WinP win,int mode)1924 _dxfChangeBufferMode(WinP win, int mode)
1925 {
1926     DEFWINDATA(win);
1927     DEFPORT(PORT_HANDLE);
1928 
1929     ENTRY(("_dxfChangeBufferMode(0x%x, %d)",win,mode));
1930 
1931     if (mode == DoubleBufferMode) {
1932         if (BUFFER_MODE == SingleBufferMode) /* needs changing? */
1933         {
1934             PRINT (("single buffer -> double buffer")) ;
1935             _dxf_DOUBLE_BUFFER_MODE(PORT_CTX) ;
1936             BUFFER_MODE = DoubleBufferMode ;
1937         }
1938     } else /* mode == SingleBufferMode */
1939     {
1940         if (BUFFER_MODE == DoubleBufferMode) /* needs changing? */
1941         {
1942             /*
1943             *  If we're going from double to single buffer mode,
1944             *  clear the back buffer first to keep junk from showing
1945             *  when buffer becomes visible.
1946             */
1947 
1948             PRINT (("double buffer -> single buffer")) ;
1949             _tdmClearWindow(win) ;
1950             _dxf_SINGLE_BUFFER_MODE(PORT_CTX) ;
1951             BUFFER_MODE = SingleBufferMode ;
1952         }
1953     }
1954 
1955     EXIT((""));
1956 }
1957 
1958 
1959 static void
_tdmClearWindow(WinP win)1960 _tdmClearWindow (WinP win)
1961 {
1962     DEFWINDATA(win) ;
1963     DEFPORT(PORT_HANDLE) ;
1964 
1965     ENTRY(("_tdmClearWindow (0x%x)",win));
1966 
1967     _dxf_CLEAR_AREA (PORT_CTX, 0, PIXW - 1 , 0, PIXH - 1) ;
1968 
1969     EXIT((""));
1970 }
1971 
1972 int
_dxfTrySaveBuffer(WinP win)1973 _dxfTrySaveBuffer (WinP win)
1974 {
1975     XEvent xev ;
1976     XVisibilityEvent *xvis = (XVisibilityEvent *) &xev ;
1977     int camw, camh ;
1978     DEFWINDATA(win) ;
1979     DEFPORT(PORT_HANDLE) ;
1980 
1981     ENTRY(("_dxfTrySaveBuffer (0x%x)", win));
1982 
1983     /* loop all Visibility Events to determine visibility state */
1984     while (XCheckTypedWindowEvent (DPY, XWINID, VisibilityNotify, &xev))
1985         VISIBILITY = xvis->state ;
1986 
1987     /* if we already have a buffer, leave now */
1988     if (SAVE_BUF_VALID)
1989         goto done ;
1990 
1991     if (CAMERA) {
1992         if (! DXGetCameraResolution(CAMERA, &camw, &camh))
1993             /* unable to get camera resolution */
1994             DXErrorGoto (ERROR_DATA_INVALID, "#13530") ;
1995     } else {
1996         /* assume we have been given an image */
1997         if (! DXGetImageSize (OBJECT, &camw, &camh))
1998             /* unable to get image resolution */
1999             DXErrorGoto (ERROR_DATA_INVALID, "#13540") ;
2000     }
2001 
2002     /* read the window */
2003     if (! _dxf_READ_APPROX_BACKSTORE(win, camw, camh)) {
2004         /* can't read saveunder */
2005         DXWarning("#13550") ;
2006         SAVE_BUF_VALID = FALSE ;
2007         goto done ;
2008     }
2009 
2010     /* check to see if we are obscured */
2011     if (VISIBILITY != VisibilityUnobscured)
2012         SAVE_BUF_VALID = FALSE ;
2013     else {
2014         /* check for Exposures and invalidate result if present */
2015         if (XCheckTypedWindowEvent(DPY, XWINID, Expose, &xev)) {
2016             XPutBackEvent(DPY, &xev) ;
2017             SAVE_BUF_VALID = FALSE ;
2018             goto done ;
2019         } else
2020             SAVE_BUF_VALID = TRUE ;
2021     }
2022 
2023 
2024     /* give access to direct interactors */
2025     _dxfSetInteractorImage (INTERACTOR_DATA, camw, camh, SAVE_BUF) ;
2026 
2027     /*
2028     * In some cases the backing store may be simply filled with
2029     * black pixels (i.e. Evans and Sutherland).  In this case
2030     * we want the interactors to access this memory (previous line)
2031     * but we do not want to use the backing store for redraws.  This
2032     * is a temporary solution to E&S glReadPixel performance probs.
2033     */
2034     if (_dxf_isFlagsSet(_dxf_SERVICES_FLAGS(),
2035                         SF_INVALIDATE_BACKSTORE)) {
2036         SAVE_BUF_VALID = FALSE ;
2037     }
2038 
2039 done:
2040     if (_tdmXerror)
2041         goto error ;
2042 
2043     EXIT((""));
2044     return 1;
2045 
2046 error:
2047     _tdmXerror = 0 ;
2048 
2049     EXIT(("ERROR"));
2050     return 0;
2051 }
2052 
2053 
2054 int
_dxfTryRestoreBuffer(WinP win)2055 _dxfTryRestoreBuffer (WinP win)
2056 {
2057     int camw, camh ;
2058     DEFWINDATA(win);
2059     DEFPORT(PORT_HANDLE) ;
2060 
2061     ENTRY(("_dxfTryRestoreBuffer (0x%x)",win));
2062 
2063     /* check buffer status */
2064     if (! SAVE_BUF_VALID)
2065         goto error ;
2066 
2067     if (CAMERA) {
2068         if (! DXGetCameraResolution(CAMERA, &camw, &camh))
2069             /* unable to get camera resolution */
2070             DXErrorGoto (ERROR_DATA_INVALID, "#13530") ;
2071     } else {
2072         /* assume we have been given an image */
2073         if (! DXGetImageSize (OBJECT, &camw, &camh))
2074             /* unable to get image resolution */
2075             DXErrorGoto (ERROR_DATA_INVALID, "#13540") ;
2076     }
2077 
2078     /* check for presence of buffer and size */
2079     if (! SAVE_BUF || (SAVE_BUF_SIZE != camw * camh))
2080         goto error ;
2081 
2082     if (camw < PIXW)
2083         _dxf_CLEAR_AREA (PORT_CTX, camw, PIXW - 1, 0, PIXH - 1) ;
2084 
2085     if (camh < PIXH)
2086         _dxf_CLEAR_AREA (PORT_CTX, 0, PIXW - 1, 0, PIXH - (camh+1)) ;
2087 
2088     PRINT(("writing from backing store"));
2089     _dxf_SET_OUTPUT_WINDOW(win, XWINID);
2090     _dxf_WRITE_APPROX_BACKSTORE (win, camw, camh) ;
2091 #if defined(solaris)
2092 
2093     _dxf_SWAP_BUFFERS(PORT_CTX, XWINID);
2094 #endif
2095 
2096     /* If we restored from a (partialially) invalid buffer, make sure we
2097     * still refresh.
2098     */
2099 #if 0
2100 
2101     if (! SAVE_BUF_VALID )
2102         goto error ;
2103 #endif
2104 
2105     EXIT(("OK"));
2106     return OK ;
2107 
2108 error:
2109     _tdmXerror = 0 ;
2110 
2111     EXIT(("ERROR"));
2112     return ERROR ;
2113 }
2114 
2115 
2116 static void
_tdmCleanupChild(tdmChildGlobalP globals)2117 _tdmCleanupChild (tdmChildGlobalP globals)
2118 {
2119     DEFGLOBALDATA(globals) ;
2120 
2121     ENTRY(("_tdmCleanupChild (0x%x)", globals));
2122 
2123     if (globals->cacheId) {
2124         /*
2125         *  DXRemove cache entry for this instance.  This will cause
2126         *  _dxfEndRenderModule() to be invoked as a side effect, since it is
2127         *  registered as the callback for the cache deletion.
2128         */
2129         PRINT(("cacheId exists, deleting cache entry")) ;
2130         DXSetCacheEntry (0, CACHE_PERMANENT, globals->cacheId, 0, 0) ;
2131 
2132     }
2133 
2134     EXIT((""));
2135 }
2136 
2137 
2138 int
_dxfConvertWinName(char * winName)2139 _dxfConvertWinName(char *winName)
2140 {
2141     int i ;
2142 
2143     /* ENTRY(("_dxfConvertWinName(\"%s\")",winName)); */
2144 
2145     for (i = strlen(winName)-1 ; i >= 0 ; i--)
2146         if (!isdigit(winName[i]))
2147             break;
2148 
2149     if (i == -1) {
2150         /* no pound signs, all digits */
2151         /* EXIT(("0")); */
2152         return 0 ;
2153         /* #X was
2154         * } else if (winName[i] == '#' && (i !=0 && winName[i-1] == '#')) {
2155         */
2156     } else if ((winName[i] == '#' || winName[i] == 'X') && (i !=0 && winName[i-1] == '#')) {
2157         /* 2 pound signs */
2158         /* EXIT(("fill in this value")); */
2159         return atoi(&winName[i+1]) ;
2160     } else {
2161         /* EXIT(("0")); */
2162         return 0 ;
2163     }
2164 }
2165 
2166 /*
2167 * #X follows
2168 */
2169 int
_dxfUIType(char * winName)2170 _dxfUIType(char *winName)
2171 {
2172 
2173     int i ;
2174 
2175     for (i = strlen(winName)-1 ; i >= 0 ; i--)
2176         if (!isdigit(winName[i]))
2177             break;
2178 
2179     if (i > 0 && winName[i] == '#' && i !=0 && winName[i-1] == '#')
2180         return DXD_DXUI;
2181     else if (i > 0 && winName[i] == 'X' && i !=0 && winName[i-1] == '#')
2182         return DXD_EXTERNALUI;
2183     else
2184         return DXD_NOUI;
2185 }
2186 /* #X end */
2187 
2188 static Window
_getTopLevelShell(Display * dpy,Window w)2189 _getTopLevelShell (Display *dpy, Window w)
2190 {
2191     /*
2192     *  Find the top level shell widget by walking up the window hierarchy.
2193     *
2194     *  NOTE: This routine WILL NOT WORK if the Local allocator is not
2195     *  malloc!  It calls XQueryTree() which uses malloc to allocate the
2196     *  children array!
2197     */
2198 
2199     unsigned int numChild ;
2200     Window root, parent, *childList ;
2201 
2202     ENTRY(("_getTopLevelShell (0x%x, 0x%x)", dpy, w));
2203 
2204     while (XQueryTree (dpy, w, &root, &parent, &childList, &numChild)) {
2205         XFree((char *)childList) ;
2206 
2207         if (parent != root)
2208             w = parent ;
2209         else {
2210             EXIT(("w = 0x%x",w)) ;
2211             return w ;
2212         }
2213     }
2214 
2215     EXIT(("XQueryTree failed")) ;
2216     return 0 ;
2217 }
2218 
2219 extern Field DXMakeImageFormat(int w, int h, char *format);
2220 
2221 Field
_dxfCaptureHardwareImage(tdmChildGlobalP globals)2222 _dxfCaptureHardwareImage(tdmChildGlobalP globals)
2223 {
2224     DEFGLOBALDATA(globals) ;
2225     DEFPORT(PORT_HANDLE) ;
2226     Field image = NULL;
2227     Array colors;
2228 
2229     image = DXMakeImageFormat(PIXW, PIXH, "BYTE");
2230     if (! image)
2231         goto error;
2232 
2233     colors = (Array)DXGetComponentValue(image, "colors");
2234     if (! colors)
2235         goto error;
2236 
2237     if (! _dxf_READ_IMAGE(LWIN, DXGetArrayData(colors)))
2238         goto error;
2239 
2240     return image;
2241 
2242 error:
2243     DXDelete((dxObject)image);
2244     return NULL;
2245 }
2246 
2247 #endif /* DX_NATIVE_WINDOWS */
2248 
2249 void
_dxfSetCurrentView(WinP win,float * to,float * from,float * up,float fov,float width)2250 _dxfSetCurrentView(WinP win, float *to, float *from, float *up, float fov, float width)
2251 {
2252     DEFWINDATA(win);
2253     CURRENT_TO[0]   = to[0];
2254     CURRENT_TO[1]   = to[1];
2255     CURRENT_TO[2]   = to[2];
2256     CURRENT_FROM[0] = from[0];
2257     CURRENT_FROM[1] = from[1];
2258     CURRENT_FROM[2] = from[2];
2259     CURRENT_UP[0]   = up[0];
2260     CURRENT_UP[1]   = up[1];
2261     CURRENT_UP[2]   = up[2];
2262     CURRENT_FOV     = fov;
2263     CURRENT_WIDTH   = width;
2264 }
2265 
2266 /*
2267  *===================================================================
2268  *                END OF FILE
2269  *                $Source: /src/master/dx/src/exec/hwrender/hwWindow.c,v $
2270  *===================================================================
2271  */
2272 #undef tdmWindow_c
2273