aboutsummaryrefslogtreecommitdiff
path: root/src/glut/beos/glutWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/glut/beos/glutWindow.cpp')
-rw-r--r--src/glut/beos/glutWindow.cpp633
1 files changed, 633 insertions, 0 deletions
diff --git a/src/glut/beos/glutWindow.cpp b/src/glut/beos/glutWindow.cpp
new file mode 100644
index 000000000..66ea2a00a
--- /dev/null
+++ b/src/glut/beos/glutWindow.cpp
@@ -0,0 +1,633 @@
+/***********************************************************
+ * Copyright (C) 1997, Be Inc. Copyright (C) 1999, Jake Hamby.
+ *
+ * This program is freely distributable without licensing fees
+ * and is provided without guarantee or warrantee expressed or
+ * implied. This program is -not- in the public domain.
+ *
+ *
+ * FILE: glutWindow.cpp
+ *
+ * DESCRIPTION: all the routines for dealing with GlutWindows
+ ***********************************************************/
+
+/***********************************************************
+ * Headers
+ ***********************************************************/
+#include <GL/glut.h>
+#include <stdlib.h>
+#include "glutint.h"
+#include "glutState.h"
+#include "glutBlocker.h"
+
+/***********************************************************
+ * FUNCTION: getUnusedWindowSlot
+ *
+ * DESCRIPTION: helper function to get a new window slot
+ ***********************************************************/
+static int
+getUnusedWindowSlot()
+{
+ int i;
+
+ /* Look for allocated, unused slot. */
+ for (i = 0; i < gState.windowListSize; i++) {
+ if (!gState.windowList[i]) {
+ return i;
+ }
+ }
+ /* Allocate a new slot. */
+ gState.windowListSize++;
+ gState.windowList = (GlutWindow **)
+ realloc(gState.windowList,
+ gState.windowListSize * sizeof(GlutWindow *));
+
+ if (!gState.windowList)
+ __glutFatalError("out of memory.");
+ gState.windowList[gState.windowListSize - 1] = NULL;
+ return gState.windowListSize - 1;
+}
+
+/***********************************************************
+ * FUNCTION: __glutDefaultDisplay
+ * __glutDefaultReshape
+ *
+ * DESCRIPTION: default display and reshape functions
+ ***********************************************************/
+static void
+__glutDefaultDisplay(void)
+{
+ /* XXX Remove the warning after GLUT 3.0. */
+ __glutWarning("The following is a new check for GLUT 3.0; update your code.");
+ __glutFatalError(
+ "redisplay needed for window %d, but no display callback.",
+ gState.currentWindow->num + 1);
+}
+
+void
+__glutDefaultReshape(int width, int height)
+{
+ /* Adjust the viewport of the window */
+ glViewport(0, 0, (GLsizei) width, (GLsizei) height);
+}
+
+/***********************************************************
+ * CLASS: GlutWindow
+ *
+ * FUNCTION: (constructor)
+ *
+ * DESCRIPTION: creates a new GLUT window
+ * note: subwindows don't resize, but top-level windows
+ * follow all sides
+ ***********************************************************/
+GlutWindow::GlutWindow(GlutWindow *nparent, char *name,
+ int x, int y, int width, int height, ulong options) :
+ BGLView(
+ (nparent ? BRect(x,y,x+width-1,y+height-1) :
+ BRect(0,0,width-1,height-1)), name,
+ (nparent ? B_FOLLOW_NONE : B_FOLLOW_ALL_SIDES),
+ B_WILL_DRAW|B_FRAME_EVENTS|B_FULL_UPDATE_ON_RESIZE|B_PULSE_NEEDED,
+ options)
+{
+ // add myself to window list
+ num = getUnusedWindowSlot();
+ gState.windowList[num] = this;
+
+ // set up parent/children relationships
+ parent = nparent;
+ if (parent) {
+ siblings = parent->children;
+ parent->children = this;
+ } else {
+ siblings = 0;
+ }
+ children = 0;
+
+ // initialize variables
+ cursor = GLUT_CURSOR_INHERIT; // default cursor
+ for (int i = 0; i < GLUT_MAX_MENUS; i++) {
+ menu[i] = 0;
+ }
+ m_width = width;
+ m_height = height;
+ m_buttons = 0;
+
+ // clear callbacks
+ display = __glutDefaultDisplay;
+ reshape = __glutDefaultReshape;
+ mouse = 0;
+ motion = 0;
+ passive = 0;
+ entry = 0;
+ keyboard = 0;
+ visibility = 0;
+ special = 0;
+ windowStatus = 0;
+
+ // clear event counters
+ anyevents = 1;
+ displayEvent = 1; // get a reshape and a display event right away
+ reshapeEvent = 1;
+ mouseEvent = 0;
+ motionEvent = 0;
+ passiveEvent = 0;
+ entryEvent = 0;
+ keybEvent = 0;
+ windowStatusEvent = 0; // DirectConnected() will report change in
+ visState = -1; // visibility
+ specialEvent = 0;
+ statusEvent = 0;
+ menuEvent = 0;
+ visible = true;
+ gBlock.QuickNewEvent();
+
+ // if i'm a subwindow, add me to my parent view
+ if (parent) {
+ parent->Window()->Lock();
+ parent->AddChild(this);
+ parent->Window()->Unlock();
+ } else {
+ // if I'm a top-level window, create my BWindow
+ GlutBWindow *mybwindow = new GlutBWindow(
+ BRect(x,y,x+width-1,y+height-1), name);
+ mybwindow->AddChild(this);
+ mybwindow->bgl = this;
+ mybwindow->Show();
+ }
+
+ // give me the keyboard focus (focus follows mouse, X style, as
+ // implemented in GlutWindow::MouseMoved())
+ Window()->Lock();
+ MakeFocus();
+ Window()->Unlock();
+
+ // make myself the default window
+ __glutSetWindow(this);
+}
+
+/***********************************************************
+ * FUNCTION: glutCreateWindow (4.1)
+ *
+ * DESCRIPTION: creates a new GLUT window
+ ***********************************************************/
+int glutCreateWindow(const char *name) {
+ if (!be_app)
+ __glutInit();
+
+ ulong options;
+ if (!__glutConvertDisplayMode(&options)) {
+ __glutWarning("visual with necessary capabilities not found.");
+ }
+
+ // if X or Y is negative, then start at a reasonable position
+ bool defaultxy = (gState.initX < 0) || (gState.initY < 0);
+
+ GlutWindow *window = new GlutWindow(0, const_cast<char*>(name),
+ (defaultxy ? 50 : gState.initX), (defaultxy ? 50 : gState.initY),
+ gState.initWidth, gState.initHeight, options);
+
+ return window->num + 1;
+}
+
+/***********************************************************
+ * FUNCTION: glutCreateSubWindow (4.2)
+ *
+ * DESCRIPTION: creates a new GLUT subwindow
+ * Note: a subwindow is a GlutWindow (which is actually
+ * a BGLView) without its own BWindow
+ ***********************************************************/
+int glutCreateSubWindow(int win, int x, int y, int width, int height) {
+ ulong options;
+ if (!__glutConvertDisplayMode(&options)) {
+ __glutFatalError("visual with necessary capabilities not found.");
+ }
+
+ GlutWindow *window = new GlutWindow(gState.windowList[win-1], "child",
+ x, y, width, height, options);
+
+ return window->num + 1;
+}
+
+/***********************************************************
+ * FUNCTION: __glutSetWindow
+ *
+ * DESCRIPTION: set the current window (utility function)
+ ***********************************************************/
+void
+__glutSetWindow(GlutWindow * window)
+{
+ if (gState.currentWindow)
+ gState.currentWindow->UnlockGL();
+ gState.currentWindow = window;
+ gState.currentWindow->LockGL();
+}
+
+/***********************************************************
+ * FUNCTION: glutSetWindow (4.3)
+ * glutGetWindow
+ *
+ * DESCRIPTION: set and get the current window
+ ***********************************************************/
+void glutSetWindow(int win) {
+ GlutWindow *window;
+
+ if (win < 1 || win > gState.windowListSize) {
+ __glutWarning("glutSetWindow attempted on bogus window.");
+ return;
+ }
+ window = gState.windowList[win - 1];
+ if (!window) {
+ __glutWarning("glutSetWindow attempted on bogus window.");
+ return;
+ }
+ __glutSetWindow(window);
+}
+
+int glutGetWindow() {
+ if (gState.currentWindow) {
+ return gState.currentWindow->num + 1;
+ } else {
+ return 0;
+ }
+}
+
+/***********************************************************
+ * FUNCTION: __glutDestroyWindow
+ *
+ * DESCRIPTION: recursively set entries to 0
+ ***********************************************************/
+static void
+__glutDestroyWindow(GlutWindow *window, GlutWindow *initialWindow) {
+ // first, find all children recursively and set their entries to 0
+ GlutWindow *cur = window->children;
+ while (cur) {
+ GlutWindow *siblings = cur->siblings;
+ __glutDestroyWindow(cur, initialWindow);
+ cur = siblings;
+ }
+
+ /* Remove from parent's children list (only necessary for
+ non-initial windows and subwindows!). */
+ GlutWindow *parent = window->parent;
+ if (parent && parent == initialWindow->parent) {
+ GlutWindow **prev = &parent->children;
+ cur = parent->children;
+ while (cur) {
+ if (cur == window) {
+ *prev = cur->siblings;
+ break;
+ }
+ prev = &(cur->siblings);
+ cur = cur->siblings;
+ }
+ }
+
+ // finally, check if we are the current window, and set to 0
+ if (gState.currentWindow == window) {
+ gState.currentWindow = 0;
+ }
+ gState.windowList[window->num] = 0;
+}
+
+/***********************************************************
+ * FUNCTION: glutDestroyWindow (4.4)
+ *
+ * DESCRIPTION: destroy window and all its children
+ ***********************************************************/
+void glutDestroyWindow(int win) {
+ // can't destroy a window if another window has the GL context
+ if (gState.currentWindow)
+ gState.currentWindow->UnlockGL();
+
+ // lock the window
+ GlutWindow *window = gState.windowList[win-1];
+ BWindow *bwindow = window->Window();
+ bwindow->Lock();
+
+ // if win is the current window, set current window to 0
+ if (gState.currentWindow == window) {
+ gState.currentWindow = 0;
+ }
+
+ // recursively set child entries to 0
+ __glutDestroyWindow(window, window);
+
+ // try flushing OpenGL
+ window->LockGL();
+ glFlush();
+ window->UnlockGL();
+
+ // now, if the window was top-level, delete its BWindow
+ if(!window->parent) {
+ bwindow->Quit();
+ } else {
+ // else, detach it from the BWindow and delete it
+ window->RemoveSelf();
+ delete window;
+ bwindow->Unlock();
+ }
+ // relock GL if the current window is still valid
+ if(gState.currentWindow)
+ gState.currentWindow->LockGL();
+}
+
+/***********************************************************
+ * FUNCTION: __glutDestroyAllWindows
+ *
+ * DESCRIPTION: destroy all windows when exit() is called
+ * this seems to be necessary to avoid delays
+ * and crashes when using BDirectWindow
+ ***********************************************************/
+void __glutDestroyAllWindows() {
+ for(int i=0; i<gState.windowListSize; i++) {
+ if (gState.windowList[i]) {
+ glutDestroyWindow(i + 1);
+ }
+ }
+ gState.display->Lock();
+ gState.display->Quit();
+ status_t ignored;
+ wait_for_thread(gState.appthread, &ignored);
+}
+
+/***********************************************************
+ * FUNCTION: glutPostRedisplay (4.5)
+ *
+ * DESCRIPTION: mark window as needing redisplay
+ ***********************************************************/
+void glutPostRedisplay() {
+ gState.currentWindow->Window()->Lock();
+ gState.currentWindow->anyevents = true;
+ gState.currentWindow->displayEvent = true;
+ gState.currentWindow->Window()->Unlock();
+ gBlock.QuickNewEvent();
+}
+
+/***********************************************************
+ * FUNCTION: glutPostWindowRedisplay
+ *
+ * DESCRIPTION: mark window as needing redisplay
+ ***********************************************************/
+void glutPostWindowRedisplay(int win) {
+ GlutWindow *gwin = gState.windowList[win - 1];
+ gwin->Window()->Lock();
+ gwin->anyevents = true;
+ gwin->displayEvent = true;
+ gwin->Window()->Unlock();
+ gBlock.QuickNewEvent();
+}
+
+/***********************************************************
+ * FUNCTION: glutSwapBuffers (4.6)
+ *
+ * DESCRIPTION: swap buffers
+ ***********************************************************/
+void glutSwapBuffers() {
+ gState.currentWindow->SwapBuffers();
+}
+
+/***********************************************************
+ * FUNCTION: glutPositionWindow (4.7)
+ *
+ * DESCRIPTION: move window
+ ***********************************************************/
+void glutPositionWindow(int x, int y) {
+ BDirectWindow *win = dynamic_cast<BDirectWindow*>(gState.currentWindow->Window());
+ win->Lock();
+ if (gState.currentWindow->parent)
+ gState.currentWindow->MoveTo(x, y); // move the child view
+ else {
+ if(win->IsFullScreen()) {
+ win->SetFullScreen(false);
+ }
+ win->MoveTo(x, y); // move the window
+ }
+ win->Unlock();
+}
+
+/***********************************************************
+ * FUNCTION: glutReshapeWindow (4.8)
+ *
+ * DESCRIPTION: reshape window (we'll catch the callback
+ * when the view gets a Draw() message
+ ***********************************************************/
+void glutReshapeWindow(int width, int height) {
+ BDirectWindow *win = dynamic_cast<BDirectWindow*>(gState.currentWindow->Window());
+ win->Lock();
+ if (gState.currentWindow->parent)
+ gState.currentWindow->ResizeTo(width-1, height-1); // resize the child
+ else {
+ if(win->IsFullScreen()) {
+ win->SetFullScreen(false);
+ }
+ win->ResizeTo(width-1, height-1); // resize the parent
+ }
+ win->Unlock();
+}
+
+/***********************************************************
+ * FUNCTION: glutFullScreen (4.9)
+ *
+ * DESCRIPTION: makes the window full screen
+ ***********************************************************/
+void glutFullScreen() {
+ BDirectWindow *win = dynamic_cast<BDirectWindow*>(gState.currentWindow->Window());
+ win->Lock();
+ win->SetFullScreen(true);
+ win->Unlock();
+}
+
+/***********************************************************
+ * FUNCTION: glutPopWindow (4.10)
+ * glutPushWindow
+ *
+ * DESCRIPTION: change the stacking order of the current window
+ * NOTE: I can't figure out how to do this for windows,
+ * and there is no concept of "stacking order" for
+ * subwindows, so these are currently no-ops.
+ ***********************************************************/
+void glutPopWindow() { }
+void glutPushWindow() { }
+
+/***********************************************************
+ * FUNCTION: glutShowWindow (4.11)
+ * glutHideWindow
+ * glutIconifyWindow
+ *
+ * DESCRIPTION: change display status of current window
+ ***********************************************************/
+void glutShowWindow() {
+ gState.currentWindow->Window()->Lock();
+ if (gState.currentWindow->parent) // subwindow
+ gState.currentWindow->Show();
+ else {
+ if(gState.currentWindow->Window()->IsHidden())
+ gState.currentWindow->Window()->Show(); // show the actual BWindow
+ gState.currentWindow->Window()->Minimize(false);
+ }
+ gState.currentWindow->Window()->Unlock();
+}
+
+void glutHideWindow() {
+ gState.currentWindow->Window()->Lock();
+ if (gState.currentWindow->parent) // subwindow
+ gState.currentWindow->Hide();
+ else
+ gState.currentWindow->Window()->Hide(); // show the actual BWindow
+ gState.currentWindow->Window()->Unlock();
+}
+
+void glutIconifyWindow() {
+ if(gState.currentWindow->parent)
+ __glutFatalError("can't iconify a subwindow");
+
+ gState.currentWindow->Window()->Lock();
+ gState.currentWindow->Window()->Minimize(true);
+ gState.currentWindow->Window()->Unlock();
+}
+
+/***********************************************************
+ * FUNCTION: glutSetWindowTitle (4.12)
+ * glutSetIconTitle
+ *
+ * DESCRIPTION: set the window title (icon title is same)
+ ***********************************************************/
+void glutSetWindowTitle(const char *name) {
+ if (gState.currentWindow->parent)
+ __glutFatalError("glutSetWindowTitle: isn't a top-level window");
+
+ gState.currentWindow->Window()->Lock();
+ gState.currentWindow->Window()->SetTitle(name);
+ gState.currentWindow->Window()->Unlock();
+}
+
+void glutSetIconTitle(const char *name) {
+ glutSetWindowTitle(name);
+}
+
+/***********************************************************
+ * FUNCTION: __glutConvertDisplayMode
+ *
+ * DESCRIPTION: converts the current display mode into a BGLView
+ * display mode, printing warnings as appropriate.
+ *
+ * PARAMETERS: if options is non-NULL, the current display mode is
+ * returned in it.
+ *
+ * RETURNS: 1 if the current display mode is possible, else 0
+ ***********************************************************/
+int __glutConvertDisplayMode(unsigned long *options) {
+ if (gState.displayString) {
+ /* __glutDisplayString should be NULL except if
+ glutInitDisplayString has been called to register a
+ different display string. Calling glutInitDisplayString
+ means using a string instead of an integer mask determine
+ the visual to use. This big ugly code is in glutDstr.cpp */
+ return __glutConvertDisplayModeFromString(options);
+ }
+
+ if(options) {
+ ulong newoptions = 0;
+ if(gState.displayMode & GLUT_ACCUM)
+ newoptions |= BGL_ACCUM;
+ if(gState.displayMode & GLUT_ALPHA)
+ newoptions |= BGL_ALPHA;
+ if(gState.displayMode & GLUT_DEPTH)
+ newoptions |= BGL_DEPTH;
+ if(gState.displayMode & GLUT_DOUBLE)
+ newoptions |= BGL_DOUBLE;
+ if(gState.displayMode & GLUT_STENCIL)
+ newoptions |= BGL_STENCIL;
+ *options = newoptions;
+ }
+
+ if(gState.displayMode & GLUT_INDEX) {
+ __glutWarning("BeOS doesn't support indexed color");
+ return 0;
+ }
+ if(gState.displayMode & GLUT_MULTISAMPLE) {
+ return 1; // try to go without multisampling
+ }
+ if(gState.displayMode & GLUT_STEREO) {
+ __glutWarning("BeOS doesn't support stereo windows");
+ return 0;
+ }
+ if(gState.displayMode & GLUT_LUMINANCE) {
+ __glutWarning("BeOS doesn't support luminance color model");
+ return 0;
+ }
+ return 1; // visual supported
+}
+
+/***********************************************************
+ * CLASS: GlutBWindow
+ *
+ * DESCRIPTION: very thin wrapper around BWindow
+ ***********************************************************/
+GlutBWindow::GlutBWindow(BRect frame, char *name) :
+ BDirectWindow(frame, name, B_TITLED_WINDOW, 0) {
+ fConnectionDisabled = false;
+ bgl = 0;
+ SetPulseRate(100000);
+
+ if (!SupportsWindowMode()) {
+ __glutFatalError("video card doesn't support windowed operation");
+ }
+}
+
+void GlutBWindow::DirectConnected( direct_buffer_info *info ) {
+ bgl->DirectConnected(info);
+ if(bgl && !fConnectionDisabled) {
+ bgl->EnableDirectMode(true);
+ }
+ int newVisState;
+ if((info->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_START) {
+ bgl->visible = true;
+ }
+ if(!bgl->visible || info->buffer_state == B_DIRECT_STOP)
+ newVisState = GLUT_HIDDEN;
+ else {
+ if (info->clip_list_count == 0)
+ newVisState = GLUT_FULLY_COVERED;
+ else if (info->clip_list_count == 1)
+ newVisState = GLUT_FULLY_RETAINED;
+ else
+ newVisState = GLUT_PARTIALLY_RETAINED;
+ }
+ if(newVisState != bgl->visState) {
+ bgl->visState = newVisState;
+ bgl->anyevents = bgl->windowStatusEvent = true;
+ gBlock.NewEvent();
+ }
+}
+
+GlutBWindow::~GlutBWindow() {
+ fConnectionDisabled = true;
+ if(bgl) {
+ bgl->EnableDirectMode(false);
+ }
+ if(!IsHidden())
+ Hide();
+ Sync();
+}
+
+bool GlutBWindow::QuitRequested() {
+ gState.quitAll = true;
+ gBlock.NewEvent();
+ return false; // don't quit now, wait for main thread to do it
+}
+
+void GlutBWindow::Minimize(bool minimize) {
+ bgl->visible = !minimize;
+ BWindow::Minimize(minimize);
+}
+
+void GlutBWindow::Hide() {
+ BWindow::Hide();
+ bgl->visible = false;
+}
+
+void GlutBWindow::Show() {
+ BWindow::Show();
+ bgl->visible = true;
+}