Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

FltkOpenGLDisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: FltkOpenGLDisplayDevice.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.77 $       $Date: 2020/04/23 07:07:42 $
00014  *
00015  ***************************************************************************/
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include "FltkOpenGLDisplayDevice.h"
00028 #include "Inform.h"
00029 #include "utilities.h"
00030 #include "config.h"   // VMD version strings etc
00031 #include "VMDApp.h"  
00032 #include "FL/Fl.H"
00033 #include "FL/Fl_Gl_Window.H"
00034 #include "FL/forms.H"
00035 
00036 // FLTK High-DPI display support:
00037 //   FLTK versions 1.3.5 and later incorporate Apple-specific extensions
00038 //   for retina display support.  
00039 //
00040 //   On Apple MacOS when High-DPI Retina displays are enabled, 
00041 //   FLTK apparently uses a hard-coded 2:1 pixel to drawing unit scale factor 
00042 //
00043 //   High-DPI support on Win32, Win64, and X-Windows require further
00044 //   special handling available only in FLTK 1.4.x, which was redesigned with
00045 //   a new per-screen scale factor:
00046 //     https://www.fltk.org/doc-1.4/drawing.html
00047 //
00048 //   On Windows, X-Windows, the window-specific scale factor is:
00049 //     int nscreen = windows->screen_num();
00050 //     float s = Fl::screen_scale(nscreen);
00051 //
00052 //   The active scale factor can be overridden with the use of the
00053 //   FLTK_SCALING_FACTOR environment variable, and FLTK windows
00054 //   will respond to (cmd | ctrl)/+/-/0 (like a web browser) to allow
00055 //   interactive adjustment of scaling factor.
00056 //   FLTK 1.4.x adds Fl_Image::scale() to impact image drawing.
00057 //
00058 // Older discussions:
00059 //   https://www.oyranos.org/2016/01/high-dpi-with-fltk/index.html
00060 //   https://groups.google.com/forum/#!topic/fltkgeneral/qS-A50x6owk
00061 //
00062 #if defined(__APPLE__)
00063 #if (FL_MAJOR_VERSION >= 1) && (((FL_MINOR_VERSION >= 3) && (FL_PATCH_VERSION >= 5)) || (FL_MINOR_VERSION >= 4))
00064 #define VMDFLTKUSEHIGHDPIRETINA 1
00065 #endif
00066 #endif
00067 
00070 class myglwindow : public Fl_Gl_Window {
00071   FltkOpenGLDisplayDevice *dispdev;
00072   VMDApp *app;     // cached VMDApp handle for use in drag-and-drop
00073   int dragpending; // flag indicating incoming PASTE event is drag-and-drop
00074 
00075 public:
00076   myglwindow(int wx, int wy, int width, int height, const char *nm, 
00077     FltkOpenGLDisplayDevice *d, VMDApp *vmdapp) 
00078   : Fl_Gl_Window(wx, wy, width, height, nm), dispdev(d), app(vmdapp), dragpending(0) {
00079     // XXX this may not be reliable on MacOS X with recent revs of FLTK
00080     size_range(1,1,0,0); // resizable to full screen
00081   }
00082 
00083 
00084   int handle(int event) {
00085     // handle paste operations
00086     if (event == FL_PASTE) {
00087       // ignore paste operations that weren't due to drag-and-drop
00088       // since they could be any arbitrary data/text, and not just filenames.
00089       if (dragpending) {
00090         int len = Fl::event_length();
00091 
00092         // ignore zero-length paste events (why do these occur???)
00093         if (len > 0) {
00094           int numfiles, i;
00095           const char *lastc;
00096           int lasti;
00097           FileSpec spec;
00098           const char *ctext = Fl::event_text();
00099           char *filename = (char *) malloc((1 + len) * sizeof(char));
00100 
00101           for (lasti=0,lastc=ctext,numfiles=0,i=0; i<len; i++) {
00102             // parse out all but last filename, which doesn't have a CR
00103             if (ctext[i] == '\n') {
00104               memcpy(filename, lastc, (i-lasti)*sizeof(char));
00105               filename[i-lasti] = '\0';
00106   
00107               // attempt to load the file into a new molecule
00108               app->molecule_load(-1, filename, NULL, &spec);
00109   
00110               lasti=i+1;
00111               lastc=&ctext[lasti];
00112               numfiles++;
00113             }
00114   
00115             // special-case last filename, since there's no CR
00116             if (i == (len-1)) {
00117               memcpy(filename, lastc, (1+i-lasti)*sizeof(char));
00118               filename[1+i-lasti] = '\0';
00119   
00120               // attempt to load the file into a new molecule
00121               app->molecule_load(-1, filename, NULL, &spec);
00122               numfiles++;
00123             }
00124           }
00125   
00126           free(filename);
00127         }
00128   
00129         dragpending = 0; // no longer waiting for drag-and-drop paste
00130       }
00131   
00132       return 1; // indicate that we handled the paste operation
00133     }
00134 
00135     // handle drag-and-drop operations
00136     if (event == FL_DND_ENTER || event == FL_DND_DRAG) {
00137       return 1; // indicate that we want the drag-and-drop operation
00138     }
00139     if (event == FL_DND_RELEASE) {
00140       Fl::paste(*this);
00141       dragpending = 1; // flag to expect incoming paste due to DND operation
00142       return 1;
00143     }
00144     // end of cut-paste and drag-and-drop handling
00145 
00146     switch (event) {
00147       case FL_MOUSEWHEEL:
00148         dispdev->lastevent = event;
00149         dispdev->lastzdelta = Fl::event_dy();
00150         break;
00151       case FL_PUSH:
00152         dispdev->lastevent = event;
00153         dispdev->lastbtn = Fl::event_button();
00154         if (dispdev->lastbtn == FL_LEFT_MOUSE && Fl::event_state(FL_META)) {
00155           dispdev->lastbtn = FL_MIDDLE_MOUSE; 
00156         }
00157         break;
00158       case FL_DRAG:
00159         dispdev->lastevent = event;
00160         break;
00161       case FL_RELEASE:
00162         dispdev->lastevent = event;
00163         break;
00164 #if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 1)
00165       case FL_KEYDOWN:
00166 #else
00167       // This event code is superceded by FL_KEYDOWN in newer revs of FLTK
00168       case FL_KEYBOARD:
00169 #endif
00170         dispdev->lastevent = event;
00171         dispdev->lastkeycode = Fl::event_key();
00172         dispdev->lastbtn = *Fl::event_text();
00173         break; 
00174       default:
00175         return Fl_Gl_Window::handle(event);
00176     }
00177     return 1;
00178   }
00179   void draw() {
00180     dispdev->reshape();
00181     dispdev->_needRedraw = 1;
00182     app->VMDupdate(VMD_IGNORE_EVENTS);
00183   }    
00184   // override the hide() method since we have no way of getting it back
00185   void hide() {
00186     if (fl_show_question("Really Quit?", 0))
00187       app->VMDexit("",0,0);
00188   }
00189 };
00190  
00191 
00192 // static data for this object
00193 static const char *glStereoNameStr[OPENGL_STEREO_MODES] = 
00194  { "Off", 
00195    "QuadBuffered", 
00196    "HDTV SideBySide",
00197    "Checkerboard",
00198    "ColumnInterleaved",
00199    "RowInterleaved",
00200    "Anaglyph", 
00201    "SideBySide", 
00202    "AboveBelow",
00203    "Left", 
00204    "Right" };
00205 
00206 static const char *glRenderNameStr[OPENGL_RENDER_MODES] =
00207 { "Normal",
00208   "GLSL",
00209   "Acrobat3D" }; 
00210 
00211 static const char *glCacheNameStr[OPENGL_CACHE_MODES] =
00212 { "Off",
00213   "On" };
00214 
00216 
00217 // constructor ... open a window and set initial default values
00218 FltkOpenGLDisplayDevice::FltkOpenGLDisplayDevice(int argc, char **argv, 
00219   VMDApp *vmdapp_p, int *size, int *loc)
00220     : OpenGLRenderer((char *) "VMD " VMDVERSION " OpenGL Display") {
00221 
00222   vmdapp = vmdapp_p; // save VMDApp handle for use by drag-and-drop handlers, 
00223                      // and GPU memory management routines
00224 
00225   // set up data possible before opening window
00226   stereoNames = glStereoNameStr;
00227   stereoModes = OPENGL_STEREO_MODES;
00228 
00229   // GLSL is only available on MacOS X 10.4 and later.
00230   renderNames = glRenderNameStr;
00231   renderModes = OPENGL_RENDER_MODES;
00232 
00233   cacheNames = glCacheNameStr;
00234   cacheModes = OPENGL_CACHE_MODES;
00235 
00236 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00237   if (getenv("VMDNOHIGHDPI") != NULL) {
00238     msgWarn << "User override: High-DPI OpenGL display support disabled." << sendmsg;
00239   } else {
00240     // Enable High-DPI support on Apple Retina displays when supported by
00241     // the underlying FLTK version
00242     // Global FLTK function to activate support for high-DPI Apple Retina
00243     // displays.  This must be called before _any_ Fl_Gl_Window is shown.
00244     // When active, the pixel_w() and pixel_h() methods must be used instead
00245     // of w() and h(), e.g., glViewport(0, 0, pixel_w(), pixel_h()).
00246     Fl::use_high_res_GL(1);
00247     msgInfo << "High-DPI OpenGL display support enabled." << sendmsg;
00248   }
00249 #endif
00250 
00251   // open the window
00252   int SX = 100, SY = 100, W, H;
00253 
00254   W = size[0];
00255   H = size[1];
00256   if (loc) {
00257     SX = loc[0];
00258     SY = loc[1];
00259   }
00260   window = new myglwindow(SX, SY, W, H, name, this, vmdapp_p);
00261 
00262   ext->hasstereo = FALSE;         // stereo is off initially
00263   ext->stereodrawforced = FALSE;  // stereo not forced initially
00264   ext->hasmultisample = FALSE;    // multisample is off initially
00265 
00266   int rc=0;
00267 // FLTK stereo support only started working for MacOS X at around version 1.1.7
00268 #if (FL_MAJOR_VERSION >= 1) && (((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)) || ((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)))
00269   // find an appropriate visual and colormap ...
00270   if (getenv("VMDPREFERSTEREO") != NULL) {
00271     // Stereo limps along with FLTK 1.1.7 on MacOS X
00272     rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_STEREO);
00273     ext->hasstereo = TRUE;
00274 #if defined(__APPLE__)
00275     ext->stereodrawforced = TRUE; // forced draw in stereo all the time when on
00276 #endif
00277   // FLTK multisample antialiasing still doesn't actually work in 
00278   // MacOS X as of FLTK 1.1.10...
00279 #if !defined(__APPLE__)
00280   //  } else if (getenv("VMDPREFERMULTISAMPLE") != NULL) {
00281   } else if (rc != 0) {
00282     rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_MULTISAMPLE);
00283     ext->hasmultisample = TRUE; // FLTK only does SGI multisample, no ARB yet
00284 #endif
00285   } else {
00286     rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
00287   }
00288 #else
00289   // find an appropriate visual and colormap ...
00290   rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
00291 #endif
00292 
00293   window->show();
00294   // (7) bind the rendering context to the window
00295   window->make_current();
00296 
00297   // (8) actually request the window to be displayed
00298   screenX = Fl::w();
00299   screenY = Fl::h();  
00300 
00301   // (9) configure the rendering properly
00302   setup_initial_opengl_state();  // setup initial OpenGL state
00303   
00304   // set flags for the capabilities of this display
00305   // whether we can do antialiasing or not.
00306   if (ext->hasmultisample) 
00307     aaAvailable = TRUE;  // we use multisampling over other methods
00308   else
00309     aaAvailable = FALSE; // no non-multisample implementation yet
00310 
00311   // set default settings
00312   if (ext->hasmultisample) {
00313     aa_on();  // enable fast multisample based antialiasing by default
00314               // other antialiasing techniques are slow, so only multisample
00315               // makes sense to enable by default.
00316   } 
00317 
00318   cueingAvailable = TRUE;
00319   cueing_on(); // leave depth cueing on by default, despite the speed hit.
00320 
00321   cullingAvailable = TRUE;
00322   culling_off();
00323 
00324   set_sphere_mode(sphereMode);
00325   set_sphere_res(sphereRes);
00326   set_line_width(lineWidth);
00327   set_line_style(lineStyle);
00328 
00329   // reshape and clear the display, which initializes some other variables
00330   reshape();
00331   normal();
00332   clear();
00333   update();
00334 }
00335 
00336 // destructor ... close the window
00337 FltkOpenGLDisplayDevice::~FltkOpenGLDisplayDevice(void) {
00338   free_opengl_ctx(); // free display lists, textures, etc
00339   delete window;
00340 }
00341 
00343 
00344 //
00345 // get the current state of the device's pointer (i.e. cursor if it has one)
00346 //
00347 
00348 // abs pos of cursor from lower-left corner of display
00349 int FltkOpenGLDisplayDevice::x(void) {
00350   //Fl::check();
00351 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00352   // Enable High-DPI support on Apple Retina displays when supported by
00353   // the underlying FLTK version
00354   // When FLTK high-DPI support is enabled, it is necessary to multiply
00355   // values returned by event_x() by the result of 
00356   // Fl_Gl_Window::pixels_per_unit() to get correct GL-window pixel 
00357   // coordinates.
00358   // XXX Docs bug: FLTK docs don't specify how event_x_root() is affected, but
00359   //     it appears to follow the same behavior as event_x().
00360   return Fl::event_x_root() * window->pixels_per_unit();  
00361 #elif 1
00362   return Fl::event_x_root();  
00363 #else
00364   int x, y;
00365   Fl::get_mouse(x, y);
00366   return x;  
00367 #endif
00368 }
00369 
00370 
00371 // same, for y direction
00372 int FltkOpenGLDisplayDevice::y(void) {
00373   //Fl::check();
00374 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00375   // Enable High-DPI support on Apple Retina displays when supported by
00376   // the underlying FLTK version
00377   // When FLTK high-DPI support is enabled, it is necessary to multiply
00378   // values returned by event_y() by the result of 
00379   // Fl_Gl_Window::pixels_per_unit() to get correct GL-window pixel 
00380   // coordinates.
00381   // XXX Docs bug: FLTK docs don't specify how event_y_root() is affected, but
00382   //     it appears to follow the same behavior as event_y().
00383   return screenY - (Fl::event_y_root() * window->pixels_per_unit());
00384 #elif 1
00385   return screenY - Fl::event_y_root();
00386 #else
00387   int x, y;
00388   Fl::get_mouse(x, y);
00389   return screenY - y;  
00390 #endif
00391 }
00392 
00393 // return the current state of the shift, control, and alt keys
00394 int FltkOpenGLDisplayDevice::shift_state(void) {
00395   Fl::check();
00396    
00397   int retval = 0;
00398   int keymask = (int) Fl::event_state();
00399   if (keymask & FL_SHIFT)
00400     retval |= SHIFT;
00401   if (keymask & FL_CTRL)
00402     retval |= CONTROL;
00403   if (keymask & FL_ALT)
00404     retval |= ALT;
00405   return retval;
00406 }
00407 
00408 // return the spaceball state, if any
00409 int FltkOpenGLDisplayDevice::spaceball(int *rx, int *ry, int *rz, int *tx, int *ty,
00410 int *tz, int *buttons) {
00411   // not implemented yet
00412   return 0;
00413 }
00414 
00415 
00416 // set the Nth cursor shape as the current one.  If no arg given, the
00417 // default shape (n=0) is used.
00418 void FltkOpenGLDisplayDevice::set_cursor(int n) {
00419   switch (n) {
00420     default:
00421     case DisplayDevice::NORMAL_CURSOR: window->cursor(FL_CURSOR_ARROW); break;
00422     case DisplayDevice::TRANS_CURSOR: window->cursor(FL_CURSOR_MOVE); break;
00423     case DisplayDevice::SCALE_CURSOR: window->cursor(FL_CURSOR_WE); break;
00424     case DisplayDevice::PICK_CURSOR: window->cursor(FL_CURSOR_CROSS); break;
00425     case DisplayDevice::WAIT_CURSOR: window->cursor(FL_CURSOR_WAIT); break;
00426   }
00427 }
00428 
00429 
00430 //
00431 // event handling routines
00432 //
00433 
00434 // read the next event ... returns an event type (one of the above ones),
00435 // and a value.  Returns success, and sets arguments.
00436 int FltkOpenGLDisplayDevice::read_event(long &retdev, long &retval) {
00437 #if !defined(__APPLE__)
00438     // disabled on OSX to avoid problems with Tcl/Tk mishandling events.
00439     // XXX this code was previously being used on MacOS X for Intel, but
00440     //     it seems that it should match what we do on PowerPC so we 
00441     //     do the same in all MacOS X cases now.
00442     Fl::check();
00443 #endif
00444   
00445   switch (lastevent) {
00446     case FL_MOUSEWHEEL:
00447       // XXX tests on the Mac show that FLTK is using a coordinate system 
00448       // backwards from what is used on Windows' zDelta value.
00449       if (lastzdelta < 0) {
00450         retdev = WIN_WHEELUP;
00451       } else {
00452         retdev = WIN_WHEELDOWN;
00453       }
00454       break;
00455     case FL_PUSH:
00456     case FL_DRAG:
00457     case FL_RELEASE:
00458       if (lastbtn == FL_LEFT_MOUSE) retdev = WIN_LEFT;
00459       else if (lastbtn == FL_MIDDLE_MOUSE) retdev = WIN_MIDDLE;
00460       else if (lastbtn == FL_RIGHT_MOUSE) retdev = WIN_RIGHT;
00461       else {
00462         //printf("unknown button: %d\n", lastbtn);
00463       }
00464       retval = (lastevent == FL_PUSH || lastevent == FL_DRAG);
00465       break;
00466   
00467 #if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 1)
00468     case FL_KEYDOWN:
00469 #else
00470     // This event code is superceded by FL_KEYDOWN in newer revs of FLTK
00471     case FL_KEYBOARD:
00472 #endif
00473       // check function keys first
00474       if (lastkeycode >= FL_F && lastkeycode <= FL_F_Last) {
00475         retdev = (lastkeycode - FL_F) + ((int) WIN_KBD_F1);
00476       } else {
00477         switch(lastkeycode) {
00478           case FL_Escape:      retdev = WIN_KBD_ESCAPE;    break;
00479           case FL_Up:          retdev = WIN_KBD_UP;        break;
00480           case FL_Down:        retdev = WIN_KBD_DOWN;      break;
00481           case FL_Left:        retdev = WIN_KBD_LEFT;      break;
00482           case FL_Right:       retdev = WIN_KBD_RIGHT;     break;
00483           case FL_Page_Up:     retdev = WIN_KBD_PAGE_UP;   break;
00484           case FL_Page_Down:   retdev = WIN_KBD_PAGE_UP;   break;
00485           case FL_Home:        retdev = WIN_KBD_HOME;      break;
00486           case FL_End:         retdev = WIN_KBD_END;       break;
00487           case FL_Insert:      retdev = WIN_KBD_INSERT;    break;
00488           case FL_Delete:      retdev = WIN_KBD_DELETE;    break;
00489 
00490           default:
00491             retdev = WIN_KBD;
00492             break;
00493         }
00494       }
00495       retval = lastbtn;
00496       break;
00497 
00498     default:
00499       return 0;
00500   }
00501   lastevent = 0;
00502   return 1;
00503 }
00504 
00505 //
00506 // virtual routines for preparing to draw, drawing, and finishing drawing
00507 //
00508 
00509 // reshape the display after a shape change
00510 void FltkOpenGLDisplayDevice::reshape(void) {
00511 
00512 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00513   // Enable High-DPI support on Apple Retina displays when supported by
00514   // the underlying FLTK version
00515   xSize = window->w() * window->pixels_per_unit();
00516   ySize = window->h() * window->pixels_per_unit();
00517   xOrig = window->x() * window->pixels_per_unit();
00518   yOrig = screenY - (window->y() * window->pixels_per_unit()) - ySize;
00519 #else
00520   xSize = window->w();
00521   ySize = window->h();
00522   xOrig = window->x();
00523   yOrig = screenY - window->y() - ySize;
00524 #endif
00525 
00526   switch (inStereo) {
00527     case OPENGL_STEREO_SIDE:
00528       set_screen_pos(0.5f * (float)xSize / (float)ySize);
00529       break;
00530 
00531     case OPENGL_STEREO_ABOVEBELOW:
00532       set_screen_pos(2.0f * (float)xSize / (float)ySize);
00533       break;
00534 
00535     case OPENGL_STEREO_STENCIL_CHECKERBOARD:
00536     case OPENGL_STEREO_STENCIL_COLUMNS:
00537     case OPENGL_STEREO_STENCIL_ROWS:
00538       enable_stencil_stereo(inStereo);
00539       set_screen_pos((float)xSize / (float)ySize);
00540       break;
00541 
00542     default:
00543       set_screen_pos((float)xSize / (float)ySize);
00544       break;
00545   }
00546 }
00547 
00548 unsigned char * FltkOpenGLDisplayDevice::readpixels_rgb3u(int &x, int &y) {
00549   unsigned char * img;
00550 
00551   x = xSize;
00552   y = ySize;
00553 
00554   if ((img = (unsigned char *) malloc(x * y * 3)) != NULL) {
00555 #if !defined(WIREGL) 
00556     glPixelStorei(GL_PACK_ALIGNMENT, 1);
00557     glReadPixels(0, 0, x, y, GL_RGB, GL_UNSIGNED_BYTE, img);
00558 #endif
00559   } else {
00560     x = 0;
00561     y = 0;
00562   } 
00563 
00564   return img; 
00565 }
00566 
00567 unsigned char * FltkOpenGLDisplayDevice::readpixels_rgba4u(int &x, int &y) {
00568   unsigned char * img;
00569 
00570   x = xSize;
00571   y = ySize;
00572 
00573   if ((img = (unsigned char *) malloc(x * y * 4)) != NULL) {
00574 #if !defined(WIREGL) 
00575     glPixelStorei(GL_PACK_ALIGNMENT, 1);
00576     glReadPixels(0, 0, x, y, GL_RGBA, GL_UNSIGNED_BYTE, img);
00577 #endif
00578   } else {
00579     x = 0;
00580     y = 0;
00581   } 
00582 
00583   return img; 
00584 }
00585 
00586 
00587 // update after drawing
00588 void FltkOpenGLDisplayDevice::update(int do_update) {
00589   if(do_update)
00590     window->swap_buffers();
00591 
00592   glDrawBuffer(GL_BACK);
00593 }
00594 
00595 void FltkOpenGLDisplayDevice::do_resize_window(int w, int h) {
00596 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00597   // when running in High-DPI / retina mode, the user specifies VMD image 
00598   // resolutions in real rendered pixels, not pseudo pixels, so we have to 
00599   // pre-divide out the scale factor since FLTK will multiply it back in.
00600   window->size(w / window->pixels_per_unit(), h / window->pixels_per_unit());
00601 #else
00602   window->size(w, h);
00603 #endif
00604 
00605   // XXX this may not be reliable on MacOS X with recent revs of FLTK
00606   window->size_range(1,1,0,0); // resizable to full screen
00607 }
00608 
00609 void FltkOpenGLDisplayDevice::do_reposition_window(int xpos, int ypos) {
00610   window->position(xpos, ypos);
00611   // XXX this may not be reliable on MacOS X with recent revs of FLTK
00612   window->size_range(1,1,0,0); // resizable to full screen
00613 }
00614 
00615 

Generated on Thu Dec 5 02:42:27 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002