|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $" 00003 // 00004 // GLUT emulation routines for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 // Emulation of Glut using fltk. 00029 00030 // GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996. 00031 // "This program is freely distributable without licensing fees and is 00032 // provided without guarantee or warrantee expressed or implied. This 00033 // program is -not- in the public domain." 00034 00035 // Although I have copied the GLUT API, none of my code is based on 00036 // any Glut implementation details and is therefore covered by the LGPL. 00037 00038 #include "flstring.h" 00039 #if HAVE_GL 00040 00041 # include <FL/glut.H> 00042 # ifdef HAVE_GLXGETPROCADDRESSARB 00043 # define GLX_GLXEXT_LEGACY 00044 # include <GL/glx.h> 00045 # endif // HAVE_GLXGETPROCADDRESSARB 00046 # ifdef HAVE_DLFCN_H 00047 # include <dlfcn.h> 00048 # endif // HAVE_DLFCN_H 00049 # define MAXWINDOWS 32 00050 static Fl_Glut_Window *windows[MAXWINDOWS+1]; 00051 00052 static void (*glut_idle_func)() = 0; // global glut idle function 00053 00054 Fl_Glut_Window *glut_window; 00055 int glut_menu; 00056 void (*glut_menustate_function)(int); 00057 void (*glut_menustatus_function)(int,int,int); 00058 00059 static void default_reshape(int w, int h) {glViewport(0,0,w,h);} 00060 static void default_display() {} 00061 00062 void Fl_Glut_Window::make_current() { 00063 glut_window = this; 00064 if (shown()) Fl_Gl_Window::make_current(); 00065 } 00066 00067 static int indraw; 00068 void Fl_Glut_Window::draw() { 00069 glut_window = this; 00070 indraw = 1; 00071 if (!valid()) {reshape(w(),h()); valid(1);} 00072 display(); 00073 indraw = 0; 00074 } 00075 00076 void glutSwapBuffers() { 00077 if (!indraw) glut_window->swap_buffers(); 00078 } 00079 00080 void Fl_Glut_Window::draw_overlay() { 00081 glut_window = this; 00082 if (!valid()) {reshape(w(),h()); valid(1);} 00083 overlaydisplay(); 00084 } 00085 00086 static void domenu(int, int, int); 00087 00088 int Fl_Glut_Window::handle(int event) { 00089 make_current(); 00090 int ex = Fl::event_x(); 00091 int ey = Fl::event_y(); 00092 int button; 00093 switch (event) { 00094 00095 case FL_PUSH: 00096 if (keyboard || special) Fl::focus(this); 00097 button = Fl::event_button()-1; 00098 if (button<0) button = 0; 00099 if (button>2) button = 2; 00100 if (menu[button]) {domenu(menu[button],ex,ey); return 1;} 00101 mouse_down |= 1<<button; 00102 if (mouse) {mouse(button,GLUT_DOWN,ex,ey); return 1;} 00103 if (motion) return 1; 00104 break; 00105 00106 case FL_MOUSEWHEEL: 00107 button = Fl::event_dy(); 00108 while (button < 0) {if (mouse) mouse(3,GLUT_DOWN,ex,ey); ++button;} 00109 while (button > 0) {if (mouse) mouse(4,GLUT_DOWN,ex,ey); --button;} 00110 return 1; 00111 00112 case FL_RELEASE: 00113 for (button = 0; button < 3; button++) if (mouse_down & (1<<button)) { 00114 if (mouse) mouse(button,GLUT_UP,ex,ey); 00115 } 00116 mouse_down = 0; 00117 return 1; 00118 00119 case FL_ENTER: 00120 if (entry) {entry(GLUT_ENTERED); return 1;} 00121 if (passivemotion) return 1; 00122 break; 00123 00124 case FL_LEAVE: 00125 if (entry) {entry(GLUT_LEFT); return 1;} 00126 if (passivemotion) return 1; 00127 break; 00128 00129 case FL_DRAG: 00130 if (motion) {motion(ex, ey); return 1;} 00131 break; 00132 00133 case FL_MOVE: 00134 if (passivemotion) {passivemotion(ex, ey); return 1;} 00135 break; 00136 00137 case FL_FOCUS: 00138 if (keyboard || special) return 1; 00139 break; 00140 00141 case FL_SHORTCUT: 00142 if (!keyboard && !special) break; 00143 00144 case FL_KEYBOARD: 00145 if (Fl::event_text()[0]) { 00146 if (keyboard) {keyboard(Fl::event_text()[0],ex,ey); return 1;} 00147 break; 00148 } else { 00149 if (special) { 00150 int k = Fl::event_key(); 00151 if (k > FL_F && k <= FL_F_Last) k -= FL_F; 00152 special(k,ex,ey); 00153 return 1; 00154 } 00155 break; 00156 } 00157 00158 case FL_HIDE: 00159 if (visibility) visibility(GLUT_NOT_VISIBLE); 00160 break; 00161 00162 case FL_SHOW: 00163 if (visibility) visibility(GLUT_VISIBLE); 00164 break; 00165 } 00166 00167 return Fl_Gl_Window::handle(event); 00168 } 00169 00170 static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH; 00171 00172 void Fl_Glut_Window::_init() { 00173 for (number=1; number<MAXWINDOWS; number++) if (!windows[number]) break; 00174 windows[number] = this; 00175 menu[0] = menu[1] = menu[2] = 0; 00176 reshape = default_reshape; 00177 display = default_display; 00178 overlaydisplay = default_display; 00179 keyboard = 0; 00180 mouse = 0; 00181 motion = 0; 00182 passivemotion = 0; 00183 entry = 0; 00184 visibility = 0; 00185 special = 0; 00186 mouse_down = 0; 00187 mode(glut_mode); 00188 } 00189 00191 Fl_Glut_Window::Fl_Glut_Window(int W, int H, const char *t) : 00192 Fl_Gl_Window(W,H,t) {_init();} 00193 00195 Fl_Glut_Window::Fl_Glut_Window(int X,int Y,int W,int H, const char *t) : 00196 Fl_Gl_Window(X,Y,W,H,t) {_init();} 00197 00198 static int initargc; 00199 static char **initargv; 00200 00201 void glutInit(int *argc, char **argv) { 00202 initargc = *argc; 00203 initargv = new char*[*argc+1]; 00204 int i,j; 00205 for (i=0; i<=*argc; i++) initargv[i] = argv[i]; 00206 for (i=j=1; i<*argc; ) { 00207 if (Fl::arg(*argc,argv,i)); 00208 else argv[j++] = argv[i++]; 00209 } 00210 argv[j] = 0; 00211 *argc = j; 00212 } 00213 00214 void glutInitDisplayMode(unsigned int mode) { 00215 glut_mode = mode; 00216 } 00217 00218 void glutMainLoop() {Fl::run();} 00219 00221 00222 static int initx=0, inity=0, initw=300, inith=300, initpos=0; 00223 00224 void glutInitWindowPosition(int x, int y) { 00225 initx = x; inity = y; initpos = 1; 00226 } 00227 00228 void glutInitWindowSize(int w, int h) { 00229 initw = w; inith = h; 00230 } 00231 00232 int glutCreateWindow(char *title) { 00233 return glutCreateWindow((const char*)title); 00234 } 00235 00236 int glutCreateWindow(const char *title) { 00237 Fl_Glut_Window *W; 00238 if (initpos) { 00239 W = new Fl_Glut_Window(initx,inity,initw,inith,title); 00240 initpos = 0; 00241 } else { 00242 W = new Fl_Glut_Window(initw,inith,title); 00243 } 00244 W->resizable(W); 00245 if (initargc) { 00246 W->show(initargc,initargv); 00247 initargc = 0; 00248 } else { 00249 W->show(); 00250 } 00251 W->valid(0); 00252 W->context_valid(0); 00253 W->make_current(); 00254 return W->number; 00255 } 00256 00257 int glutCreateSubWindow(int win, int x, int y, int w, int h) { 00258 Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0); 00259 windows[win]->add(W); 00260 if (windows[win]->shown()) W->show(); 00261 W->make_current(); 00262 return W->number; 00263 } 00265 Fl_Glut_Window::~Fl_Glut_Window() { 00266 if (glut_window == this) glut_window = 0; 00267 windows[number] = 0; 00268 } 00269 00270 void glutDestroyWindow(int win) { 00271 // should destroy children!!! 00272 delete windows[win]; 00273 } 00274 00275 void glutPostWindowRedisplay(int win) { 00276 windows[win]->redraw(); 00277 } 00278 00279 void glutSetWindow(int win) { 00280 windows[win]->make_current(); 00281 } 00282 00284 #include <FL/Fl_Menu_Item.H> 00285 00286 struct menu { 00287 void (*cb)(int); 00288 Fl_Menu_Item *m; 00289 int size; 00290 int alloc; 00291 }; 00292 00293 #define MAXMENUS 32 00294 static menu menus[MAXMENUS+1]; 00295 00296 static void domenu(int n, int ex, int ey) { 00297 glut_menu = n; 00298 menu *m = &menus[n]; 00299 if (glut_menustate_function) glut_menustate_function(1); 00300 if (glut_menustatus_function) glut_menustatus_function(1,ex,ey); 00301 const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0); 00302 if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument())); 00303 if (glut_menustatus_function) glut_menustatus_function(0,ex,ey); 00304 if (glut_menustate_function) glut_menustate_function(0); 00305 } 00306 00307 int glutCreateMenu(void (*cb)(int)) { 00308 int i; 00309 for (i=1; i<MAXMENUS; i++) if (!menus[i].cb) break; 00310 menu *m = &menus[i]; 00311 m->cb = cb; 00312 return glut_menu = i; 00313 } 00314 00315 void glutDestroyMenu(int n) { 00316 menu *m = &menus[n]; 00317 delete[] m->m; 00318 m->m = 0; 00319 m->cb = 0; 00320 m->size = m->alloc = 0; 00321 } 00322 00323 static Fl_Menu_Item* additem(menu *m) { 00324 if (m->size+1 >= m->alloc) { 00325 m->alloc = m->size*2+10; 00326 Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc]; 00327 for (int i=0; i<m->size; i++) nm[i] = m->m[i]; 00328 delete[] m->m; 00329 m->m = nm; 00330 } 00331 int n = m->size++; 00332 m->m[n+1].text = 0; 00333 Fl_Menu_Item* i = &(m->m[n]); 00334 i->shortcut_ = 0; 00335 i->flags = 0; 00336 i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0; 00337 return i; 00338 } 00339 00340 void glutAddMenuEntry(char *label, int value) { 00341 menu *m = &menus[glut_menu]; 00342 Fl_Menu_Item* i = additem(m); 00343 i->text = label; 00344 i->callback_ = (Fl_Callback*)(m->cb); 00345 i->user_data_ = (void *)value; 00346 } 00347 00348 void glutAddSubMenu(char *label, int submenu) { 00349 menu *m = &menus[glut_menu]; 00350 Fl_Menu_Item* i = additem(m); 00351 i->text = label; 00352 i->callback_ = 0; 00353 i->user_data_ = (void *)(menus[submenu].m); 00354 i->flags = FL_PUP_SUBMENU; 00355 } 00356 00357 void glutChangeToMenuEntry(int item, char *label, int value) { 00358 menu *m = &menus[glut_menu]; 00359 Fl_Menu_Item* i = &m->m[item-1]; 00360 i->text = label; 00361 i->callback_ = (Fl_Callback*)(m->cb); 00362 i->user_data_ = (void *)value; 00363 i->flags = 0; 00364 } 00365 00366 void glutChangeToSubMenu(int item, char *label, int submenu) { 00367 menu *m = &menus[glut_menu]; 00368 Fl_Menu_Item* i = &m->m[item-1]; 00369 i->text = label; 00370 i->callback_ = 0; 00371 i->user_data_ = (void *)(menus[submenu].m); 00372 i->flags = FL_PUP_SUBMENU; 00373 } 00374 00375 void glutRemoveMenuItem(int item) { 00376 menu *m = &menus[glut_menu]; 00377 if (item > m->size || item < 1) return; 00378 for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1]; 00379 m->size--; 00380 } 00381 00383 00384 int glutGet(GLenum type) { 00385 switch (type) { 00386 case GLUT_RETURN_ZERO: return 0; 00387 case GLUT_WINDOW_X: return glut_window->x(); 00388 case GLUT_WINDOW_Y: return glut_window->y(); 00389 case GLUT_WINDOW_WIDTH: return glut_window->w(); 00390 case GLUT_WINDOW_HEIGHT: return glut_window->h(); 00391 case GLUT_WINDOW_PARENT: 00392 if (glut_window->parent()) 00393 return ((Fl_Glut_Window *)(glut_window->parent()))->number; 00394 else 00395 return 0; 00396 //case GLUT_WINDOW_NUM_CHILDREN: 00397 //case GLUT_WINDOW_CURSOR: return 00398 case GLUT_SCREEN_WIDTH: return Fl::w(); 00399 case GLUT_SCREEN_HEIGHT: return Fl::h(); 00400 //case GLUT_SCREEN_WIDTH_MM: 00401 //case GLUT_SCREEN_HEIGHT_MM: 00402 case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size; 00403 case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode); 00404 case GLUT_INIT_WINDOW_X: return initx; 00405 case GLUT_INIT_WINDOW_Y: return inity; 00406 case GLUT_INIT_WINDOW_WIDTH: return initw; 00407 case GLUT_INIT_WINDOW_HEIGHT: return inith; 00408 case GLUT_INIT_DISPLAY_MODE: return glut_mode; 00409 //case GLUT_ELAPSED_TIME: 00410 case GLUT_WINDOW_BUFFER_SIZE: 00411 if (glutGet(GLUT_WINDOW_RGBA)) 00412 return glutGet(GLUT_WINDOW_RED_SIZE)+ 00413 glutGet(GLUT_WINDOW_GREEN_SIZE)+ 00414 glutGet(GLUT_WINDOW_BLUE_SIZE)+ 00415 glutGet(GLUT_WINDOW_ALPHA_SIZE); 00416 else 00417 return glutGet(GLUT_WINDOW_COLORMAP_SIZE); 00418 case GLUT_VERSION: return 20400; 00419 default: {GLint p; glGetIntegerv(type, &p); return p;} 00420 } 00421 } 00422 00423 int glutLayerGet(GLenum type) { 00424 switch (type) { 00425 case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay(); 00426 //case GLUT_LAYER_IN_USE: 00427 //case GLUT_HAS_OVERLAY: 00428 case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI 00429 case GLUT_NORMAL_DAMAGED: return glut_window->damage(); 00430 case GLUT_OVERLAY_DAMAGED: return 1; // kind of works... 00431 default: return 0; 00432 } 00433 } 00434 00435 int glutDeviceGet(GLenum type) { 00436 switch (type) { 00437 case GLUT_HAS_KEYBOARD : return 1; 00438 case GLUT_HAS_MOUSE : return 1; 00439 case GLUT_NUM_MOUSE_BUTTONS : return 3; 00440 default : return 0; 00441 } 00442 } 00443 00444 // Get extension function address... 00445 GLUTproc glutGetProcAddress(const char *procName) { 00446 # ifdef WIN32 00447 return (GLUTproc)wglGetProcAddress((LPCSTR)procName); 00448 00449 # elif defined(HAVE_DLSYM) && defined(HAVE_DLFCN_H) 00450 char symbol[1024]; 00451 00452 snprintf(symbol, sizeof(symbol), "_%s", procName); 00453 00454 # ifdef RTLD_DEFAULT 00455 return (GLUTproc)dlsym(RTLD_DEFAULT, symbol); 00456 00457 # else // No RTLD_DEFAULT support, so open the current a.out symbols... 00458 static void *rtld_default = 0; 00459 00460 if (!rtld_default) rtld_default = dlopen(0, RTLD_LAZY); 00461 00462 if (rtld_default) return (GLUTproc)dlsym(rtld_default, symbol); 00463 else return 0; 00464 00465 # endif // RTLD_DEFAULT 00466 00467 # elif defined(HAVE_GLXGETPROCADDRESSARB) 00468 return (GLUTproc)glXGetProcAddressARB((const GLubyte *)procName); 00469 00470 # else 00471 return (GLUTproc)0; 00472 # endif // WIN32 00473 } 00474 00475 // Parse the GL_EXTENSIONS string to see if the named extension is 00476 // supported. 00477 // 00478 // This code was copied from FreeGLUT 2.4.0 which carries the 00479 // following notice: 00480 // 00481 // Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 00482 int glutExtensionSupported( const char* extension ) 00483 { 00484 if (!extension || strchr(extension, ' ')) return 0; 00485 00486 const char *extensions, *start; 00487 const int len = strlen( extension ); 00488 00489 start = extensions = (const char *) glGetString(GL_EXTENSIONS); 00490 00491 if (!extensions) return 0; 00492 00493 for (;;) { 00494 const char *p = strstr(extensions, extension); 00495 if (!p) return 0; /* not found */ 00496 /* check that the match isn't a super string */ 00497 if ((p == start || p[-1] == ' ') && 00498 (p[len] == ' ' || p[len] == 0)) return 1; 00499 /* skip the false match and continue */ 00500 extensions = p + len; 00501 } 00502 } 00503 00504 // Add a mechanism to handle adding/removing the glut idle function 00505 // without depending on the (deprecated) set_idle method. 00506 void glutIdleFunc(void (*f)()) 00507 { 00508 // no change 00509 if(glut_idle_func == f) return; 00510 // remove current idle 00511 if(glut_idle_func) Fl::remove_idle((void (*)(void *))glut_idle_func); 00512 // install new idle func - if one was passed 00513 if(f) Fl::add_idle((void (*)(void *))f); 00514 // record new idle func - even if it is NULL 00515 glut_idle_func = f; 00516 } // glutIdleFunc 00517 00518 #endif // HAVE_GL 00519 00520 // 00521 // End of "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $". 00522 //