1 /***********************************************************
2 * Copyright (C) 1997, Be Inc. All rights reserved.
6 * DESCRIPTION: all the routines for dealing with GlutWindows
7 ***********************************************************/
9 /***********************************************************
11 ***********************************************************/
15 #include "glutState.h"
16 #include "glutBlocker.h"
18 /***********************************************************
19 * FUNCTION: getUnusedWindowSlot
21 * DESCRIPTION: helper function to get a new window slot
22 ***********************************************************/
28 /* Look for allocated, unused slot. */
29 for (i
= 0; i
< gState
.windowListSize
; i
++) {
30 if (!gState
.windowList
[i
]) {
34 /* Allocate a new slot. */
35 gState
.windowListSize
++;
36 gState
.windowList
= (GlutWindow
**)
37 realloc(gState
.windowList
,
38 gState
.windowListSize
* sizeof(GlutWindow
*));
40 if (!gState
.windowList
)
41 __glutFatalError("out of memory.");
42 gState
.windowList
[gState
.windowListSize
- 1] = NULL
;
43 return gState
.windowListSize
- 1;
46 /***********************************************************
47 * FUNCTION: __glutDefaultDisplay
48 * __glutDefaultReshape
50 * DESCRIPTION: default display and reshape functions
51 ***********************************************************/
53 __glutDefaultDisplay(void)
55 /* XXX Remove the warning after GLUT 3.0. */
56 __glutWarning("The following is a new check for GLUT 3.0; update your code.");
58 "redisplay needed for window %d, but no display callback.",
59 gState
.currentWindow
->num
+ 1);
63 __glutDefaultReshape(int width
, int height
)
65 /* Adjust the viewport of the window */
66 glViewport(0, 0, (GLsizei
) width
, (GLsizei
) height
);
69 /***********************************************************
72 * FUNCTION: (constructor)
74 * DESCRIPTION: creates a new GLUT window
75 * note: subwindows don't resize, but top-level windows
77 ***********************************************************/
78 GlutWindow::GlutWindow(GlutWindow
*nparent
, char *name
,
79 int x
, int y
, int width
, int height
, ulong options
) :
81 (nparent
? BRect(x
,y
,x
+width
-1,y
+height
-1) :
82 BRect(0,0,width
-1,height
-1)), name
,
83 (nparent
? B_FOLLOW_NONE
: B_FOLLOW_ALL_SIDES
),
84 B_WILL_DRAW
|B_FRAME_EVENTS
|B_FULL_UPDATE_ON_RESIZE
|B_PULSE_NEEDED
,
87 // add myself to window list
88 num
= getUnusedWindowSlot();
89 gState
.windowList
[num
] = this;
91 // set up parent/children relationships
94 siblings
= parent
->children
;
95 parent
->children
= this;
101 // initialize variables
102 cursor
= GLUT_CURSOR_INHERIT
; // default cursor
103 for (int i
= 0; i
< GLUT_MAX_MENUS
; i
++) {
111 display
= __glutDefaultDisplay
;
112 reshape
= __glutDefaultReshape
;
121 // faked out single buffering
122 swapHack
= gState
.swapHack
;
124 // clear event counters
126 displayEvent
= 1; // get a reshape and a display event right away
133 visEvent
= 1; // we also get a visibility event
134 visState
= GLUT_VISIBLE
;
138 gBlock
.QuickNewEvent();
140 // if i'm a subwindow, add me to my parent view
142 parent
->Window()->Lock();
143 parent
->AddChild(this);
144 parent
->Window()->Unlock();
146 // if I'm a top-level window, create my BWindow
147 GlutBWindow
*mybwindow
= new GlutBWindow(
148 BRect(x
,y
,x
+width
-1,y
+height
-1), name
);
149 mybwindow
->AddChild(this);
153 // give me the keyboard focus (focus follows mouse, X style, as
154 // implemented in GlutWindow::MouseMoved())
159 // make myself the default window
160 __glutSetWindow(this);
163 /***********************************************************
164 * FUNCTION: glutCreateWindow (4.1)
166 * DESCRIPTION: creates a new GLUT window
167 ***********************************************************/
168 int glutCreateWindow(const char *name
) {
173 if (!__glutConvertDisplayMode(&options
)) {
174 __glutWarning("visual with necessary capabilities not found.");
177 // if X or Y is negative, then start at a reasonable position
178 bool defaultxy
= (gState
.initX
< 0) || (gState
.initY
< 0);
180 GlutWindow
*window
= new GlutWindow(0, const_cast<char*>(name
),
181 (defaultxy
? 50 : gState
.initX
), (defaultxy
? 50 : gState
.initY
),
182 gState
.initWidth
, gState
.initHeight
, options
);
184 return window
->num
+ 1;
187 /***********************************************************
188 * FUNCTION: glutCreateSubWindow (4.2)
190 * DESCRIPTION: creates a new GLUT subwindow
191 * Note: a subwindow is a GlutWindow (which is actually
192 * a BGLView) without its own BWindow
193 ***********************************************************/
194 int glutCreateSubWindow(int win
, int x
, int y
, int width
, int height
) {
196 if (!__glutConvertDisplayMode(&options
)) {
197 __glutFatalError("visual with necessary capabilities not found.");
200 GlutWindow
*window
= new GlutWindow(gState
.windowList
[win
-1], "child",
201 x
, y
, width
, height
, options
);
203 return window
->num
+ 1;
206 /***********************************************************
207 * FUNCTION: __glutSetWindow
209 * DESCRIPTION: set the current window (utility function)
210 ***********************************************************/
212 __glutSetWindow(GlutWindow
* window
)
214 if (gState
.currentWindow
)
215 gState
.currentWindow
->UnlockGL();
216 gState
.currentWindow
= window
;
217 gState
.currentWindow
->LockGL();
220 /***********************************************************
221 * FUNCTION: glutSetWindow (4.3)
224 * DESCRIPTION: set and get the current window
225 ***********************************************************/
226 void glutSetWindow(int win
) {
229 if (win
< 1 || win
> gState
.windowListSize
) {
230 __glutWarning("glutSetWindow attempted on bogus window.");
233 window
= gState
.windowList
[win
- 1];
235 __glutWarning("glutSetWindow attempted on bogus window.");
238 __glutSetWindow(window
);
241 int glutGetWindow() {
242 if (gState
.currentWindow
) {
243 return gState
.currentWindow
->num
+ 1;
249 /***********************************************************
250 * FUNCTION: __glutDestroyWindow
252 * DESCRIPTION: recursively set entries to 0
253 ***********************************************************/
255 __glutDestroyWindow(GlutWindow
*window
, GlutWindow
*initialWindow
) {
256 // first, find all children recursively and set their entries to 0
257 GlutWindow
*cur
= window
->children
;
259 GlutWindow
*siblings
= cur
->siblings
;
260 __glutDestroyWindow(cur
, initialWindow
);
264 /* Remove from parent's children list (only necessary for
265 non-initial windows and subwindows!). */
266 GlutWindow
*parent
= window
->parent
;
267 if (parent
&& parent
== initialWindow
->parent
) {
268 GlutWindow
**prev
= &parent
->children
;
269 cur
= parent
->children
;
272 *prev
= cur
->siblings
;
275 prev
= &(cur
->siblings
);
280 // finally, check if we are the current window, and set to 0
281 if (gState
.currentWindow
== window
) {
282 gState
.currentWindow
= 0;
284 gState
.windowList
[window
->num
] = 0;
287 /***********************************************************
288 * FUNCTION: glutDestroyWindow (4.4)
290 * DESCRIPTION: destroy window and all its children
291 ***********************************************************/
292 void glutDestroyWindow(int win
) {
293 // can't destroy a window if another window has the GL context
294 gState
.currentWindow
->UnlockGL();
297 GlutWindow
*window
= gState
.windowList
[win
-1];
298 BWindow
*bwindow
= window
->Window();
301 // if win is the current window, set current window to 0 and unlock GL
302 if (gState
.currentWindow
== window
) {
304 gState
.currentWindow
= 0;
307 // recursively set child entries to 0
308 __glutDestroyWindow(window
, window
);
310 // now, if the window was top-level, delete its BWindow
311 if(!window
->parent
) {
314 // else, detach it from the BWindow and delete it
315 window
->RemoveSelf();
320 // relock GL if the current window is still valid
321 if(gState
.currentWindow
)
322 gState
.currentWindow
->LockGL();
325 /***********************************************************
326 * FUNCTION: glutPostRedisplay (4.5)
328 * DESCRIPTION: mark window as needing redisplay
329 ***********************************************************/
330 void glutPostRedisplay() {
331 gState
.currentWindow
->Window()->Lock();
332 gState
.currentWindow
->anyevents
= true;
333 gState
.currentWindow
->displayEvent
= true;
334 gState
.currentWindow
->Window()->Unlock();
335 gBlock
.QuickNewEvent();
338 /***********************************************************
339 * FUNCTION: glutSwapBuffers (4.6)
341 * DESCRIPTION: swap buffers
342 ***********************************************************/
343 void glutSwapBuffers() {
344 gState
.currentWindow
->SwapBuffers();
347 /***********************************************************
348 * FUNCTION: glutPositionWindow (4.7)
350 * DESCRIPTION: move window
351 ***********************************************************/
352 void glutPositionWindow(int x
, int y
) {
353 gState
.currentWindow
->Window()->Lock();
354 if (gState
.currentWindow
->parent
)
355 gState
.currentWindow
->MoveTo(x
, y
); // move the child view
357 gState
.currentWindow
->Window()->MoveTo(x
, y
); // move the window
358 gState
.currentWindow
->Window()->Unlock();
361 /***********************************************************
362 * FUNCTION: glutReshapeWindow (4.8)
364 * DESCRIPTION: reshape window (we'll catch the callback
365 * when the view gets a Draw() message
366 ***********************************************************/
367 void glutReshapeWindow(int width
, int height
) {
368 gState
.currentWindow
->Window()->Lock();
369 if (gState
.currentWindow
->parent
)
370 gState
.currentWindow
->ResizeTo(width
-1, height
-1); // resize the child
372 gState
.currentWindow
->Window()->ResizeTo(width
-1, height
-1); // resize the parent
373 gState
.currentWindow
->Window()->Unlock();
376 /***********************************************************
377 * FUNCTION: glutFullScreen (4.9)
379 * DESCRIPTION: makes the window full screen
380 * NOTE: we could add Game Kit support later?
381 ***********************************************************/
382 void glutFullScreen() {
383 gState
.currentWindow
->Window()->Lock();
384 BRect frame
= BScreen(gState
.currentWindow
->Window()).Frame();
385 glutPositionWindow(0, 0);
386 glutReshapeWindow((int)(frame
.Width()) + 1, (int)(frame
.Height()) + 1);
387 gState
.currentWindow
->Window()->Unlock();
390 /***********************************************************
391 * FUNCTION: glutPopWindow (4.10)
394 * DESCRIPTION: change the stacking order of the current window
395 * NOTE: I can't figure out how to do this for windows,
396 * and there is no concept of "stacking order" for
397 * subwindows, so these are currently no-ops.
398 ***********************************************************/
399 void glutPopWindow() { }
400 void glutPushWindow() { }
402 /***********************************************************
403 * FUNCTION: glutShowWindow (4.11)
407 * DESCRIPTION: change display status of current window
408 ***********************************************************/
409 void glutShowWindow() {
410 gState
.currentWindow
->Window()->Lock();
411 if (gState
.currentWindow
->parent
) // subwindow
412 gState
.currentWindow
->Show();
414 gState
.currentWindow
->Window()->Show(); // show the actual BWindow
415 gState
.currentWindow
->Window()->Minimize(false);
417 gState
.currentWindow
->Window()->Unlock();
420 void glutHideWindow() {
421 gState
.currentWindow
->Window()->Lock();
422 if (gState
.currentWindow
->parent
) // subwindow
423 gState
.currentWindow
->Hide();
425 gState
.currentWindow
->Window()->Hide(); // show the actual BWindow
426 gState
.currentWindow
->Window()->Unlock();
429 void glutIconifyWindow() {
430 if(gState
.currentWindow
->parent
)
431 __glutFatalError("can't iconify a subwindow");
433 gState
.currentWindow
->Window()->Lock();
434 gState
.currentWindow
->Window()->Minimize(true);
435 gState
.currentWindow
->Window()->Unlock();
438 /***********************************************************
439 * FUNCTION: glutSetWindowTitle (4.12)
442 * DESCRIPTION: set the window title (icon title is same)
443 ***********************************************************/
444 void glutSetWindowTitle(const char *name
) {
445 if (gState
.currentWindow
->parent
)
446 __glutFatalError("glutSetWindowTitle: isn't a top-level window");
448 gState
.currentWindow
->Window()->Lock();
449 gState
.currentWindow
->Window()->SetTitle(name
);
450 gState
.currentWindow
->Window()->Unlock();
453 void glutSetIconTitle(const char *name
) {
454 glutSetWindowTitle(name
);
457 /***********************************************************
458 * FUNCTION: __glutConvertDisplayMode
460 * DESCRIPTION: converts the current display mode into a BGLView
461 * display mode, printing warnings as appropriate.
463 * PARAMETERS: if options is non-NULL, the current display mode is
466 * RETURNS: 1 if the current display mode is possible, else 0
467 ***********************************************************/
468 int __glutConvertDisplayMode(unsigned long *options
) {
469 if (gState
.displayString
) {
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. This big ugly code is in glutDstr.cpp */
475 return __glutConvertDisplayModeFromString(options
);
479 ulong newoptions
= BGL_DOUBLE
;
480 if(gState
.displayMode
& GLUT_ACCUM
)
481 newoptions
|= BGL_ACCUM
;
482 if(gState
.displayMode
& GLUT_ALPHA
)
483 newoptions
|= BGL_ALPHA
;
484 if(gState
.displayMode
& GLUT_DEPTH
)
485 newoptions
|= BGL_DEPTH
;
486 if(gState
.displayMode
& GLUT_STENCIL
)
487 newoptions
|= BGL_STENCIL
;
488 *options
= newoptions
;
491 // if not GLUT_DOUBLE, turn on the swap hack bit
492 gState
.swapHack
= !(gState
.displayMode
& GLUT_DOUBLE
);
494 if(gState
.displayMode
& GLUT_INDEX
) {
495 __glutWarning("BeOS doesn't support indexed color");
498 if(gState
.displayMode
& GLUT_MULTISAMPLE
) {
499 return 1; // try to go without multisampling
501 if(gState
.displayMode
& GLUT_STEREO
) {
502 __glutWarning("BeOS doesn't support stereo windows");
505 if(gState
.displayMode
& GLUT_LUMINANCE
) {
506 __glutWarning("BeOS doesn't support luminance color model");
509 return 1; // visual supported
512 /***********************************************************
515 * DESCRIPTION: very thin wrapper around BWindow
516 ***********************************************************/
517 GlutBWindow::GlutBWindow(BRect frame
, char *name
) :
518 BWindow(frame
, name
, B_TITLED_WINDOW
, 0) {
519 SetPulseRate(100000);
522 bool GlutBWindow::QuitRequested() {
523 exit(0); // exit program completely on quit
524 return true; // UNREACHED