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