2 /* Copyright (c) Mark J. Kilgard, 1994, 1997. */
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. */
9 #include <GL/vms_x_fix.h>
22 #include "gl\os2mesa.h"
25 //define for resource id for main GLUT window, in samples it is defined in GL_TEST.h
28 int evglSetPixelFormat(int iPixelFormat
);
31 #elif !defined(_WIN32)
34 #include <X11/Xatom.h>
39 GLUTwindow
*__glutCurrentWindow
= NULL
;
40 GLUTwindow
**__glutWindowList
= NULL
;
41 int __glutWindowListSize
= 0;
42 #if !defined(_WIN32) && !defined(__OS2__)
43 GLUTstale
*__glutStaleWindowList
= NULL
;
45 GLUTwindow
*__glutMenuWindow
= NULL
;
47 void (*__glutFreeOverlayFunc
) (GLUToverlay
*);
48 XVisualInfo
*(*__glutDetermineVisualFromString
) (char *string
, Bool
* treatAsSingle
,
49 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
, void** fbc
) = NULL
;
51 static Criterion requiredWindowCriteria
[] =
56 static int numRequiredWindowCriteria
= sizeof(requiredWindowCriteria
) / sizeof(Criterion
);
57 static int requiredWindowCriteriaMask
= (1 << LEVEL
) | (1 << TRANSPARENT
);
60 cleanWindowWorkList(GLUTwindow
* window
)
62 GLUTwindow
**pEntry
= &__glutWindowWorkList
;
63 GLUTwindow
*entry
= __glutWindowWorkList
;
65 /* Tranverse singly-linked window work list look for the
68 if (entry
== window
) {
69 /* Found it; delete it. */
70 *pEntry
= entry
->prevWorkWin
;
73 pEntry
= &entry
->prevWorkWin
;
79 #if !defined(_WIN32) && !defined(__OS2PM__)
82 cleanStaleWindowList(GLUTwindow
* window
)
84 GLUTstale
**pEntry
= &__glutStaleWindowList
;
85 GLUTstale
*entry
= __glutStaleWindowList
;
87 /* Tranverse singly-linked stale window list look for the
90 if (entry
->window
== window
) {
91 /* Found it; delete it. */
92 *pEntry
= entry
->next
;
96 pEntry
= &entry
->next
;
104 static GLUTwindow
*__glutWindowCache
= NULL
;
107 __glutGetWindow(Window win
)
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
))) {
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
;
125 if (__glutWindowList
[i
]->overlay
) {
126 if (win
== __glutWindowList
[i
]->overlay
->win
) {
127 __glutWindowCache
= __glutWindowList
[i
];
128 return __glutWindowCache
;
133 #if !defined(_WIN32) && !defined(__OS2PM__)
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
;
152 if (__glutCurrentWindow
) {
153 return __glutCurrentWindow
->num
+ 1;
161 __glutSetWindow(GLUTwindow
* window
)
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
171 __glutCurrentWindow
= window
;
173 MAKE_CURRENT_LAYER(__glutCurrentWindow
);
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
);
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. */
191 __glutPutOnWorkList(__glutCurrentWindow
, GLUT_DEBUG_WORK
);
197 glutSetWindow(int win
)
201 if (win
< 1 || win
> __glutWindowListSize
) {
202 __glutWarning("glutSetWindow attempted on bogus window.");
205 window
= __glutWindowList
[win
- 1];
207 __glutWarning("glutSetWindow attempted on bogus window.");
210 __glutSetWindow(window
);
215 getUnusedWindowSlot(void)
219 /* Look for allocated, unused slot. */
220 for (i
= 0; i
< __glutWindowListSize
; i
++) {
221 if (!__glutWindowList
[i
]) {
225 /* Allocate a new slot. */
226 __glutWindowListSize
++;
227 if (__glutWindowList
) {
228 __glutWindowList
= (GLUTwindow
**)
229 realloc(__glutWindowList
,
230 __glutWindowListSize
* sizeof(GLUTwindow
*));
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
*));
238 if (!__glutWindowList
)
239 __glutFatalError("out of memory.");
240 __glutWindowList
[__glutWindowListSize
- 1] = NULL
;
241 return __glutWindowListSize
- 1;
245 getVisualInfoCI(unsigned int mode
)
248 static int bufSizeList
[] =
249 {16, 12, 8, 4, 2, 1, 0};
254 /* Should not be looking at display mode mask if
255 __glutDisplayString is non-NULL. */
256 assert(!__glutDisplayString
);
258 list
[n
++] = GLX_BUFFER_SIZE
;
260 if (GLUT_WIND_IS_DOUBLE(mode
)) {
261 list
[n
++] = GLX_DOUBLEBUFFER
;
263 if (GLUT_WIND_IS_STEREO(mode
)) {
264 list
[n
++] = GLX_STEREO
;
266 if (GLUT_WIND_HAS_DEPTH(mode
)) {
267 list
[n
++] = GLX_DEPTH_SIZE
;
270 if (GLUT_WIND_HAS_STENCIL(mode
)) {
271 list
[n
++] = GLX_STENCIL_SIZE
;
274 list
[n
] = (int) None
; /* terminate list */
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. */
284 for (i
= 0; bufSizeList
[i
]; i
++) {
285 /* XXX Assumes list[1] is where GLX_BUFFER_SIZE parameter
287 list
[1] = bufSizeList
[i
];
288 vi
= glXChooseVisual(__glutDisplay
,
296 glXChooseVisual(mode
);
302 getVisualInfoRGB(unsigned int mode
)
308 /* Should not be looking at display mode mask if
309 __glutDisplayString is non-NULL. */
310 assert(!__glutDisplayString
);
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. */
317 list
[n
++] = GLX_RGBA
;
318 list
[n
++] = GLX_RED_SIZE
;
320 list
[n
++] = GLX_GREEN_SIZE
;
322 list
[n
++] = GLX_BLUE_SIZE
;
324 if (GLUT_WIND_HAS_ALPHA(mode
)) {
325 list
[n
++] = GLX_ALPHA_SIZE
;
328 if (GLUT_WIND_IS_DOUBLE(mode
)) {
329 list
[n
++] = GLX_DOUBLEBUFFER
;
331 if (GLUT_WIND_IS_STEREO(mode
)) {
332 list
[n
++] = GLX_STEREO
;
334 if (GLUT_WIND_HAS_DEPTH(mode
)) {
335 list
[n
++] = GLX_DEPTH_SIZE
;
338 if (GLUT_WIND_HAS_STENCIL(mode
)) {
339 list
[n
++] = GLX_STENCIL_SIZE
;
342 if (GLUT_WIND_HAS_ACCUM(mode
)) {
343 list
[n
++] = GLX_ACCUM_RED_SIZE
;
345 list
[n
++] = GLX_ACCUM_GREEN_SIZE
;
347 list
[n
++] = GLX_ACCUM_BLUE_SIZE
;
349 if (GLUT_WIND_HAS_ALPHA(mode
)) {
350 list
[n
++] = GLX_ACCUM_ALPHA_SIZE
;
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"))
359 #if defined(GLX_ARB_multisample)
360 list
[n
++] = GLX_SAMPLES_ARB
;
361 #elif defined(GLX_SGIS_multisample)
362 list
[n
++] = GLX_SAMPLES_SGIS
;
364 /* XXX Is 4 a reasonable minimum acceptable number of
369 list
[n
] = (int) None
; /* terminate list */
371 return glXChooseVisual(__glutDisplay
,
376 glXChooseVisual(mode
);
382 __glutGetVisualInfo(unsigned int mode
)
384 /* XXX GLUT_LUMINANCE not implemented for GLUT 3.0. */
385 if (GLUT_WIND_IS_LUMINANCE(mode
))
388 if (GLUT_WIND_IS_RGB(mode
))
389 return getVisualInfoRGB(mode
);
391 return getVisualInfoCI(mode
);
395 __glutDetermineVisual(
396 unsigned int displayMode
,
397 Bool
* treatAsSingle
,
398 XVisualInfo
* (getVisualInfo
) (unsigned int))
402 /* Should not be looking at display mode mask if
403 __glutDisplayString is non-NULL. */
404 assert(!__glutDisplayString
);
406 *treatAsSingle
= GLUT_WIND_IS_SINGLE(displayMode
);
407 vis
= getVisualInfo(displayMode
);
409 /* Fallback cases when can't get exactly what was asked
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
;
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
);
435 static void GLUTCALLBACK
436 __glutDefaultDisplay(void)
438 /* XXX Remove the warning after GLUT 3.0. */
439 __glutWarning("The following is a new check for GLUT 3.0; update your code.");
441 "redisplay needed for window %d, but no display callback.",
442 __glutCurrentWindow
->num
+ 1);
446 __glutDefaultReshape(int width
, int height
)
448 GLUToverlay
*overlay
;
450 /* Adjust the viewport of the window (and overlay if one
452 MAKE_CURRENT_WINDOW(__glutCurrentWindow
);
453 glViewport(0, 0, (GLsizei
) width
, (GLsizei
) height
);
454 overlay
= __glutCurrentWindow
->overlay
;
456 MAKE_CURRENT_OVERLAY(overlay
);
457 glViewport(0, 0, (GLsizei
) width
, (GLsizei
) height
);
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
);
466 __glutDetermineWindowVisual(Bool
* treatAsSingle
, Bool
* visAlloced
, void **fbc
)
468 if (__glutDisplayString
) {
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
480 assert(__glutDetermineVisualFromString
);
483 return __glutDetermineVisualFromString(__glutDisplayString
, treatAsSingle
,
484 requiredWindowCriteria
, numRequiredWindowCriteria
, requiredWindowCriteriaMask
, fbc
);
488 return __glutDetermineVisual(__glutDisplayMode
,
489 treatAsSingle
, __glutGetVisualInfo
);
493 /* ARGSUSED5 */ /* Only Win32 uses gameMode parameter. */
495 __glutCreateWindow(GLUTwindow
* parent
,
496 int x
, int y
, int width
, int height
, int gameMode
)
499 XSetWindowAttributes wa
;
500 unsigned long attribMask
;
503 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
509 #if defined(__OS2PM__)
511 extern HAB hab
; /* PM anchor block handle */
514 if(!WinQueryClassInfo(hab
,"GLUT", &classinfo
) )
515 __glutOpenOS2Connection(NULL
);
517 #elif defined(_WIN32)
521 if (!GetClassInfo(GetModuleHandle(NULL
), "GLUT", &wc
)) {
522 __glutOpenWin32Connection(NULL
);
525 if (!__glutDisplay
) {
526 __glutOpenXConnection(NULL
);
531 if (__glutGameModeWindow
) {
532 __glutFatalError("cannot create windows in game mode.");
536 winnum
= getUnusedWindowSlot();
537 window
= (GLUTwindow
*) malloc(sizeof(GLUTwindow
));
539 __glutFatalError("out of memory.");
541 window
->num
= winnum
;
543 #if defined(__OS2PM__)
544 /* Add this new window to the window list. */
545 __glutWindowList
[winnum
] = window
;
546 window
->shownState
= -1;
549 #if !defined(_WIN32) && !defined(__OS2PM__)
550 window
->vis
= __glutDetermineWindowVisual(&window
->treatAsSingle
,
551 &window
->visAlloced
, (void**) &fbc
);
554 "visual with necessary capabilities not found.");
556 __glutSetupColormap(window
->vis
, &window
->colormap
, &window
->cmap
);
558 window
->eventMask
= StructureNotifyMask
| ExposureMask
;
560 attribMask
= CWBackPixmap
| CWBorderPixel
| CWColormap
| CWEventMask
;
561 wa
.background_pixmap
= None
;
563 wa
.colormap
= window
->cmap
;
564 wa
.event_mask
= window
->eventMask
;
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
;
571 wa
.do_not_propagate_mask
= 0;
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
;
581 #if defined(__OS2PM__)
585 ERRORID erridErrorCode
;/* last error id code */
586 extern HAB hab
; /* PM anchor block handle */
589 flStyle
= WS_CLIPCHILDREN
|WS_VISIBLE
;
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
;
597 /* A standard toplevel window with borders and such. */
598 flStyle
= FCF_STANDARD
| WS_CLIPCHILDREN
;
599 // flStyle = WS_OVERLAPPEDWINDOW;
603 HWND hwnd
; /* Window */
604 ULONG ListBoxId
; /* Window id */
605 /* (supplied by application) */
608 HWND hwndClient
; /* handle to the client */
609 HWND hwndFrame
; /* handle to the frame */
610 PFNWP GenericWndProc
;
612 RECTL rect
; /* Boundary rectangle */
616 /************************************************/
617 // flCreate = (FCF_STANDARD) & ~FCF_TASKLIST;
618 /**********************************/
620 { window
->frame
= NULL
;
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 */
631 NULL
, /* Control data */
632 NULL
); /* Pres parameters */
634 erridErrorCode
= WinGetLastError(hab
);
637 window
->hdc
= WinOpenWindowDC(window
->win
);
638 window
->hpsBuffer
= hpsCurrent
;
642 rect
.xRight
= x
+width
;
644 rect
.yTop
= y
+ height
;
646 /***** else parent *****************************/
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 */
658 erridErrorCode
= WinGetLastError(hab
);
659 window
->win
= hwndClient
;
660 window
->frame
= hwnd
;
661 window
->hdc
= WinOpenWindowDC(window
->win
);
663 window
->hpsBuffer
= hpsCurrent
;
666 /* converts a client window's boundaries into an equivalent frame rectangle */
668 rect
.xRight
= x
+width
;
670 rect
.yTop
= y
+ height
;
672 /* calculate equivalent frame boundary from boundary data */
673 WinCalcFrameRect(window
->frame
, &rect
, FALSE
);
675 /***** endof if(parent) *****************************/
677 /* Must set the XHDC for fake glXChooseVisual & fake
678 glXCreateContext & fake XAllocColorCells. */
681 window
->vis
= __glutDetermineWindowVisual(&window
->treatAsSingle
,
682 &window
->visAlloced
, &fbc
);
685 "pixel format with necessary capabilities not found.");
688 rc
= wglChoosePixelFormat(window
->hdc
, window
->vis
),
690 // evglSetPixelFormat(2); /* int iPixelFormat 1 - doublebuffer/2 - single buffer ??*/
691 wglSetPixelFormat(window
->hdc
,rc
,window
->vis
);
693 __glutSetupColormap(window
->vis
, &window
->colormap
, &window
->cmap
);
695 window
->ctx
= glXCreateContext(window
->hpsBuffer
, window
->vis
,
696 None
, __glutTryDirect
);
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*/
703 /* Make sure subwindows get a windowStatus callback. */
705 WinPostMsg(parent
->win
, WM_ACTIVATE
, 0, 0);
710 #elif defined(_WIN32)
712 __glutAdjustCoords(parent
? parent
->win
: NULL
,
713 &x
, &y
, &width
, &height
);
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
;
723 /* A standard toplevel window with borders and such. */
724 style
= WS_OVERLAPPEDWINDOW
;
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. */
735 window
->vis
= __glutDetermineWindowVisual(&window
->treatAsSingle
,
736 &window
->visAlloced
, &fbc
);
739 "pixel format with necessary capabilities not found.");
741 if (!SetPixelFormat(window
->hdc
,
742 ChoosePixelFormat(window
->hdc
, window
->vis
),
744 __glutFatalError("SetPixelFormat failed during window create.");
746 __glutSetupColormap(window
->vis
, &window
->colormap
, &window
->cmap
);
747 /* Make sure subwindows get a windowStatus callback. */
749 PostMessage(parent
->win
, WM_ACTIVATE
, 0, 0);
751 window
->renderDc
= window
->hdc
;
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
,
759 window
->renderWin
= window
->win
;
760 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
762 window
->ctx
= __glut_glXCreateContextWithConfigSGIX(__glutDisplay
, fbc
,
763 GLX_RGBA_TYPE_SGIX
, None
, __glutTryDirect
);
766 #if defined(__OS2PM__)
767 // window->ctx = glXCreateContext(window->hpsBuffer, window->vis,
768 // None, __glutTryDirect);
770 window
->ctx
= glXCreateContext(__glutDisplay
, window
->vis
,
771 None
, __glutTryDirect
);
775 "failed to create OpenGL rendering context.");
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.");
786 window
->parent
= parent
;
788 window
->siblings
= parent
->children
;
789 parent
->children
= window
;
791 window
->siblings
= NULL
;
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
;
815 window
->joystick
= NULL
;
816 window
->joyPollInterval
= 0;
819 #if defined(__OS2PM__)
820 window
->wm_command
= NULL
;
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
;
830 window
->shownState
= 0;
831 window
->visState
= -1; /* not VisibilityUnobscured,
832 VisibilityPartiallyObscured, or
833 VisibilityFullyObscured */
835 window
->entryState
= -1; /* not EnterNotify or LeaveNotify */
837 window
->desiredConfMask
= 0;
838 window
->buttonUses
= 0;
839 window
->cursor
= GLUT_CURSOR_INHERIT
;
841 /* Setup window to be mapped when glutMainLoop starts. */
842 window
->workMask
= GLUT_MAP_WORK
;
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
;
853 window
->desiredMapState
= NormalState
;
856 window
->desiredMapState
= NormalState
;
858 window
->prevWorkWin
= __glutWindowWorkList
;
859 __glutWindowWorkList
= window
;
861 /* Initially, no menus attached. */
862 for (i
= 0; i
< GLUT_MAX_MENUS
; i
++) {
866 /* Add this new window to the window list. */
867 __glutWindowList
[winnum
] = window
;
869 /* Make the new window the current window. */
870 __glutSetWindow(window
);
872 __glutDetermineMesaSwapHackSupport();
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
);
890 glutCreateWindow(const char *title
)
892 static int firstWindow
= 1;
894 #if !defined(_WIN32) && !defined(__OS2__)
898 XTextProperty textprop
;
900 if (__glutGameModeWindow
) {
901 __glutFatalError("cannot create windows in game mode.");
903 window
= __glutCreateWindow(NULL
,
904 __glutSizeHints
.x
, __glutSizeHints
.y
,
905 __glutInitWidth
, __glutInitHeight
,
906 /* not game mode */ 0);
908 /* Setup ICCCM properties. */
909 textprop
.value
= (unsigned char *) title
;
910 textprop
.encoding
= XA_STRING
;
912 textprop
.nitems
= strlen(title
);
914 WinSetWindowText(window
->frame
, (PCSZ
)title
);
916 window
->desiredMapState
= IconicState
;
918 #elif defined(_WIN32)
919 SetWindowText(win
, title
);
921 window
->desiredMapState
= IconicState
;
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
);
934 XSetWMProtocols(__glutDisplay
, win
, &__glutWMDeleteWindow
, 1);
937 return window
->num
+ 1;
942 __glutCreateWindowWithExit(const char *title
, void (__cdecl
*exitfunc
)(int))
944 __glutExitFunc
= exitfunc
;
945 return glutCreateWindow(title
);
950 glutCreateSubWindow(int win
, int x
, int y
, int width
, int height
)
954 window
= __glutCreateWindow(__glutWindowList
[win
- 1],
955 x
, y
, width
, height
, /* not game mode */ 0);
956 #if !defined(_WIN32) && !defined(__OS2__)
958 GLUTwindow
*toplevel
;
960 toplevel
= __glutToplevelOf(window
);
961 if (toplevel
->cmap
!= window
->cmap
) {
962 __glutPutOnWorkList(toplevel
, GLUT_COLORMAP_WORK
);
966 return window
->num
+ 1;
971 __glutDestroyWindow(GLUTwindow
* window
,
972 GLUTwindow
* initialWindow
)
974 GLUTwindow
**prev
, *cur
, *parent
, *siblings
;
976 /* Recursively destroy any children. */
977 cur
= window
->children
;
979 siblings
= cur
->siblings
;
980 __glutDestroyWindow(cur
, initialWindow
);
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
;
991 *prev
= cur
->siblings
;
994 prev
= &(cur
->siblings
);
998 /* Unbind if bound to this window. */
999 if (window
== __glutCurrentWindow
) {
1001 __glutCurrentWindow
= NULL
;
1003 /* Begin tearing down window itself. */
1004 if (window
->overlay
) {
1005 __glutFreeOverlayFunc(window
->overlay
);
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
);
1013 /* NULLing the __glutWindowList helps detect is a window
1014 instance has been destroyed, given a window number. */
1015 __glutWindowList
[window
->num
] = NULL
;
1017 /* Cleanup data structures that might contain window. */
1018 cleanWindowWorkList(window
);
1019 #if !defined(_WIN32) && !defined(__OS2__)
1020 cleanStaleWindowList(window
);
1022 /* Remove window from the "get window cache" if it is there. */
1023 if (__glutWindowCache
== window
)
1024 __glutWindowCache
= NULL
;
1026 if (window
->visAlloced
) {
1027 /* Only free XVisualInfo* gotten from glXChooseVisual. */
1031 if (window
== __glutGameModeWindow
) {
1032 /* Destroying the game mode window should implicitly
1033 have GLUT leave game mode. */
1034 __glutCloseDownGameMode();
1042 glutDestroyWindow(int win
)
1044 GLUTwindow
*window
= __glutWindowList
[win
- 1];
1046 if (__glutMappedMenu
&& __glutMenuWindow
== window
) {
1047 __glutFatalUsage("destroying menu window not allowed while menus in use");
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
1055 __glutPutOnWorkList(__glutToplevelOf(window
->parent
),
1056 GLUT_COLORMAP_WORK
);
1059 __glutDestroyWindow(window
, window
);
1060 XFlush(__glutDisplay
);
1065 __glutChangeWindowEventMask(long eventMask
, Bool add
)
1068 /* Add eventMask to window's event mask. */
1069 if ((__glutCurrentWindow
->eventMask
& eventMask
) !=
1071 __glutCurrentWindow
->eventMask
|= eventMask
;
1072 __glutPutOnWorkList(__glutCurrentWindow
,
1073 GLUT_EVENT_MASK_WORK
);
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
);
1086 glutDisplayFunc(GLUTdisplayCB displayFunc
)
1088 /* XXX Remove the warning after GLUT 3.0. */
1090 __glutFatalError("NULL display callback not allowed in GLUT 3.0; update your code.");
1091 __glutCurrentWindow
->display
= displayFunc
;
1095 glutMouseFunc(GLUTmouseCB mouseFunc
)
1097 if (__glutCurrentWindow
->mouse
) {
1099 /* Previous mouseFunc being disabled. */
1100 __glutCurrentWindow
->buttonUses
--;
1101 __glutChangeWindowEventMask(
1102 ButtonPressMask
| ButtonReleaseMask
,
1103 __glutCurrentWindow
->buttonUses
> 0);
1107 /* Previously no mouseFunc, new one being installed. */
1108 __glutCurrentWindow
->buttonUses
++;
1109 __glutChangeWindowEventMask(
1110 ButtonPressMask
| ButtonReleaseMask
, True
);
1113 __glutCurrentWindow
->mouse
= mouseFunc
;
1117 glutMotionFunc(GLUTmotionCB motionFunc
)
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
1124 if (__glutCurrentWindow
->motion
) {
1126 /* previous mouseFunc being disabled */
1127 __glutCurrentWindow
->buttonUses
--;
1128 __glutChangeWindowEventMask(
1129 ButtonPressMask
| ButtonReleaseMask
,
1130 __glutCurrentWindow
->buttonUses
> 0);
1134 /* Previously no mouseFunc, new one being installed. */
1135 __glutCurrentWindow
->buttonUses
++;
1136 __glutChangeWindowEventMask(
1137 ButtonPressMask
| ButtonReleaseMask
, True
);
1140 /* Real work of selecting for passive mouse motion. */
1141 __glutChangeWindowEventMask(
1142 Button1MotionMask
| Button2MotionMask
| Button3MotionMask
,
1143 motionFunc
!= NULL
);
1144 __glutCurrentWindow
->motion
= motionFunc
;
1148 glutPassiveMotionFunc(GLUTpassiveCB passiveMotionFunc
)
1150 __glutChangeWindowEventMask(PointerMotionMask
,
1151 passiveMotionFunc
!= NULL
);
1153 /* Passive motion also requires watching enters and leaves so
1154 that a fake passive motion event can be generated on an
1156 __glutChangeWindowEventMask(EnterWindowMask
| LeaveWindowMask
,
1157 __glutCurrentWindow
->entry
!= NULL
|| passiveMotionFunc
!= NULL
);
1159 __glutCurrentWindow
->passive
= passiveMotionFunc
;
1163 glutEntryFunc(GLUTentryCB entryFunc
)
1165 __glutChangeWindowEventMask(EnterWindowMask
| LeaveWindowMask
,
1166 entryFunc
!= NULL
|| __glutCurrentWindow
->passive
);
1167 __glutCurrentWindow
->entry
= entryFunc
;
1169 __glutCurrentWindow
->entryState
= -1;
1174 glutWindowStatusFunc(GLUTwindowStatusCB windowStatusFunc
)
1176 __glutChangeWindowEventMask(VisibilityChangeMask
,
1177 windowStatusFunc
!= NULL
);
1178 __glutCurrentWindow
->windowStatus
= windowStatusFunc
;
1179 if (!windowStatusFunc
) {
1180 /* Make state invalid. */
1181 __glutCurrentWindow
->visState
= -1;
1185 static void GLUTCALLBACK
1186 visibilityHelper(int status
)
1188 if (status
== GLUT_HIDDEN
|| status
== GLUT_FULLY_COVERED
)
1189 __glutCurrentWindow
->visibility(GLUT_NOT_VISIBLE
);
1191 __glutCurrentWindow
->visibility(GLUT_VISIBLE
);
1196 glutVisibilityFunc(GLUTvisibilityCB visibilityFunc
)
1198 __glutCurrentWindow
->visibility
= visibilityFunc
;
1201 { glutWindowStatusFunc(visibilityHelper
);
1202 #if defined(__OS2PM__)
1203 if(__glutCurrentWindow
->shownState
>= 0)
1204 { visibilityHelper(__glutCurrentWindow
->shownState
);
1209 glutWindowStatusFunc(NULL
);
1213 glutReshapeFunc(GLUTreshapeCB reshapeFunc
)
1216 __glutCurrentWindow
->reshape
= reshapeFunc
;
1218 __glutCurrentWindow
->reshape
= __glutDefaultReshape
;