1c041511dScube/***********************************************************
2c041511dScube *      Copyright (C) 1997, Be Inc.  Copyright (C) 1999, Jake Hamby.
3c041511dScube *
4c041511dScube * This program is freely distributable without licensing fees
5c041511dScube * and is provided without guarantee or warrantee expressed or
6c041511dScube * implied. This program is -not- in the public domain.
7c041511dScube *
8c041511dScube *
9c041511dScube *  FILE:	glutWindow.cpp
10c041511dScube *
11c041511dScube *	DESCRIPTION:	all the routines for dealing with GlutWindows
12c041511dScube ***********************************************************/
13c041511dScube
14c041511dScube/***********************************************************
15c041511dScube *	Headers
16c041511dScube ***********************************************************/
17c041511dScube#include <GL/glut.h>
18c041511dScube#include <stdlib.h>
19c041511dScube#include "glutint.h"
20c041511dScube#include "glutState.h"
21c041511dScube#include "glutBlocker.h"
22c041511dScube
23c041511dScube/***********************************************************
24c041511dScube *	FUNCTION:	getUnusedWindowSlot
25c041511dScube *
26c041511dScube *	DESCRIPTION:  helper function to get a new window slot
27c041511dScube ***********************************************************/
28c041511dScubestatic int
29c041511dScubegetUnusedWindowSlot()
30c041511dScube{
31c041511dScube  int i;
32c041511dScube
33c041511dScube  /* Look for allocated, unused slot. */
34c041511dScube  for (i = 0; i < gState.windowListSize; i++) {
35c041511dScube    if (!gState.windowList[i]) {
36c041511dScube      return i;
37c041511dScube    }
38c041511dScube  }
39c041511dScube  /* Allocate a new slot. */
40c041511dScube  gState.windowListSize++;
41c041511dScube  gState.windowList = (GlutWindow **)
42c041511dScube    realloc(gState.windowList,
43c041511dScube      gState.windowListSize * sizeof(GlutWindow *));
44c041511dScube
45c041511dScube  if (!gState.windowList)
46c041511dScube    __glutFatalError("out of memory.");
47c041511dScube  gState.windowList[gState.windowListSize - 1] = NULL;
48c041511dScube  return gState.windowListSize - 1;
49c041511dScube}
50c041511dScube
51c041511dScube/***********************************************************
52c041511dScube *	FUNCTION:	__glutDefaultDisplay
53c041511dScube *				__glutDefaultReshape
54c041511dScube *
55c041511dScube *	DESCRIPTION:  default display and reshape functions
56c041511dScube ***********************************************************/
57c041511dScubestatic void
58c041511dScube__glutDefaultDisplay(void)
59c041511dScube{
60c041511dScube  /* XXX Remove the warning after GLUT 3.0. */
61c041511dScube  __glutWarning("The following is a new check for GLUT 3.0; update your code.");
62c041511dScube  __glutFatalError(
63c041511dScube    "redisplay needed for window %d, but no display callback.",
64c041511dScube    gState.currentWindow->num + 1);
65c041511dScube}
66c041511dScube
67c041511dScubevoid
68c041511dScube__glutDefaultReshape(int width, int height)
69c041511dScube{
70c041511dScube  /* Adjust the viewport of the window */
71c041511dScube  glViewport(0, 0, (GLsizei) width, (GLsizei) height);
72c041511dScube}
73c041511dScube
74c041511dScube/***********************************************************
75c041511dScube *	CLASS:		GlutWindow
76c041511dScube *
77c041511dScube *	FUNCTION:	(constructor)
78c041511dScube *
79c041511dScube *	DESCRIPTION:  creates a new GLUT window
80c041511dScube *		note:  subwindows don't resize, but top-level windows
81c041511dScube *		follow all sides
82c041511dScube ***********************************************************/
83c041511dScubeGlutWindow::GlutWindow(GlutWindow *nparent, char *name,
84c041511dScube		int x, int y, int width, int height, ulong options) :
85c041511dScube		BGLView(
86c041511dScube		(nparent ? BRect(x,y,x+width-1,y+height-1) :
87c041511dScube			BRect(0,0,width-1,height-1)), name,
88c041511dScube		(nparent ? B_FOLLOW_NONE : B_FOLLOW_ALL_SIDES),
89c041511dScube		B_WILL_DRAW|B_FRAME_EVENTS|B_FULL_UPDATE_ON_RESIZE|B_PULSE_NEEDED,
90c041511dScube		options)
91c041511dScube{
92c041511dScube	// add myself to window list
93c041511dScube	num = getUnusedWindowSlot();
94c041511dScube	gState.windowList[num] = this;
95c041511dScube
96c041511dScube	// set up parent/children relationships
97c041511dScube	parent = nparent;
98c041511dScube	if (parent) {
99c041511dScube		siblings = parent->children;
100c041511dScube		parent->children = this;
101c041511dScube	} else {
102c041511dScube		siblings = 0;
103c041511dScube	}
104c041511dScube	children = 0;
105c041511dScube
106c041511dScube	// initialize variables
107c041511dScube	cursor = GLUT_CURSOR_INHERIT;	// default cursor
108c041511dScube	for (int i = 0; i < GLUT_MAX_MENUS; i++) {
109c041511dScube		menu[i] = 0;
110c041511dScube	}
111c041511dScube	m_width = width;
112c041511dScube	m_height = height;
113c041511dScube	m_buttons = 0;
114c041511dScube
115c041511dScube	// clear callbacks
116c041511dScube	display = __glutDefaultDisplay;
117c041511dScube	reshape = __glutDefaultReshape;
118c041511dScube	mouse = 0;
119c041511dScube	motion = 0;
120c041511dScube	passive = 0;
121c041511dScube	entry = 0;
122c041511dScube	keyboard = 0;
123c041511dScube	visibility = 0;
124c041511dScube	special = 0;
125c041511dScube	windowStatus = 0;
126c041511dScube
127c041511dScube	// clear event counters
128c041511dScube	anyevents = 1;
129c041511dScube	displayEvent = 1;	// get a reshape and a display event right away
130c041511dScube	reshapeEvent = 1;
131c041511dScube	mouseEvent = 0;
132c041511dScube	motionEvent = 0;
133c041511dScube	passiveEvent = 0;
134c041511dScube	entryEvent = 0;
135c041511dScube	keybEvent = 0;
136c041511dScube	windowStatusEvent = 0; // DirectConnected() will report change in
137c041511dScube	visState = -1;         // visibility
138c041511dScube	specialEvent = 0;
139c041511dScube	statusEvent = 0;
140c041511dScube	menuEvent = 0;
141c041511dScube	visible = true;
142c041511dScube	gBlock.QuickNewEvent();
143c041511dScube
144c041511dScube	// if i'm a subwindow, add me to my parent view
145c041511dScube	if (parent) {
146c041511dScube		parent->Window()->Lock();
147c041511dScube		parent->AddChild(this);
148c041511dScube		parent->Window()->Unlock();
149c041511dScube	} else {
150c041511dScube		// if I'm a top-level window, create my BWindow
151c041511dScube		GlutBWindow *mybwindow = new GlutBWindow(
152c041511dScube			BRect(x,y,x+width-1,y+height-1), name);
153c041511dScube		mybwindow->AddChild(this);
154c041511dScube		mybwindow->bgl = this;
155c041511dScube		mybwindow->Show();
156c041511dScube	}
157c041511dScube
158c041511dScube	// give me the keyboard focus (focus follows mouse, X style, as
159c041511dScube	// implemented in GlutWindow::MouseMoved())
160c041511dScube	Window()->Lock();
161c041511dScube	MakeFocus();
162c041511dScube	Window()->Unlock();
163c041511dScube
164c041511dScube	// make myself the default window
165c041511dScube	__glutSetWindow(this);
166c041511dScube}
167c041511dScube
168c041511dScube/***********************************************************
169c041511dScube *	FUNCTION:	glutCreateWindow (4.1)
170c041511dScube *
171c041511dScube *	DESCRIPTION:  creates a new GLUT window
172c041511dScube ***********************************************************/
173c041511dScubeint glutCreateWindow(const char *name) {
174c041511dScube	if (!be_app)
175c041511dScube		__glutInit();
176c041511dScube
177c041511dScube	ulong options;
178c041511dScube	if (!__glutConvertDisplayMode(&options)) {
179c041511dScube		__glutWarning("visual with necessary capabilities not found.");
180c041511dScube	}
181c041511dScube
182c041511dScube	// if X or Y is negative, then start at a reasonable position
183c041511dScube	bool defaultxy = (gState.initX < 0) || (gState.initY < 0);
184c041511dScube
185c041511dScube	GlutWindow *window = new GlutWindow(0, const_cast<char*>(name),
186c041511dScube		(defaultxy ? 50 : gState.initX), (defaultxy ? 50 : gState.initY),
187c041511dScube		gState.initWidth, gState.initHeight, options);
188c041511dScube
189c041511dScube	return window->num + 1;
190c041511dScube}
191c041511dScube
192c041511dScube/***********************************************************
193c041511dScube *	FUNCTION:	glutCreateSubWindow (4.2)
194c041511dScube *
195c041511dScube *	DESCRIPTION:  creates a new GLUT subwindow
196c041511dScube *		Note: a subwindow is a GlutWindow (which is actually
197c041511dScube *		a BGLView) without its own BWindow
198c041511dScube ***********************************************************/
199c041511dScubeint glutCreateSubWindow(int win, int x, int y, int width, int height) {
200c041511dScube	ulong options;
201c041511dScube	if (!__glutConvertDisplayMode(&options)) {
202c041511dScube		__glutFatalError("visual with necessary capabilities not found.");
203c041511dScube	}
204c041511dScube
205c041511dScube	GlutWindow *window = new GlutWindow(gState.windowList[win-1], "child",
206c041511dScube		x, y, width, height, options);
207c041511dScube
208c041511dScube	return window->num + 1;
209c041511dScube}
210c041511dScube
211c041511dScube/***********************************************************
212c041511dScube *	FUNCTION:	__glutSetWindow
213c041511dScube *
214c041511dScube *	DESCRIPTION:  set the current window (utility function)
215c041511dScube ***********************************************************/
216c041511dScubevoid
217c041511dScube__glutSetWindow(GlutWindow * window)
218c041511dScube{
219c041511dScube  if (gState.currentWindow)
220c041511dScube	  gState.currentWindow->UnlockGL();
221c041511dScube  gState.currentWindow = window;
222c041511dScube  gState.currentWindow->LockGL();
223c041511dScube}
224c041511dScube
225c041511dScube/***********************************************************
226c041511dScube *	FUNCTION:	glutSetWindow (4.3)
227c041511dScube *				glutGetWindow
228c041511dScube *
229c041511dScube *	DESCRIPTION:  set and get the current window
230c041511dScube ***********************************************************/
231c041511dScubevoid glutSetWindow(int win) {
232c041511dScube  GlutWindow *window;
233c041511dScube
234c041511dScube  if (win < 1 || win > gState.windowListSize) {
235c041511dScube    __glutWarning("glutSetWindow attempted on bogus window.");
236c041511dScube    return;
237c041511dScube  }
238c041511dScube  window = gState.windowList[win - 1];
239c041511dScube  if (!window) {
240c041511dScube    __glutWarning("glutSetWindow attempted on bogus window.");
241c041511dScube    return;
242c041511dScube  }
243c041511dScube  __glutSetWindow(window);
244c041511dScube}
245c041511dScube
246c041511dScubeint glutGetWindow() {
247c041511dScube  if (gState.currentWindow) {
248c041511dScube    return gState.currentWindow->num + 1;
249c041511dScube  } else {
250c041511dScube    return 0;
251c041511dScube  }
252c041511dScube}
253c041511dScube
254c041511dScube/***********************************************************
255c041511dScube *	FUNCTION:	__glutDestroyWindow
256c041511dScube *
257c041511dScube *	DESCRIPTION:  recursively set entries to 0
258c041511dScube ***********************************************************/
259c041511dScubestatic void
260c041511dScube__glutDestroyWindow(GlutWindow *window, GlutWindow *initialWindow) {
261c041511dScube	// first, find all children recursively and set their entries to 0
262c041511dScube	GlutWindow *cur = window->children;
263c041511dScube	while (cur) {
264c041511dScube		GlutWindow *siblings = cur->siblings;
265c041511dScube		__glutDestroyWindow(cur, initialWindow);
266c041511dScube		cur = siblings;
267c041511dScube	}
268c041511dScube
269c041511dScube  /* Remove from parent's children list (only necessary for
270c041511dScube     non-initial windows and subwindows!). */
271c041511dScube  GlutWindow *parent = window->parent;
272c041511dScube  if (parent && parent == initialWindow->parent) {
273c041511dScube    GlutWindow **prev = &parent->children;
274c041511dScube    cur = parent->children;
275c041511dScube    while (cur) {
276c041511dScube      if (cur == window) {
277c041511dScube        *prev = cur->siblings;
278c041511dScube        break;
279c041511dScube      }
280c041511dScube      prev = &(cur->siblings);
281c041511dScube      cur = cur->siblings;
282c041511dScube    }
283c041511dScube  }
284c041511dScube
285c041511dScube  // finally, check if we are the current window, and set to 0
286c041511dScube  if (gState.currentWindow == window) {
287c041511dScube  	gState.currentWindow = 0;
288c041511dScube  }
289c041511dScube  gState.windowList[window->num] = 0;
290c041511dScube}
291c041511dScube
292c041511dScube/***********************************************************
293c041511dScube *	FUNCTION:	glutDestroyWindow (4.4)
294c041511dScube *
295c041511dScube *	DESCRIPTION:  destroy window and all its children
296c041511dScube ***********************************************************/
297c041511dScubevoid glutDestroyWindow(int win) {
298c041511dScube	// can't destroy a window if another window has the GL context
299c041511dScube	if (gState.currentWindow)
300c041511dScube		gState.currentWindow->UnlockGL();
301c041511dScube
302c041511dScube	// lock the window
303c041511dScube	GlutWindow *window = gState.windowList[win-1];
304c041511dScube	BWindow *bwindow = window->Window();
305c041511dScube	bwindow->Lock();
306c041511dScube
307c041511dScube	// if win is the current window, set current window to 0
308c041511dScube	if (gState.currentWindow == window) {
309c041511dScube		gState.currentWindow = 0;
310c041511dScube	}
311c041511dScube
312c041511dScube	// recursively set child entries to 0
313c041511dScube	__glutDestroyWindow(window, window);
314c041511dScube
315c041511dScube	// try flushing OpenGL
316c041511dScube	window->LockGL();
317c041511dScube	glFlush();
318c041511dScube	window->UnlockGL();
319c041511dScube
320c041511dScube	// now, if the window was top-level, delete its BWindow
321c041511dScube	if(!window->parent) {
322c041511dScube		bwindow->Quit();
323c041511dScube	} else {
324c041511dScube		// else, detach it from the BWindow and delete it
325c041511dScube		window->RemoveSelf();
326c041511dScube		delete window;
327c041511dScube		bwindow->Unlock();
328c041511dScube	}
329c041511dScube	// relock GL if the current window is still valid
330c041511dScube	if(gState.currentWindow)
331c041511dScube		gState.currentWindow->LockGL();
332c041511dScube}
333c041511dScube
334c041511dScube/***********************************************************
335c041511dScube *	FUNCTION:	__glutDestroyAllWindows
336c041511dScube *
337c041511dScube *	DESCRIPTION:  destroy all windows when exit() is called
338c041511dScube *                this seems to be necessary to avoid delays
339c041511dScube *                and crashes when using BDirectWindow
340c041511dScube ***********************************************************/
341c041511dScubevoid __glutDestroyAllWindows() {
342c041511dScube	for(int i=0; i<gState.windowListSize; i++) {
343c041511dScube		if (gState.windowList[i]) {
344c041511dScube			glutDestroyWindow(i + 1);
345c041511dScube		}
346c041511dScube	}
347c041511dScube	gState.display->Lock();
348c041511dScube	gState.display->Quit();
349c041511dScube	status_t ignored;
350c041511dScube	wait_for_thread(gState.appthread, &ignored);
351c041511dScube}
352c041511dScube
353c041511dScube/***********************************************************
354c041511dScube *	FUNCTION:	glutPostRedisplay (4.5)
355c041511dScube *
356c041511dScube *	DESCRIPTION:  mark window as needing redisplay
357c041511dScube ***********************************************************/
358c041511dScubevoid glutPostRedisplay() {
359c041511dScube	gState.currentWindow->Window()->Lock();
360c041511dScube	gState.currentWindow->anyevents = true;
361c041511dScube	gState.currentWindow->displayEvent = true;
362c041511dScube	gState.currentWindow->Window()->Unlock();
363c041511dScube	gBlock.QuickNewEvent();
364c041511dScube}
365c041511dScube
366c041511dScube/***********************************************************
367c041511dScube *	FUNCTION:	glutPostWindowRedisplay
368c041511dScube *
369c041511dScube *	DESCRIPTION:  mark window as needing redisplay
370c041511dScube ***********************************************************/
371c041511dScubevoid glutPostWindowRedisplay(int win) {
372c041511dScube	GlutWindow *gwin = gState.windowList[win - 1];
373c041511dScube	gwin->Window()->Lock();
374c041511dScube	gwin->anyevents = true;
375c041511dScube	gwin->displayEvent = true;
376c041511dScube	gwin->Window()->Unlock();
377c041511dScube	gBlock.QuickNewEvent();
378c041511dScube}
379c041511dScube
380c041511dScube/***********************************************************
381c041511dScube *	FUNCTION:	glutSwapBuffers (4.6)
382c041511dScube *
383c041511dScube *	DESCRIPTION:  swap buffers
384c041511dScube ***********************************************************/
385c041511dScubevoid glutSwapBuffers() {
386c041511dScube	gState.currentWindow->SwapBuffers();
387c041511dScube}
388c041511dScube
389c041511dScube/***********************************************************
390c041511dScube *	FUNCTION:	glutPositionWindow (4.7)
391c041511dScube *
392c041511dScube *	DESCRIPTION:  move window
393c041511dScube ***********************************************************/
394c041511dScubevoid glutPositionWindow(int x, int y) {
395c041511dScube	BDirectWindow *win = dynamic_cast<BDirectWindow*>(gState.currentWindow->Window());
396c041511dScube	win->Lock();
397c041511dScube	if (gState.currentWindow->parent)
398c041511dScube		gState.currentWindow->MoveTo(x, y);	// move the child view
399c041511dScube	else {
400c041511dScube		if(win->IsFullScreen()) {
401c041511dScube			win->SetFullScreen(false);
402c041511dScube		}
403c041511dScube		win->MoveTo(x, y);  // move the window
404c041511dScube	}
405c041511dScube	win->Unlock();
406c041511dScube}
407c041511dScube
408c041511dScube/***********************************************************
409c041511dScube *	FUNCTION:	glutReshapeWindow (4.8)
410c041511dScube *
411c041511dScube *	DESCRIPTION:  reshape window (we'll catch the callback
412c041511dScube *				when the view gets a Draw() message
413c041511dScube ***********************************************************/
414c041511dScubevoid glutReshapeWindow(int width, int height) {
415c041511dScube	BDirectWindow *win = dynamic_cast<BDirectWindow*>(gState.currentWindow->Window());
416c041511dScube	win->Lock();
417c041511dScube	if (gState.currentWindow->parent)
418c041511dScube		gState.currentWindow->ResizeTo(width-1, height-1);		// resize the child
419c041511dScube	else {
420c041511dScube		if(win->IsFullScreen()) {
421c041511dScube			win->SetFullScreen(false);
422c041511dScube		}
423c041511dScube		win->ResizeTo(width-1, height-1);  // resize the parent
424c041511dScube	}
425c041511dScube	win->Unlock();
426c041511dScube}
427c041511dScube
428c041511dScube/***********************************************************
429c041511dScube *	FUNCTION:	glutFullScreen (4.9)
430c041511dScube *
431c041511dScube *	DESCRIPTION:  makes the window full screen
432c041511dScube ***********************************************************/
433c041511dScubevoid glutFullScreen() {
434c041511dScube	BDirectWindow *win = dynamic_cast<BDirectWindow*>(gState.currentWindow->Window());
435c041511dScube	win->Lock();
436c041511dScube	win->SetFullScreen(true);
437c041511dScube	win->Unlock();
438c041511dScube}
439c041511dScube
440c041511dScube/***********************************************************
441c041511dScube *	FUNCTION:	glutPopWindow (4.10)
442c041511dScube *				glutPushWindow
443c041511dScube *
444c041511dScube *	DESCRIPTION:  change the stacking order of the current window
445c041511dScube *		NOTE:	I can't figure out how to do this for windows,
446c041511dScube *				and there is no concept of "stacking order" for
447c041511dScube *				subwindows, so these are currently no-ops.
448c041511dScube ***********************************************************/
449c041511dScubevoid glutPopWindow() { }
450c041511dScubevoid glutPushWindow() { }
451c041511dScube
452c041511dScube/***********************************************************
453c041511dScube *	FUNCTION:	glutShowWindow (4.11)
454c041511dScube *				glutHideWindow
455c041511dScube *				glutIconifyWindow
456c041511dScube *
457c041511dScube *	DESCRIPTION:  change display status of current window
458c041511dScube ***********************************************************/
459c041511dScubevoid glutShowWindow() {
460c041511dScube	gState.currentWindow->Window()->Lock();
461c041511dScube	if (gState.currentWindow->parent)	// subwindow
462c041511dScube		gState.currentWindow->Show();
463c041511dScube	else {
464c041511dScube		if(gState.currentWindow->Window()->IsHidden())
465c041511dScube			gState.currentWindow->Window()->Show();	// show the actual BWindow
466c041511dScube		gState.currentWindow->Window()->Minimize(false);
467c041511dScube	}
468c041511dScube	gState.currentWindow->Window()->Unlock();
469c041511dScube}
470c041511dScube
471c041511dScubevoid glutHideWindow() {
472c041511dScube	gState.currentWindow->Window()->Lock();
473c041511dScube	if (gState.currentWindow->parent)	// subwindow
474c041511dScube		gState.currentWindow->Hide();
475c041511dScube	else
476c041511dScube		gState.currentWindow->Window()->Hide();	// show the actual BWindow
477c041511dScube	gState.currentWindow->Window()->Unlock();
478c041511dScube}
479c041511dScube
480c041511dScubevoid glutIconifyWindow() {
481c041511dScube	if(gState.currentWindow->parent)
482c041511dScube		__glutFatalError("can't iconify a subwindow");
483c041511dScube
484c041511dScube	gState.currentWindow->Window()->Lock();
485c041511dScube	gState.currentWindow->Window()->Minimize(true);
486c041511dScube	gState.currentWindow->Window()->Unlock();
487c041511dScube}
488c041511dScube
489c041511dScube/***********************************************************
490c041511dScube *	FUNCTION:	glutSetWindowTitle (4.12)
491c041511dScube *				glutSetIconTitle
492c041511dScube *
493c041511dScube *	DESCRIPTION:  set the window title (icon title is same)
494c041511dScube ***********************************************************/
495c041511dScubevoid glutSetWindowTitle(const char *name) {
496c041511dScube	if (gState.currentWindow->parent)
497c041511dScube		__glutFatalError("glutSetWindowTitle: isn't a top-level window");
498c041511dScube
499c041511dScube	gState.currentWindow->Window()->Lock();
500c041511dScube	gState.currentWindow->Window()->SetTitle(name);
501c041511dScube	gState.currentWindow->Window()->Unlock();
502c041511dScube}
503c041511dScube
504c041511dScubevoid glutSetIconTitle(const char *name) {
505c041511dScube	glutSetWindowTitle(name);
506c041511dScube}
507c041511dScube
508c041511dScube/***********************************************************
509c041511dScube *	FUNCTION:	__glutConvertDisplayMode
510c041511dScube *
511c041511dScube *	DESCRIPTION:  converts the current display mode into a BGLView
512c041511dScube *		display mode, printing warnings as appropriate.
513c041511dScube *
514c041511dScube *	PARAMETERS:	 if options is non-NULL, the current display mode is
515c041511dScube *		returned in it.
516c041511dScube *
517c041511dScube *	RETURNS:	1 if the current display mode is possible, else 0
518c041511dScube ***********************************************************/
519c041511dScubeint __glutConvertDisplayMode(unsigned long *options) {
520c041511dScube	if (gState.displayString) {
521c041511dScube		/* __glutDisplayString should be NULL except if
522c041511dScube       glutInitDisplayString has been called to register a
523c041511dScube       different display string.  Calling glutInitDisplayString
524c041511dScube       means using a string instead of an integer mask determine
525c041511dScube       the visual to use.  This big ugly code is in glutDstr.cpp */
526c041511dScube       return __glutConvertDisplayModeFromString(options);
527c041511dScube    }
528c041511dScube
529c041511dScube	if(options) {
530c041511dScube		ulong newoptions = 0;
531c041511dScube		if(gState.displayMode & GLUT_ACCUM)
532c041511dScube			newoptions |= BGL_ACCUM;
533c041511dScube		if(gState.displayMode & GLUT_ALPHA)
534c041511dScube			newoptions |= BGL_ALPHA;
535c041511dScube		if(gState.displayMode & GLUT_DEPTH)
536c041511dScube			newoptions |= BGL_DEPTH;
537c041511dScube		if(gState.displayMode & GLUT_DOUBLE)
538c041511dScube			newoptions |= BGL_DOUBLE;
539c041511dScube		if(gState.displayMode & GLUT_STENCIL)
540c041511dScube			newoptions |= BGL_STENCIL;
541c041511dScube		*options = newoptions;
542c041511dScube	}
543c041511dScube
544c041511dScube	if(gState.displayMode & GLUT_INDEX) {
545c041511dScube		__glutWarning("BeOS doesn't support indexed color");
546c041511dScube		return 0;
547c041511dScube	}
548c041511dScube	if(gState.displayMode & GLUT_MULTISAMPLE) {
549c041511dScube		return 1;	// try to go without multisampling
550c041511dScube	}
551c041511dScube	if(gState.displayMode & GLUT_STEREO) {
552c041511dScube		__glutWarning("BeOS doesn't support stereo windows");
553c041511dScube		return 0;
554c041511dScube	}
555c041511dScube	if(gState.displayMode & GLUT_LUMINANCE) {
556c041511dScube		__glutWarning("BeOS doesn't support luminance color model");
557c041511dScube		return 0;
558c041511dScube	}
559c041511dScube	return 1;	// visual supported
560c041511dScube}
561c041511dScube
562c041511dScube/***********************************************************
563c041511dScube *	CLASS:		GlutBWindow
564c041511dScube *
565c041511dScube *	DESCRIPTION:  very thin wrapper around BWindow
566c041511dScube ***********************************************************/
567c041511dScubeGlutBWindow::GlutBWindow(BRect frame, char *name) :
568c041511dScube			BDirectWindow(frame, name, B_TITLED_WINDOW, 0) {
569c041511dScube	fConnectionDisabled = false;
570c041511dScube	bgl = 0;
571c041511dScube	SetPulseRate(100000);
572c041511dScube
573c041511dScube	if (!SupportsWindowMode()) {
574c041511dScube		__glutFatalError("video card doesn't support windowed operation");
575c041511dScube	}
576c041511dScube}
577c041511dScube
578c041511dScubevoid GlutBWindow::DirectConnected( direct_buffer_info *info ) {
579c041511dScube	bgl->DirectConnected(info);
580c041511dScube	if(bgl && !fConnectionDisabled) {
581c041511dScube		bgl->EnableDirectMode(true);
582c041511dScube	}
583c041511dScube	int newVisState;
584c041511dScube	if((info->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_START) {
585c041511dScube		bgl->visible = true;
586c041511dScube	}
587c041511dScube	if(!bgl->visible || info->buffer_state == B_DIRECT_STOP)
588c041511dScube		newVisState = GLUT_HIDDEN;
589c041511dScube	else {
590c041511dScube		if (info->clip_list_count == 0)
591c041511dScube			newVisState = GLUT_FULLY_COVERED;
592c041511dScube		else if (info->clip_list_count == 1)
593c041511dScube			newVisState = GLUT_FULLY_RETAINED;
594c041511dScube		else
595c041511dScube			newVisState = GLUT_PARTIALLY_RETAINED;
596c041511dScube	}
597c041511dScube	if(newVisState != bgl->visState) {
598c041511dScube		bgl->visState = newVisState;
599c041511dScube		bgl->anyevents = bgl->windowStatusEvent = true;
600c041511dScube		gBlock.NewEvent();
601c041511dScube	}
602c041511dScube}
603c041511dScube
604c041511dScubeGlutBWindow::~GlutBWindow() {
605c041511dScube	fConnectionDisabled = true;
606c041511dScube	if(bgl) {
607c041511dScube		bgl->EnableDirectMode(false);
608c041511dScube	}
609c041511dScube	if(!IsHidden())
610c041511dScube		Hide();
611c041511dScube	Sync();
612c041511dScube}
613c041511dScube
614c041511dScubebool GlutBWindow::QuitRequested() {
615c041511dScube	gState.quitAll = true;
616c041511dScube	gBlock.NewEvent();
617c041511dScube	return false;	// don't quit now, wait for main thread to do it
618c041511dScube}
619c041511dScube
620c041511dScubevoid GlutBWindow::Minimize(bool minimize) {
621c041511dScube	bgl->visible = !minimize;
622c041511dScube	BWindow::Minimize(minimize);
623c041511dScube}
624c041511dScube
625c041511dScubevoid GlutBWindow::Hide() {
626c041511dScube	BWindow::Hide();
627c041511dScube	bgl->visible = false;
628c041511dScube}
629c041511dScube
630c041511dScubevoid GlutBWindow::Show() {
631c041511dScube	BWindow::Show();
632c041511dScube	bgl->visible = true;
633c041511dScube}
634