gallium/draw: initial code to properly support llvm in the draw module
[mesa.git] / src / glut / os2 / glut_win.cpp
1
2 /* Copyright (c) Mark J. Kilgard, 1994, 1997. */
3
4 /* This program is freely distributable without licensing fees
5 and is provided without guarantee or warrantee expressed or
6 implied. This program is -not- in the public domain. */
7
8 #ifdef __VMS
9 #include <GL/vms_x_fix.h>
10 #endif
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <assert.h>
16 #if defined(__OS2__)
17 #define POKA 0
18 #include "WarpGL.h"
19 #include "glutos2.h"
20 #include "glutint.h"
21
22 #include "gl\os2mesa.h"
23
24 //
25 //define for resource id for main GLUT window, in samples it is defined in GL_TEST.h
26 #define ID_WINDOW 256
27
28 int evglSetPixelFormat(int iPixelFormat);
29 HPS hpsCurrent;
30
31 #elif !defined(_WIN32)
32
33 #include <X11/Xlib.h>
34 #include <X11/Xatom.h>
35 #endif
36
37 #include "glutint.h"
38
39 GLUTwindow *__glutCurrentWindow = NULL;
40 GLUTwindow **__glutWindowList = NULL;
41 int __glutWindowListSize = 0;
42 #if !defined(_WIN32) && !defined(__OS2__)
43 GLUTstale *__glutStaleWindowList = NULL;
44 #endif
45 GLUTwindow *__glutMenuWindow = NULL;
46
47 void (*__glutFreeOverlayFunc) (GLUToverlay *);
48 XVisualInfo *(*__glutDetermineVisualFromString) (char *string, Bool * treatAsSingle,
49 Criterion * requiredCriteria, int nRequired, int requiredMask, void** fbc) = NULL;
50
51 static Criterion requiredWindowCriteria[] =
52 {
53 {LEVEL, EQ, 0},
54 {TRANSPARENT, EQ, 0}
55 };
56 static int numRequiredWindowCriteria = sizeof(requiredWindowCriteria) / sizeof(Criterion);
57 static int requiredWindowCriteriaMask = (1 << LEVEL) | (1 << TRANSPARENT);
58
59 static void
60 cleanWindowWorkList(GLUTwindow * window)
61 {
62 GLUTwindow **pEntry = &__glutWindowWorkList;
63 GLUTwindow *entry = __glutWindowWorkList;
64
65 /* Tranverse singly-linked window work list look for the
66 window. */
67 while (entry) {
68 if (entry == window) {
69 /* Found it; delete it. */
70 *pEntry = entry->prevWorkWin;
71 return;
72 } else {
73 pEntry = &entry->prevWorkWin;
74 entry = *pEntry;
75 }
76 }
77 }
78
79 #if !defined(_WIN32) && !defined(__OS2PM__)
80
81 static void
82 cleanStaleWindowList(GLUTwindow * window)
83 {
84 GLUTstale **pEntry = &__glutStaleWindowList;
85 GLUTstale *entry = __glutStaleWindowList;
86
87 /* Tranverse singly-linked stale window list look for the
88 window ID. */
89 while (entry) {
90 if (entry->window == window) {
91 /* Found it; delete it. */
92 *pEntry = entry->next;
93 free(entry);
94 return;
95 } else {
96 pEntry = &entry->next;
97 entry = *pEntry;
98 }
99 }
100 }
101
102 #endif
103
104 static GLUTwindow *__glutWindowCache = NULL;
105
106 GLUTwindow *
107 __glutGetWindow(Window win)
108 {
109 int i;
110
111 /* Does win belong to the last window ID looked up? */
112 if (__glutWindowCache && (win == __glutWindowCache->win ||
113 (__glutWindowCache->overlay && win ==
114 __glutWindowCache->overlay->win))) {
115 return
116 __glutWindowCache;
117 }
118 /* Otherwise scan the window list looking for the window ID. */
119 for (i = 0; i < __glutWindowListSize; i++) {
120 if (__glutWindowList[i]) {
121 if (win == __glutWindowList[i]->win) {
122 __glutWindowCache = __glutWindowList[i];
123 return __glutWindowCache;
124 }
125 if (__glutWindowList[i]->overlay) {
126 if (win == __glutWindowList[i]->overlay->win) {
127 __glutWindowCache = __glutWindowList[i];
128 return __glutWindowCache;
129 }
130 }
131 }
132 }
133 #if !defined(_WIN32) && !defined(__OS2PM__)
134 {
135 GLUTstale *entry;
136
137 /* Scan through destroyed overlay window IDs for which no
138 DestroyNotify has yet been received. */
139 for (entry = __glutStaleWindowList; entry; entry = entry->next) {
140 if (entry->win == win)
141 return entry->window;
142 }
143 }
144 #endif
145 return NULL;
146 }
147
148 /* CENTRY */
149 int GLUTAPIENTRY
150 glutGetWindow(void)
151 {
152 if (__glutCurrentWindow) {
153 return __glutCurrentWindow->num + 1;
154 } else {
155 return 0;
156 }
157 }
158 /* ENDCENTRY */
159
160 void
161 __glutSetWindow(GLUTwindow * window)
162 {
163 /* It is tempting to try to short-circuit the call to
164 glXMakeCurrent if we "know" we are going to make current
165 to a window we are already current to. In fact, this
166 assumption breaks when GLUT is expected to integrated with
167 other OpenGL windowing APIs that also make current to
168 OpenGL contexts. Since glXMakeCurrent short-circuits the
169 "already bound" case, GLUT avoids the temptation to do so
170 too. */
171 __glutCurrentWindow = window;
172
173 MAKE_CURRENT_LAYER(__glutCurrentWindow);
174
175 #if !defined(_WIN32) && !defined(__OS2__)
176 /* We should be careful to force a finish between each
177 iteration through the GLUT main loop if indirect OpenGL
178 contexts are in use; indirect contexts tend to have much
179 longer latency because lots of OpenGL extension requests
180 can queue up in the X protocol stream. We accomplish this
181 by posting GLUT_FINISH_WORK to be done. */
182 if (!__glutCurrentWindow->isDirect)
183 __glutPutOnWorkList(__glutCurrentWindow, GLUT_FINISH_WORK);
184 #endif
185
186 /* If debugging is enabled, we'll want to check this window
187 for any OpenGL errors every iteration through the GLUT
188 main loop. To accomplish this, we post the
189 GLUT_DEBUG_WORK to be done on this window. */
190 if (__glutDebug) {
191 __glutPutOnWorkList(__glutCurrentWindow, GLUT_DEBUG_WORK);
192 }
193 }
194
195 /* CENTRY */
196 void GLUTAPIENTRY
197 glutSetWindow(int win)
198 {
199 GLUTwindow *window;
200
201 if (win < 1 || win > __glutWindowListSize) {
202 __glutWarning("glutSetWindow attempted on bogus window.");
203 return;
204 }
205 window = __glutWindowList[win - 1];
206 if (!window) {
207 __glutWarning("glutSetWindow attempted on bogus window.");
208 return;
209 }
210 __glutSetWindow(window);
211 }
212 /* ENDCENTRY */
213
214 static int
215 getUnusedWindowSlot(void)
216 {
217 int i;
218
219 /* Look for allocated, unused slot. */
220 for (i = 0; i < __glutWindowListSize; i++) {
221 if (!__glutWindowList[i]) {
222 return i;
223 }
224 }
225 /* Allocate a new slot. */
226 __glutWindowListSize++;
227 if (__glutWindowList) {
228 __glutWindowList = (GLUTwindow **)
229 realloc(__glutWindowList,
230 __glutWindowListSize * sizeof(GLUTwindow *));
231 } else {
232 /* XXX Some realloc's do not correctly perform a malloc
233 when asked to perform a realloc on a NULL pointer,
234 though the ANSI C library spec requires this. */
235 __glutWindowList = (GLUTwindow **)
236 malloc(sizeof(GLUTwindow *));
237 }
238 if (!__glutWindowList)
239 __glutFatalError("out of memory.");
240 __glutWindowList[__glutWindowListSize - 1] = NULL;
241 return __glutWindowListSize - 1;
242 }
243
244 static XVisualInfo *
245 getVisualInfoCI(unsigned int mode)
246 {
247 #if POKA
248 static int bufSizeList[] =
249 {16, 12, 8, 4, 2, 1, 0};
250 XVisualInfo *vi;
251 int list[32];
252 int i, n = 0;
253
254 /* Should not be looking at display mode mask if
255 __glutDisplayString is non-NULL. */
256 assert(!__glutDisplayString);
257
258 list[n++] = GLX_BUFFER_SIZE;
259 list[n++] = 1;
260 if (GLUT_WIND_IS_DOUBLE(mode)) {
261 list[n++] = GLX_DOUBLEBUFFER;
262 }
263 if (GLUT_WIND_IS_STEREO(mode)) {
264 list[n++] = GLX_STEREO;
265 }
266 if (GLUT_WIND_HAS_DEPTH(mode)) {
267 list[n++] = GLX_DEPTH_SIZE;
268 list[n++] = 1;
269 }
270 if (GLUT_WIND_HAS_STENCIL(mode)) {
271 list[n++] = GLX_STENCIL_SIZE;
272 list[n++] = 1;
273 }
274 list[n] = (int) None; /* terminate list */
275
276 /* glXChooseVisual specify GLX_BUFFER_SIZE prefers the
277 "smallest index buffer of at least the specified size".
278 This would be reasonable if GLUT allowed the user to
279 specify the required buffe size, but GLUT's display mode
280 is too simplistic (easy to use?). GLUT should try to find
281 the "largest". So start with a large buffer size and
282 shrink until we find a matching one that exists. */
283
284 for (i = 0; bufSizeList[i]; i++) {
285 /* XXX Assumes list[1] is where GLX_BUFFER_SIZE parameter
286 is. */
287 list[1] = bufSizeList[i];
288 vi = glXChooseVisual(__glutDisplay,
289 __glutScreen, list);
290 if (vi)
291 return vi;
292 }
293 return NULL;
294 #else
295 return
296 glXChooseVisual(mode);
297
298 #endif
299 }
300
301 static XVisualInfo *
302 getVisualInfoRGB(unsigned int mode)
303 {
304 #if POKA
305 int list[32];
306 int n = 0;
307
308 /* Should not be looking at display mode mask if
309 __glutDisplayString is non-NULL. */
310 assert(!__glutDisplayString);
311
312 /* XXX Would a caching mechanism to minize the calls to
313 glXChooseVisual? You'd have to reference count
314 XVisualInfo* pointers. Would also have to properly
315 interact with glutInitDisplayString. */
316
317 list[n++] = GLX_RGBA;
318 list[n++] = GLX_RED_SIZE;
319 list[n++] = 1;
320 list[n++] = GLX_GREEN_SIZE;
321 list[n++] = 1;
322 list[n++] = GLX_BLUE_SIZE;
323 list[n++] = 1;
324 if (GLUT_WIND_HAS_ALPHA(mode)) {
325 list[n++] = GLX_ALPHA_SIZE;
326 list[n++] = 1;
327 }
328 if (GLUT_WIND_IS_DOUBLE(mode)) {
329 list[n++] = GLX_DOUBLEBUFFER;
330 }
331 if (GLUT_WIND_IS_STEREO(mode)) {
332 list[n++] = GLX_STEREO;
333 }
334 if (GLUT_WIND_HAS_DEPTH(mode)) {
335 list[n++] = GLX_DEPTH_SIZE;
336 list[n++] = 1;
337 }
338 if (GLUT_WIND_HAS_STENCIL(mode)) {
339 list[n++] = GLX_STENCIL_SIZE;
340 list[n++] = 1;
341 }
342 if (GLUT_WIND_HAS_ACCUM(mode)) {
343 list[n++] = GLX_ACCUM_RED_SIZE;
344 list[n++] = 1;
345 list[n++] = GLX_ACCUM_GREEN_SIZE;
346 list[n++] = 1;
347 list[n++] = GLX_ACCUM_BLUE_SIZE;
348 list[n++] = 1;
349 if (GLUT_WIND_HAS_ALPHA(mode)) {
350 list[n++] = GLX_ACCUM_ALPHA_SIZE;
351 list[n++] = 1;
352 }
353 }
354 #if defined(GLX_VERSION_1_1) && (defined(GLX_SGIS_multisample) || defined(GLX_ARB_multisample))
355 if (GLUT_WIND_IS_MULTISAMPLE(mode)) {
356 if (!__glutIsSupportedByGLX("GLX_SGIS_multisample") &&
357 !__glutIsSupportedByGLX("GLX_ARB_multisample"))
358 return NULL;
359 #if defined(GLX_ARB_multisample)
360 list[n++] = GLX_SAMPLES_ARB;
361 #elif defined(GLX_SGIS_multisample)
362 list[n++] = GLX_SAMPLES_SGIS;
363 #endif
364 /* XXX Is 4 a reasonable minimum acceptable number of
365 samples? */
366 list[n++] = 4;
367 }
368 #endif
369 list[n] = (int) None; /* terminate list */
370
371 return glXChooseVisual(__glutDisplay,
372 __glutScreen, list);
373 #else /* POKA */
374
375 return
376 glXChooseVisual(mode);
377
378 #endif
379 }
380
381 XVisualInfo *
382 __glutGetVisualInfo(unsigned int mode)
383 {
384 /* XXX GLUT_LUMINANCE not implemented for GLUT 3.0. */
385 if (GLUT_WIND_IS_LUMINANCE(mode))
386 return NULL;
387
388 if (GLUT_WIND_IS_RGB(mode))
389 return getVisualInfoRGB(mode);
390 else
391 return getVisualInfoCI(mode);
392 }
393
394 XVisualInfo *
395 __glutDetermineVisual(
396 unsigned int displayMode,
397 Bool * treatAsSingle,
398 XVisualInfo * (getVisualInfo) (unsigned int))
399 {
400 XVisualInfo *vis;
401
402 /* Should not be looking at display mode mask if
403 __glutDisplayString is non-NULL. */
404 assert(!__glutDisplayString);
405
406 *treatAsSingle = GLUT_WIND_IS_SINGLE(displayMode);
407 vis = getVisualInfo(displayMode);
408 if (!vis) {
409 /* Fallback cases when can't get exactly what was asked
410 for... */
411 if (GLUT_WIND_IS_SINGLE(displayMode)) {
412 /* If we can't find a single buffered visual, try looking
413 for a double buffered visual. We can treat a double
414 buffered visual as a single buffer visual by changing
415 the draw buffer to GL_FRONT and treating any swap
416 buffers as no-ops. */
417 displayMode |= GLUT_DOUBLE;
418 vis = getVisualInfo(displayMode);
419 *treatAsSingle = True;
420 }
421 if (!vis && GLUT_WIND_IS_MULTISAMPLE(displayMode)) {
422 /* If we can't seem to get multisampling (ie, not Reality
423 Engine class graphics!), go without multisampling. It
424 is up to the application to query how many multisamples
425 were allocated (0 equals no multisampling) if the
426 application is going to use multisampling for more than
427 just antialiasing. */
428 displayMode &= ~GLUT_MULTISAMPLE;
429 vis = getVisualInfo(displayMode);
430 }
431 }
432 return vis;
433 }
434
435 static void GLUTCALLBACK
436 __glutDefaultDisplay(void)
437 {
438 /* XXX Remove the warning after GLUT 3.0. */
439 __glutWarning("The following is a new check for GLUT 3.0; update your code.");
440 __glutFatalError(
441 "redisplay needed for window %d, but no display callback.",
442 __glutCurrentWindow->num + 1);
443 }
444
445 void GLUTCALLBACK
446 __glutDefaultReshape(int width, int height)
447 {
448 GLUToverlay *overlay;
449
450 /* Adjust the viewport of the window (and overlay if one
451 exists). */
452 MAKE_CURRENT_WINDOW(__glutCurrentWindow);
453 glViewport(0, 0, (GLsizei) width, (GLsizei) height);
454 overlay = __glutCurrentWindow->overlay;
455 if (overlay) {
456 MAKE_CURRENT_OVERLAY(overlay);
457 glViewport(0, 0, (GLsizei) width, (GLsizei) height);
458 }
459 /* Make sure we are current to the current layer (application
460 should be able to count on the current layer not changing
461 unless the application explicitly calls glutUseLayer). */
462 MAKE_CURRENT_LAYER(__glutCurrentWindow);
463 }
464
465 XVisualInfo *
466 __glutDetermineWindowVisual(Bool * treatAsSingle, Bool * visAlloced, void **fbc)
467 {
468 if (__glutDisplayString) {
469
470 /* __glutDisplayString should be NULL except if
471 glutInitDisplayString has been called to register a
472 different display string. Calling glutInitDisplayString
473 means using a string instead of an integer mask determine
474 the visual to use. Using the function pointer variable
475 __glutDetermineVisualFromString below avoids linking in
476 the code for implementing glutInitDisplayString (ie,
477 glut_dstr.o) unless glutInitDisplayString gets called by
478 the application. */
479
480 assert(__glutDetermineVisualFromString);
481 *visAlloced = False;
482 *fbc = NULL;
483 return __glutDetermineVisualFromString(__glutDisplayString, treatAsSingle,
484 requiredWindowCriteria, numRequiredWindowCriteria, requiredWindowCriteriaMask, fbc);
485 } else {
486 *visAlloced = True;
487 *fbc = NULL;
488 return __glutDetermineVisual(__glutDisplayMode,
489 treatAsSingle, __glutGetVisualInfo);
490 }
491 }
492
493 /* ARGSUSED5 */ /* Only Win32 uses gameMode parameter. */
494 GLUTwindow *
495 __glutCreateWindow(GLUTwindow * parent,
496 int x, int y, int width, int height, int gameMode)
497 {
498 GLUTwindow *window;
499 XSetWindowAttributes wa;
500 unsigned long attribMask;
501 int winnum;
502 int i;
503 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
504 GLXFBConfigSGIX fbc;
505 #else
506 void *fbc;
507 #endif
508
509 #if defined(__OS2PM__)
510 {
511 extern HAB hab; /* PM anchor block handle */
512 CLASSINFO classinfo;
513
514 if(!WinQueryClassInfo(hab,"GLUT", &classinfo) )
515 __glutOpenOS2Connection(NULL);
516 }
517 #elif defined(_WIN32)
518 WNDCLASS wc;
519 int style;
520
521 if (!GetClassInfo(GetModuleHandle(NULL), "GLUT", &wc)) {
522 __glutOpenWin32Connection(NULL);
523 }
524 #else
525 if (!__glutDisplay) {
526 __glutOpenXConnection(NULL);
527 }
528 #endif
529
530 #ifndef __OS2PM__
531 if (__glutGameModeWindow) {
532 __glutFatalError("cannot create windows in game mode.");
533 }
534 #endif
535
536 winnum = getUnusedWindowSlot();
537 window = (GLUTwindow *) malloc(sizeof(GLUTwindow));
538 if (!window) {
539 __glutFatalError("out of memory.");
540 }
541 window->num = winnum;
542
543 #if defined(__OS2PM__)
544 /* Add this new window to the window list. */
545 __glutWindowList[winnum] = window;
546 window->shownState = -1;
547 #endif
548
549 #if !defined(_WIN32) && !defined(__OS2PM__)
550 window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
551 &window->visAlloced, (void**) &fbc);
552 if (!window->vis) {
553 __glutFatalError(
554 "visual with necessary capabilities not found.");
555 }
556 __glutSetupColormap(window->vis, &window->colormap, &window->cmap);
557 #endif
558 window->eventMask = StructureNotifyMask | ExposureMask;
559
560 attribMask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
561 wa.background_pixmap = None;
562 wa.border_pixel = 0;
563 wa.colormap = window->cmap;
564 wa.event_mask = window->eventMask;
565 if (parent) {
566 if (parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK)
567 wa.event_mask |= GLUT_HACK_STOP_PROPAGATE_MASK;
568 attribMask |= CWDontPropagate;
569 wa.do_not_propagate_mask = parent->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK;
570 } else {
571 wa.do_not_propagate_mask = 0;
572 }
573
574 /* Stash width and height before Win32's __glutAdjustCoords
575 possibly overwrites the values. */
576 window->width = width;
577 window->height = height;
578 window->forceReshape = True;
579 window->ignoreKeyRepeat = False;
580
581 #if defined(__OS2PM__)
582
583 { ULONG flStyle=0;
584 int ii;
585 ERRORID erridErrorCode;/* last error id code */
586 extern HAB hab; /* PM anchor block handle */
587
588 if (parent) {
589 flStyle = WS_CLIPCHILDREN|WS_VISIBLE;
590 } else {
591 if (gameMode) {
592 /* Game mode window should be a WS_POPUP window to
593 ensure that the taskbar is hidden by it. A standard
594 WS_OVERLAPPEDWINDOW does not hide the task bar. */
595 flStyle = FCF_STANDARD | WS_MAXIMIZED;
596 } else {
597 /* A standard toplevel window with borders and such. */
598 flStyle = FCF_STANDARD | WS_CLIPCHILDREN;
599 // flStyle = WS_OVERLAPPEDWINDOW;
600 }
601 }
602 {
603 HWND hwnd; /* Window */
604 ULONG ListBoxId; /* Window id */
605 /* (supplied by application) */
606
607
608 HWND hwndClient; /* handle to the client */
609 HWND hwndFrame; /* handle to the frame */
610 PFNWP GenericWndProc;
611 FRAMECDATA fcd;
612 RECTL rect; /* Boundary rectangle */
613
614
615
616 /************************************************/
617 // flCreate = (FCF_STANDARD) & ~FCF_TASKLIST;
618 /**********************************/
619 if (parent)
620 { window->frame = NULL;
621
622 hwnd = WinCreateWindow(parent->win, /* Parent window */
623 "GLUTCHILD", /* Class name */
624 "", /* Window text */
625 flStyle, /* Window style */
626 x, y, /* Position (x,y) */
627 width, height, /* Size (width,height) */
628 parent->win, /* Owner window */
629 HWND_TOP, /* Sibling window */
630 0, /* Window id */
631 NULL, /* Control data */
632 NULL); /* Pres parameters */
633
634 erridErrorCode = WinGetLastError(hab);
635 window->win = hwnd;
636
637 window->hdc = WinOpenWindowDC(window->win);
638 window->hpsBuffer = hpsCurrent;
639
640
641 rect.xLeft = x;
642 rect.xRight = x+width;
643 rect.yBottom = y;
644 rect.yTop = y + height;
645
646 /***** else parent *****************************/
647 } else {
648 hwnd = WinCreateStdWindow(HWND_DESKTOP,
649 0, /* WS_VISIBLE frame-window style */
650 &flStyle, /* window style */
651 "GLUT", /* class name */
652 "GLUT",/* window title */
653 0L, /* default client style */
654 NULLHANDLE, /* resource in executable file */
655 ID_WINDOW, /* resource id */
656 &hwndClient); /* receives client window handle */
657
658 erridErrorCode = WinGetLastError(hab);
659 window->win = hwndClient;
660 window->frame = hwnd;
661 window->hdc = WinOpenWindowDC(window->win);
662
663 window->hpsBuffer = hpsCurrent;
664
665
666 /* converts a client window's boundaries into an equivalent frame rectangle */
667 rect.xLeft = x;
668 rect.xRight = x+width;
669 rect.yBottom = y;
670 rect.yTop = y + height;
671
672 /* calculate equivalent frame boundary from boundary data */
673 WinCalcFrameRect(window->frame, &rect, FALSE);
674 }
675 /***** endof if(parent) *****************************/
676
677 /* Must set the XHDC for fake glXChooseVisual & fake
678 glXCreateContext & fake XAllocColorCells. */
679 XHDC = window->hdc;
680 XHWND = window->win;
681 window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
682 &window->visAlloced, &fbc);
683 if (!window->vis)
684 { __glutFatalError(
685 "pixel format with necessary capabilities not found.");
686 }
687 { int rc;
688 rc = wglChoosePixelFormat(window->hdc, window->vis),
689
690 // evglSetPixelFormat(2); /* int iPixelFormat 1 - doublebuffer/2 - single buffer ??*/
691 wglSetPixelFormat(window->hdc,rc,window->vis);
692 }
693 __glutSetupColormap(window->vis, &window->colormap, &window->cmap);
694
695 window->ctx = glXCreateContext(window->hpsBuffer, window->vis,
696 None, __glutTryDirect);
697
698 WinSetWindowPos(hwnd,
699 HWND_TOP,rect.xLeft,rect.yBottom,
700 rect.xRight-rect.xLeft, rect.yTop-rect.yBottom,
701 SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW|SWP_ZORDER); /* flags*/
702
703 /* Make sure subwindows get a windowStatus callback. */
704 if (parent)
705 WinPostMsg(parent->win, WM_ACTIVATE, 0, 0);
706
707 }
708 }
709
710 #elif defined(_WIN32)
711
712 __glutAdjustCoords(parent ? parent->win : NULL,
713 &x, &y, &width, &height);
714 if (parent) {
715 style = WS_CHILD;
716 } else {
717 if (gameMode) {
718 /* Game mode window should be a WS_POPUP window to
719 ensure that the taskbar is hidden by it. A standard
720 WS_OVERLAPPEDWINDOW does not hide the task bar. */
721 style = WS_POPUP | WS_MAXIMIZE;
722 } else {
723 /* A standard toplevel window with borders and such. */
724 style = WS_OVERLAPPEDWINDOW;
725 }
726 }
727 window->win = CreateWindow("GLUT", "GLUT",
728 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
729 x, y, width, height, parent ? parent->win : __glutRoot,
730 NULL, GetModuleHandle(NULL), 0);
731 window->hdc = GetDC(window->win);
732 /* Must set the XHDC for fake glXChooseVisual & fake
733 glXCreateContext & fake XAllocColorCells. */
734 XHDC = window->hdc;
735 window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
736 &window->visAlloced, &fbc);
737 if (!window->vis) {
738 __glutFatalError(
739 "pixel format with necessary capabilities not found.");
740 }
741 if (!SetPixelFormat(window->hdc,
742 ChoosePixelFormat(window->hdc, window->vis),
743 window->vis)) {
744 __glutFatalError("SetPixelFormat failed during window create.");
745 }
746 __glutSetupColormap(window->vis, &window->colormap, &window->cmap);
747 /* Make sure subwindows get a windowStatus callback. */
748 if (parent) {
749 PostMessage(parent->win, WM_ACTIVATE, 0, 0);
750 }
751 window->renderDc = window->hdc;
752 #else
753 window->win = XCreateWindow(__glutDisplay,
754 parent == NULL ? __glutRoot : parent->win,
755 x, y, width, height, 0,
756 window->vis->depth, InputOutput, window->vis->visual,
757 attribMask, &wa);
758 #endif
759 window->renderWin = window->win;
760 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
761 if (fbc) {
762 window->ctx = __glut_glXCreateContextWithConfigSGIX(__glutDisplay, fbc,
763 GLX_RGBA_TYPE_SGIX, None, __glutTryDirect);
764 } else
765 #endif
766 #if defined(__OS2PM__)
767 // window->ctx = glXCreateContext(window->hpsBuffer, window->vis,
768 // None, __glutTryDirect);
769 #else
770 window->ctx = glXCreateContext(__glutDisplay, window->vis,
771 None, __glutTryDirect);
772 #endif
773 if (!window->ctx) {
774 __glutFatalError(
775 "failed to create OpenGL rendering context.");
776 }
777 window->renderCtx = window->ctx;
778 #if !defined(_WIN32) && !defined(__OS2PM__)
779 window->isDirect = glXIsDirect(__glutDisplay, window->ctx);
780 if (__glutForceDirect) {
781 if (!window->isDirect)
782 __glutFatalError("direct rendering not possible.");
783 }
784 #endif
785
786 window->parent = parent;
787 if (parent) {
788 window->siblings = parent->children;
789 parent->children = window;
790 } else {
791 window->siblings = NULL;
792 }
793 window->overlay = NULL;
794 window->children = NULL;
795 window->display = __glutDefaultDisplay;
796 window->reshape = __glutDefaultReshape;
797 window->mouse = NULL;
798 window->motion = NULL;
799 window->passive = NULL;
800 window->entry = NULL;
801 window->keyboard = NULL;
802 window->keyboardUp = NULL;
803 window->windowStatus = NULL;
804 window->visibility = NULL;
805 window->special = NULL;
806 window->specialUp = NULL;
807 window->buttonBox = NULL;
808 window->dials = NULL;
809 window->spaceMotion = NULL;
810 window->spaceRotate = NULL;
811 window->spaceButton = NULL;
812 window->tabletMotion = NULL;
813 window->tabletButton = NULL;
814 #ifdef _WIN32
815 window->joystick = NULL;
816 window->joyPollInterval = 0;
817 #endif
818
819 #if defined(__OS2PM__)
820 window->wm_command = NULL;
821 #endif
822
823 window->tabletPos[0] = -1;
824 window->tabletPos[1] = -1;
825 #if defined(__OS2PM__)
826 if(window->shownState == -1)
827 window->shownState = 0;
828 window->visState = window->shownState;
829 #else
830 window->shownState = 0;
831 window->visState = -1; /* not VisibilityUnobscured,
832 VisibilityPartiallyObscured, or
833 VisibilityFullyObscured */
834 #endif
835 window->entryState = -1; /* not EnterNotify or LeaveNotify */
836
837 window->desiredConfMask = 0;
838 window->buttonUses = 0;
839 window->cursor = GLUT_CURSOR_INHERIT;
840
841 /* Setup window to be mapped when glutMainLoop starts. */
842 window->workMask = GLUT_MAP_WORK;
843 #ifdef _WIN32
844 if (gameMode) {
845 /* When mapping a game mode window, just show
846 the window. We have already created the game
847 mode window with a maximize flag at creation
848 time. Doing a ShowWindow(window->win, SW_SHOWNORMAL)
849 would be wrong for a game mode window since it
850 would unmaximize the window. */
851 window->desiredMapState = GameModeState;
852 } else {
853 window->desiredMapState = NormalState;
854 }
855 #else
856 window->desiredMapState = NormalState;
857 #endif
858 window->prevWorkWin = __glutWindowWorkList;
859 __glutWindowWorkList = window;
860
861 /* Initially, no menus attached. */
862 for (i = 0; i < GLUT_MAX_MENUS; i++) {
863 window->menu[i] = 0;
864 }
865
866 /* Add this new window to the window list. */
867 __glutWindowList[winnum] = window;
868
869 /* Make the new window the current window. */
870 __glutSetWindow(window);
871
872 __glutDetermineMesaSwapHackSupport();
873
874 if (window->treatAsSingle) {
875 /* We do this because either the window really is single
876 buffered (in which case this is redundant, but harmless,
877 because this is the initial single-buffered context
878 state); or we are treating a double buffered window as a
879 single-buffered window because the system does not appear
880 to export any suitable single- buffered visuals (in which
881 the following are necessary). */
882 glDrawBuffer(GL_FRONT);
883 glReadBuffer(GL_FRONT);
884 }
885 return window;
886 }
887
888 /* CENTRY */
889 int GLUTAPIENTRY
890 glutCreateWindow(const char *title)
891 {
892 static int firstWindow = 1;
893 GLUTwindow *window;
894 #if !defined(_WIN32) && !defined(__OS2__)
895 XWMHints *wmHints;
896 #endif
897 Window win;
898 XTextProperty textprop;
899
900 if (__glutGameModeWindow) {
901 __glutFatalError("cannot create windows in game mode.");
902 }
903 window = __glutCreateWindow(NULL,
904 __glutSizeHints.x, __glutSizeHints.y,
905 __glutInitWidth, __glutInitHeight,
906 /* not game mode */ 0);
907 win = window->win;
908 /* Setup ICCCM properties. */
909 textprop.value = (unsigned char *) title;
910 textprop.encoding = XA_STRING;
911 textprop.format = 8;
912 textprop.nitems = strlen(title);
913 #if defined(__OS2__)
914 WinSetWindowText(window->frame, (PCSZ)title);
915 if (__glutIconic) {
916 window->desiredMapState = IconicState;
917 }
918 #elif defined(_WIN32)
919 SetWindowText(win, title);
920 if (__glutIconic) {
921 window->desiredMapState = IconicState;
922 }
923 #else
924 wmHints = XAllocWMHints();
925 wmHints->initial_state =
926 __glutIconic ? IconicState : NormalState;
927 wmHints->flags = StateHint;
928 XSetWMProperties(__glutDisplay, win, &textprop, &textprop,
929 /* Only put WM_COMMAND property on first window. */
930 firstWindow ? __glutArgv : NULL,
931 firstWindow ? __glutArgc : 0,
932 &__glutSizeHints, wmHints, NULL);
933 XFree(wmHints);
934 XSetWMProtocols(__glutDisplay, win, &__glutWMDeleteWindow, 1);
935 #endif
936 firstWindow = 0;
937 return window->num + 1;
938 }
939
940 #ifdef _WIN32
941 int GLUTAPIENTRY
942 __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int))
943 {
944 __glutExitFunc = exitfunc;
945 return glutCreateWindow(title);
946 }
947 #endif
948
949 int GLUTAPIENTRY
950 glutCreateSubWindow(int win, int x, int y, int width, int height)
951 {
952 GLUTwindow *window;
953
954 window = __glutCreateWindow(__glutWindowList[win - 1],
955 x, y, width, height, /* not game mode */ 0);
956 #if !defined(_WIN32) && !defined(__OS2__)
957 {
958 GLUTwindow *toplevel;
959
960 toplevel = __glutToplevelOf(window);
961 if (toplevel->cmap != window->cmap) {
962 __glutPutOnWorkList(toplevel, GLUT_COLORMAP_WORK);
963 }
964 }
965 #endif
966 return window->num + 1;
967 }
968 /* ENDCENTRY */
969
970 void
971 __glutDestroyWindow(GLUTwindow * window,
972 GLUTwindow * initialWindow)
973 {
974 GLUTwindow **prev, *cur, *parent, *siblings;
975
976 /* Recursively destroy any children. */
977 cur = window->children;
978 while (cur) {
979 siblings = cur->siblings;
980 __glutDestroyWindow(cur, initialWindow);
981 cur = siblings;
982 }
983 /* Remove from parent's children list (only necessary for
984 non-initial windows and subwindows!). */
985 parent = window->parent;
986 if (parent && parent == initialWindow->parent) {
987 prev = &parent->children;
988 cur = parent->children;
989 while (cur) {
990 if (cur == window) {
991 *prev = cur->siblings;
992 break;
993 }
994 prev = &(cur->siblings);
995 cur = cur->siblings;
996 }
997 }
998 /* Unbind if bound to this window. */
999 if (window == __glutCurrentWindow) {
1000 UNMAKE_CURRENT();
1001 __glutCurrentWindow = NULL;
1002 }
1003 /* Begin tearing down window itself. */
1004 if (window->overlay) {
1005 __glutFreeOverlayFunc(window->overlay);
1006 }
1007 XDestroyWindow(__glutDisplay, window->win);
1008 glXDestroyContext(__glutDisplay, window->ctx);
1009 if (window->colormap) {
1010 /* Only color index windows have colormap data structure. */
1011 __glutFreeColormap(window->colormap);
1012 }
1013 /* NULLing the __glutWindowList helps detect is a window
1014 instance has been destroyed, given a window number. */
1015 __glutWindowList[window->num] = NULL;
1016
1017 /* Cleanup data structures that might contain window. */
1018 cleanWindowWorkList(window);
1019 #if !defined(_WIN32) && !defined(__OS2__)
1020 cleanStaleWindowList(window);
1021 #endif
1022 /* Remove window from the "get window cache" if it is there. */
1023 if (__glutWindowCache == window)
1024 __glutWindowCache = NULL;
1025
1026 if (window->visAlloced) {
1027 /* Only free XVisualInfo* gotten from glXChooseVisual. */
1028 XFree(window->vis);
1029 }
1030
1031 if (window == __glutGameModeWindow) {
1032 /* Destroying the game mode window should implicitly
1033 have GLUT leave game mode. */
1034 __glutCloseDownGameMode();
1035 }
1036
1037 free(window);
1038 }
1039
1040 /* CENTRY */
1041 void GLUTAPIENTRY
1042 glutDestroyWindow(int win)
1043 {
1044 GLUTwindow *window = __glutWindowList[win - 1];
1045
1046 if (__glutMappedMenu && __glutMenuWindow == window) {
1047 __glutFatalUsage("destroying menu window not allowed while menus in use");
1048 }
1049 #if !defined(_WIN32) && !defined(__OS2__)
1050 /* If not a toplevel window... */
1051 if (window->parent) {
1052 /* Destroying subwindows may change colormap requirements;
1053 recalculate toplevel window's WM_COLORMAP_WINDOWS
1054 property. */
1055 __glutPutOnWorkList(__glutToplevelOf(window->parent),
1056 GLUT_COLORMAP_WORK);
1057 }
1058 #endif
1059 __glutDestroyWindow(window, window);
1060 XFlush(__glutDisplay);
1061 }
1062 /* ENDCENTRY */
1063
1064 void
1065 __glutChangeWindowEventMask(long eventMask, Bool add)
1066 {
1067 if (add) {
1068 /* Add eventMask to window's event mask. */
1069 if ((__glutCurrentWindow->eventMask & eventMask) !=
1070 eventMask) {
1071 __glutCurrentWindow->eventMask |= eventMask;
1072 __glutPutOnWorkList(__glutCurrentWindow,
1073 GLUT_EVENT_MASK_WORK);
1074 }
1075 } else {
1076 /* Remove eventMask from window's event mask. */
1077 if (__glutCurrentWindow->eventMask & eventMask) {
1078 __glutCurrentWindow->eventMask &= ~eventMask;
1079 __glutPutOnWorkList(__glutCurrentWindow,
1080 GLUT_EVENT_MASK_WORK);
1081 }
1082 }
1083 }
1084
1085 void GLUTAPIENTRY
1086 glutDisplayFunc(GLUTdisplayCB displayFunc)
1087 {
1088 /* XXX Remove the warning after GLUT 3.0. */
1089 if (!displayFunc)
1090 __glutFatalError("NULL display callback not allowed in GLUT 3.0; update your code.");
1091 __glutCurrentWindow->display = displayFunc;
1092 }
1093
1094 void GLUTAPIENTRY
1095 glutMouseFunc(GLUTmouseCB mouseFunc)
1096 {
1097 if (__glutCurrentWindow->mouse) {
1098 if (!mouseFunc) {
1099 /* Previous mouseFunc being disabled. */
1100 __glutCurrentWindow->buttonUses--;
1101 __glutChangeWindowEventMask(
1102 ButtonPressMask | ButtonReleaseMask,
1103 __glutCurrentWindow->buttonUses > 0);
1104 }
1105 } else {
1106 if (mouseFunc) {
1107 /* Previously no mouseFunc, new one being installed. */
1108 __glutCurrentWindow->buttonUses++;
1109 __glutChangeWindowEventMask(
1110 ButtonPressMask | ButtonReleaseMask, True);
1111 }
1112 }
1113 __glutCurrentWindow->mouse = mouseFunc;
1114 }
1115
1116 void GLUTAPIENTRY
1117 glutMotionFunc(GLUTmotionCB motionFunc)
1118 {
1119 /* Hack. Some window managers (4Dwm by default) will mask
1120 motion events if the client is not selecting for button
1121 press and release events. So we select for press and
1122 release events too (being careful to use reference
1123 counting). */
1124 if (__glutCurrentWindow->motion) {
1125 if (!motionFunc) {
1126 /* previous mouseFunc being disabled */
1127 __glutCurrentWindow->buttonUses--;
1128 __glutChangeWindowEventMask(
1129 ButtonPressMask | ButtonReleaseMask,
1130 __glutCurrentWindow->buttonUses > 0);
1131 }
1132 } else {
1133 if (motionFunc) {
1134 /* Previously no mouseFunc, new one being installed. */
1135 __glutCurrentWindow->buttonUses++;
1136 __glutChangeWindowEventMask(
1137 ButtonPressMask | ButtonReleaseMask, True);
1138 }
1139 }
1140 /* Real work of selecting for passive mouse motion. */
1141 __glutChangeWindowEventMask(
1142 Button1MotionMask | Button2MotionMask | Button3MotionMask,
1143 motionFunc != NULL);
1144 __glutCurrentWindow->motion = motionFunc;
1145 }
1146
1147 void GLUTAPIENTRY
1148 glutPassiveMotionFunc(GLUTpassiveCB passiveMotionFunc)
1149 {
1150 __glutChangeWindowEventMask(PointerMotionMask,
1151 passiveMotionFunc != NULL);
1152
1153 /* Passive motion also requires watching enters and leaves so
1154 that a fake passive motion event can be generated on an
1155 enter. */
1156 __glutChangeWindowEventMask(EnterWindowMask | LeaveWindowMask,
1157 __glutCurrentWindow->entry != NULL || passiveMotionFunc != NULL);
1158
1159 __glutCurrentWindow->passive = passiveMotionFunc;
1160 }
1161
1162 void GLUTAPIENTRY
1163 glutEntryFunc(GLUTentryCB entryFunc)
1164 {
1165 __glutChangeWindowEventMask(EnterWindowMask | LeaveWindowMask,
1166 entryFunc != NULL || __glutCurrentWindow->passive);
1167 __glutCurrentWindow->entry = entryFunc;
1168 if (!entryFunc) {
1169 __glutCurrentWindow->entryState = -1;
1170 }
1171 }
1172
1173 void GLUTAPIENTRY
1174 glutWindowStatusFunc(GLUTwindowStatusCB windowStatusFunc)
1175 {
1176 __glutChangeWindowEventMask(VisibilityChangeMask,
1177 windowStatusFunc != NULL);
1178 __glutCurrentWindow->windowStatus = windowStatusFunc;
1179 if (!windowStatusFunc) {
1180 /* Make state invalid. */
1181 __glutCurrentWindow->visState = -1;
1182 }
1183 }
1184
1185 static void GLUTCALLBACK
1186 visibilityHelper(int status)
1187 {
1188 if (status == GLUT_HIDDEN || status == GLUT_FULLY_COVERED)
1189 __glutCurrentWindow->visibility(GLUT_NOT_VISIBLE);
1190 else
1191 __glutCurrentWindow->visibility(GLUT_VISIBLE);
1192 }
1193
1194
1195 void GLUTAPIENTRY
1196 glutVisibilityFunc(GLUTvisibilityCB visibilityFunc)
1197 {
1198 __glutCurrentWindow->visibility = visibilityFunc;
1199
1200 if (visibilityFunc)
1201 { glutWindowStatusFunc(visibilityHelper);
1202 #if defined(__OS2PM__)
1203 if(__glutCurrentWindow->shownState >= 0)
1204 { visibilityHelper(__glutCurrentWindow->shownState);
1205 }
1206 #endif
1207 }
1208 else
1209 glutWindowStatusFunc(NULL);
1210 }
1211
1212 void GLUTAPIENTRY
1213 glutReshapeFunc(GLUTreshapeCB reshapeFunc)
1214 {
1215 if (reshapeFunc) {
1216 __glutCurrentWindow->reshape = reshapeFunc;
1217 } else {
1218 __glutCurrentWindow->reshape = __glutDefaultReshape;
1219 }
1220 }