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