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

GlWindowWin32.cpp

Go to the documentation of this file.
00001 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00002  *
00003  * VR Juggler is (C) Copyright 1998-2003 by Iowa State University
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Christopher Just,
00007  *   Patrick Hartling, Kevin Meinert,
00008  *   Carolina Cruz-Neira, Albert Baker
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Library General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Library General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public
00021  * License along with this library; if not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023  * Boston, MA 02111-1307, USA.
00024  *
00025  * -----------------------------------------------------------------
00026  * File:          $RCSfile: GlWindowWin32.cpp,v $
00027  * Date modified: $Date: 2003/07/10 23:59:15 $
00028  * Version:       $Revision: 1.33 $
00029  * -----------------------------------------------------------------
00030  *
00031  *************** <auto-copyright.pl END do not edit this line> ***************/
00032 
00033 #include <vrj/vrjConfig.h>
00034 
00035 #include <jccl/Config/ConfigElement.h>
00036 
00037 #include <vpr/Util/Assert.h>
00038 #include <gadget/InputManager.h>
00039 #include <vrj/Util/Debug.h>
00040 #include <vrj/Kernel/Kernel.h>
00041 #include <vrj/Display/Display.h>
00042 #include <vrj/Display/DisplayManager.h>
00043 #include <vrj/Draw/OGL/GlWindow.h>
00044 #include <vrj/Draw/OGL/GlWindowWin32.h>
00045 
00046 #define GL_WINDOW_WIN32_CLASSNAME "vrj::GlWindowWin32"
00047 
00048 namespace vrj
00049 {
00050 
00051 GlWindowWin32::GlWindowWin32()
00052    : mMatch(NULL), mWinHandle(NULL), mRenderContext(NULL),
00053       mDeviceContext(NULL)
00054 {
00055 }
00056 GlWindowWin32::~GlWindowWin32()
00057 {
00058    this->close();
00059 }
00060 
00061 // Open the window
00062 // - Creates a window
00063 // - Creates a rendering context
00064 // - Registers new window with the window list
00065 int GlWindowWin32::open()
00066 {
00067    if ( false == GlWindowWin32::registerWindowClass() )
00068    {
00069       return 0;
00070    }
00071 
00072    if ( window_is_open )
00073    {
00074       return 1;
00075    }
00076 
00077    HMODULE hMod = GetModuleHandle(NULL);
00078    DWORD style;
00079    int root_height;
00080 
00081    // OpenGL requires WS_CLIPCHILDREN and WS_CLIPSIBLINGS.
00082    style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
00083 
00084    // If we want a border, create an overlapped window.  This will have
00085    // a titlebar and a border.
00086    if ( border )
00087    {
00088       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_HVERB_LVL) << "attempting to give window a border"
00089          << std::endl << vprDEBUG_FLUSH;
00090       style |= WS_OVERLAPPEDWINDOW;
00091    }
00092    // Otherwise, come as close as possible to having no border by using
00093    // the thin-line border.
00094    else
00095    {
00096       vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_HVERB_LVL) << "attempting to make window borderless"
00097          << std::endl << vprDEBUG_FLUSH;
00098       style |= WS_OVERLAPPED | WS_POPUP | WS_VISIBLE;
00099    }
00100 
00101    root_height = GetSystemMetrics(SM_CYSCREEN);
00102 
00103    // Create the main application window
00104    mWinHandle = CreateWindow(GL_WINDOW_WIN32_CLASSNAME,
00105                              GL_WINDOW_WIN32_CLASSNAME, style,
00106                              origin_x, root_height - origin_y - window_height,
00107                              window_width, window_height, NULL, NULL, hMod,
00108                              NULL);
00109 
00110    // If window was not created, quit
00111    if ( NULL == mWinHandle )
00112    {
00113       return 0;
00114    }
00115 
00116    // Attach a pointer to the device for use from the WNDPROC
00117    SetWindowLong( mWinHandle, GWL_USERDATA, (LPARAM)this );
00118 
00119    // We have a valid window, so... Create the context
00120    //case WM_CREATE:
00121    mDeviceContext = GetDC(mWinHandle);            // Store the device context
00122    if ( false == setPixelFormat(mDeviceContext) ) // Select the pixel format
00123    {
00124       return 0;
00125    }
00126 
00127    // Create the rendering context and make it current
00128    mRenderContext = wglCreateContext(mDeviceContext);
00129    vprASSERT(mRenderContext != NULL);
00130    wglMakeCurrent(mDeviceContext, mRenderContext);
00131 
00132    // Register the window with the window list
00133    GlWindowWin32::addWindow(mWinHandle,this);
00134 
00135    // Display the window
00136    ShowWindow(mWinHandle, SW_SHOW);
00137    UpdateWindow(mWinHandle);             // Tell the window to paint
00138    window_is_open = true;
00139 
00140    // ----------- Event window device starting -------------- //
00141    // Are we going to act like as an event source?
00142    if (true == mAreEventSource)
00143    {
00144       this->becomeEventWindowDevice();
00145    }
00146 
00147    return 1;
00148 }
00149 
00151 void GlWindowWin32::becomeEventWindowDevice()
00152 {
00153    // Set the parameters that we will need to get events
00154    gadget::EventWindowWin32::m_hWnd = mWinHandle;
00155 
00156    // Start up the device
00157    /*   Do it in out check event function
00158    gadget::EventWindowWin32::startSampling();
00159    */
00160 
00161    gadget::Input* dev_ptr = dynamic_cast<gadget::Input*>(this);
00162    vprASSERT( dev_ptr != NULL );
00163 
00164    // @todo Possibly not the best way to add this to input manager
00165    // - What happens when the event window is removed at run-time???
00166    // - What happens when this is called again?
00167    vrj::Kernel::instance()->getInputManager()->addDevice( dev_ptr );
00168 }
00169 
00170 void GlWindowWin32::removeEventWindowDevice()
00171 {
00172    gadget::EventWindowWin32::m_hWnd = 0;
00173 
00174    gadget::Input* dev_ptr = dynamic_cast<gadget::Input*>(this);
00175    vprASSERT( dev_ptr != NULL );
00176 
00177    // @todo Possibly not the best way to add this to input manager
00178    // - What happens when the event window is removed at run-time???
00179    // - What happens when this is called again?
00180 
00181    // @todo reenable this when InputManager::removeDevice(Input*) is public
00182    //vrj::Kernel::instance()->getInputManager()->removeDevice( dev_ptr );
00183 }
00184 
00189 int GlWindowWin32::close()
00190 {
00191    //vprASSERT( !mXfuncLock.test() && "Attempting to close a display window that is locked" );
00192    // Assert that we have not impllemented correct shutdown for the case that we
00193    // are an event window as well
00194    //vprASSERT(!mAreEventSource  && "Need to implement win32 window close with gadget::EventWindow");
00195 
00196    // if not open, then don't bother.
00197    if ( !window_is_open )
00198    {
00199       return false;
00200    }
00201 
00202    if (mAreEventSource)
00203    {
00204       this->removeEventWindowDevice();
00205    }
00206 
00207    // Remove window from window list
00208    GlWindowWin32::removeWindow(mWinHandle);
00209 
00210    window_is_open = false;
00211 
00212    // destroy the win32 window
00213    return(1 == DestroyWindow(mWinHandle));
00214 }
00215 
00220 bool GlWindowWin32::makeCurrent()
00221 {
00222    vprASSERT((mDeviceContext != NULL) && (mRenderContext != NULL));
00223    wglMakeCurrent(mDeviceContext, mRenderContext);  // Make our context current
00224    return true;
00225 }
00226 
00227 // Swap the front and back buffers
00228 // Process events here
00229 void GlWindowWin32::swapBuffers()
00230 {
00231    vprASSERT(mDeviceContext != NULL);
00232    SwapBuffers(mDeviceContext);
00233 }
00234 
00235 void GlWindowWin32::checkEvents()
00236 {
00237    if (true == mAreEventSource)
00238    {
00240       gadget::EventWindowWin32::sample();
00241       // if event source, use its event processor
00242       // it will pass all events up to this->processEvent()
00243       // when done, so that we can see the messages.
00244    }
00245    else
00246    {
00247       // not an event source, so pump our own events
00248       MSG win_message;
00249       while (PeekMessage( &win_message, NULL, 0, 0, PM_REMOVE ))
00250       {
00251          // Test if quit
00252          if (win_message.message == WM_QUIT)
00253          {
00254             break;
00255          }
00256 
00257          TranslateMessage( &win_message );     // Translate the accelerator keys
00258          DispatchMessage( &win_message );      // Send to the WinProc
00259       }
00260    }
00261 }
00262 
00263 void GlWindowWin32::processEvent( UINT message, UINT wParam, LONG lParam )
00264 {
00265 
00266 }
00267 
00268 void GlWindowWin32::configWindow( vrj::Display* disp )
00269 {
00270    const char neg_one_STRING[] = "-1";
00271    vprASSERT( disp != NULL );
00272    vrj::GlWindow::configWindow( disp );
00273 
00274     // Get the vector of display chunks
00275    jccl::ConfigElementPtr disp_sys_elt = DisplayManager::instance()->getDisplaySystemElement();
00276    jccl::ConfigElementPtr display_elt = disp->getConfigElement();
00277 
00278    window_name = disp->getName();
00279    mPipe = disp->getPipe();
00280    vprASSERT( mPipe >= 0 );
00281 
00282    mXDisplayName = disp_sys_elt->getProperty<std::string>("x11_pipes", mPipe);
00283    if (mXDisplayName == neg_one_STRING)    // Use display env
00284    {
00285        const std::string DISPLAY_str("DISPLAY");    // DISPLAY_str[] = "DISPLAY";
00286        const char* d = getenv(DISPLAY_str.c_str());
00287        if (NULL != d)
00288        {
00289           mXDisplayName = std::string( d );
00290        }
00291    }
00292    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_VERB_LVL)
00293       << "glxWindow::config: display name is: "
00294       << mXDisplayName << std::endl << vprDEBUG_FLUSH;
00295 
00296    bool was_i_a_keyboard = mAreEventSource;
00297    mAreEventSource = display_elt->getProperty<bool>("act_as_event_source");
00298 
00299    // If i'm being configured to NOT be an event source, and I was one already.
00300    if (false == mAreEventSource && true == was_i_a_keyboard)
00301    {
00302       this->removeEventWindowDevice();
00303    }
00304 
00305    // If i'm being configured to be an event source, and I wasn't one already.
00306    else if (true == mAreEventSource && false == was_i_a_keyboard)
00307    {
00308       // Configure event window device portion.
00309       jccl::ConfigElementPtr event_win_chunk =
00310          display_elt->getProperty<jccl::ConfigElementPtr>("event_window_device");
00311 
00312       // Set the name of the chunk to the same as the parent chunk (so we can point at it)
00313       //event_win_chunk->setProperty("name", display_elt->getName();
00314 
00315       gadget::EventWindowWin32::config(event_win_chunk);
00316 
00317       // Custom configuration
00318       gadget::EventWindowWin32::mWidth = GlWindowWin32::window_width;
00319       gadget::EventWindowWin32::mHeight = GlWindowWin32::window_height;
00320 
00321       mWeOwnTheWindow = false;      // Event window device does not own window
00322 
00323       // if the window is already open, then make it an event window device
00324       // otherwise, this will be called once the window opens.
00325       if (window_is_open)
00326       {
00327          this->becomeEventWindowDevice();
00328       }
00329    }
00330 }
00331 
00332 // WindowProcedure to deal with the events generated.
00333 // Called only for the window that we are controlling
00334 LRESULT GlWindowWin32::handleEvent( HWND hWnd, UINT message, WPARAM wParam,
00335                                     LPARAM lParam )
00336 {
00337    switch ( message )
00338    {
00339       // ---- Window creation, setup for OpenGL ---- //
00340       case WM_CREATE:
00341          vprASSERT(false);                               // Should never get called because
00342                                                          //we are not registered when this gets called
00343 
00344          mDeviceContext = GetDC(hWnd);                   // Store the device context
00345          if ( false == setPixelFormat(mDeviceContext) )  // Select the pixel format
00346          {
00347             return 0;
00348          }
00349 
00350          // Create the rendering context and make it current
00351          mRenderContext = wglCreateContext(mDeviceContext);
00352          wglMakeCurrent(mDeviceContext, mRenderContext);
00353          break;
00354 
00355          // ---- Window is being destroyed, cleanup ---- //
00356       case WM_DESTROY:
00357 
00358          // Deselect the current rendering context and delete it
00359          wglMakeCurrent(mDeviceContext, NULL);
00360          wglDeleteContext(mRenderContext);
00361 
00362          // Tell the application to terminate after the window
00363          // is gone.
00364          PostQuitMessage(0);
00365          break;
00366 
00367          // --- Window is resized. --- //
00368       case WM_SIZE:
00369          // Call our function which modifies the clipping
00370          // volume and viewport
00371          sizeChanged(LOWORD(lParam), HIWORD(lParam));
00372          break;
00373 
00374 
00375          // The painting function.  This message sent by Windows
00376          // whenever the screen needs updating.
00377       case WM_PAINT:
00378          {
00379             PAINTSTRUCT   ps;           // Paint structure
00380             BeginPaint(hWnd, &ps);  // Validate the drawing of the window
00381             EndPaint(hWnd, &ps);
00382          }
00383          break;
00384 
00385       default:   // Passes it on if unproccessed
00386          return(DefWindowProc(hWnd, message, wParam, lParam));
00387 
00388    }
00389 
00390    return(0L);
00391 }
00392 
00393 // Set the pixel format for the given window
00394 bool GlWindowWin32::setPixelFormat(HDC hDC)
00395 {
00396    int pixel_format;
00397    PIXELFORMATDESCRIPTOR pfd;
00398    mMatch = NULL;
00399 
00400    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
00401    pfd.nSize = (sizeof(PIXELFORMATDESCRIPTOR));
00402    pfd.nVersion = 1;
00403 
00404    /* Defaults. */
00405    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
00406 
00407    if ( mVrjDisplay->isStereoRequested() )
00408    {
00409       in_stereo = true;
00410       pfd.dwFlags |= PFD_STEREO;
00411    }
00412    else
00413    {
00414       in_stereo = false;
00415    }
00416 
00417    int red_size(8), green_size(8), blue_size(8), alpha_size(8), db_size(32);
00418    jccl::ConfigElementPtr gl_fb_chunk = mVrjDisplay->getGlFrameBufferConfig();
00419 
00420    if ( gl_fb_chunk.get() != NULL )
00421    {
00422       red_size   = gl_fb_chunk->getProperty<int>("red_size");
00423       green_size = gl_fb_chunk->getProperty<int>("green_size");
00424       blue_size  = gl_fb_chunk->getProperty<int>("blue_size");
00425       alpha_size = gl_fb_chunk->getProperty<int>("alpha_size");
00426       db_size    = gl_fb_chunk->getProperty<int>("depth_buffer_size");
00427 
00428       if ( red_size < 0 )
00429       {
00430          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00431             << "WARNING: Red channel size was negative, set to: " << red_size
00432             << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00433          red_size = 1;
00434       }
00435 
00436       if ( green_size < 0 )
00437       {
00438          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00439             << "WARNING: Green channel size was negative, set to: "
00440             << green_size << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00441          green_size = 1;
00442       }
00443 
00444       if ( blue_size < 0 )
00445       {
00446          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00447             << "WARNING: Blue channel size was negative, set to: " << blue_size
00448             << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00449          blue_size = 1;
00450       }
00451 
00452       if ( alpha_size < 0 )
00453       {
00454          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00455             << "WARNING: Alpha channel size was negative, set to: "
00456             << alpha_size << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00457          alpha_size = 1;
00458       }
00459 
00460       if ( db_size < 0 )
00461       {
00462          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_WARNING_LVL)
00463             << "WARNING: Depth buffer size was negative, set to: " << db_size
00464             << ".  Setting to 1.\n" << vprDEBUG_FLUSH;
00465          db_size = 1;
00466       }
00467    }
00468 
00469    vprDEBUG(vrjDBG_DISP_MGR, vprDBG_CONFIG_LVL)
00470       << "Frame buffer visual settings for " << mVrjDisplay->getName()
00471       << ": R:" << red_size << " G:" << green_size << " B:" << blue_size
00472       << " A:" << alpha_size << " DB:" << db_size << std::endl
00473       << vprDEBUG_FLUSH;
00474 
00475    pfd.iPixelType = PFD_TYPE_RGBA;
00476    pfd.cColorBits = 32;
00477    pfd.cRedBits = red_size;
00478    pfd.cGreenBits = green_size;
00479    pfd.cBlueBits = blue_size;
00480    pfd.cAlphaBits = alpha_size;
00481    pfd.cDepthBits = db_size;
00482    pfd.cStencilBits = 0;
00483    pfd.cAccumBits = 0;
00484    pfd.cAuxBuffers = 0;
00485 
00486    // Let Win32 choose one for us
00487    pixel_format = ChoosePixelFormat(hDC, &pfd);
00488    if ( pixel_format > 0 )
00489    {
00490       mMatch = (PIXELFORMATDESCRIPTOR *) malloc(sizeof(PIXELFORMATDESCRIPTOR));
00491       DescribePixelFormat(hDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
00492                           mMatch);
00493 
00494       /* ChoosePixelFormat is dumb in that it will return a pixel
00495          format that doesn't have stereo even if it was requested
00496          so we need to make sure that if stereo was selected, we
00497          got it. */
00498       if ( mVrjDisplay->isStereoRequested() )
00499       {
00500          if ( !(mMatch->dwFlags & PFD_STEREO) )
00501          {
00502             free(mMatch);
00503             return NULL;
00504          }
00505       }
00506    }
00507 
00508    // Set the pixel format for the device context
00509    SetPixelFormat(hDC, pixel_format, &pfd);
00510    return true;
00511 }
00512 
00513 // the user has changed the size of the window
00514 void GlWindowWin32::sizeChanged( long width, long height )
00515 {
00516    window_width = width;
00517    window_height = height;
00518 
00519    if ( window_width == 0 )        // Make sure we don't have window of 1 size (divide by zero would follow)
00520    {
00521       window_width = 1;
00522    }
00523 
00524    if ( window_height == 0 )
00525    {
00526       window_height = 1;
00527    }
00528 
00529    // XXX: Should reset viewport here
00530 }
00531 
00532 
00533 
00537 LRESULT CALLBACK GlWindowWin32::WndProc(HWND hWnd, UINT message,
00538                                         WPARAM wParam, LPARAM lParam)
00539 {
00540    GlWindowWin32* glWin = getGlWin(hWnd);
00541 
00542    if ( glWin != NULL )       // Message for one of ours
00543    {
00544       glWin->processEvent( message, wParam, lParam );
00545       return glWin->handleEvent(hWnd, message, wParam, lParam);
00546    }
00547    else
00548    {
00549       return DefWindowProc(hWnd, message, wParam, lParam);
00550    }
00551 }
00552 
00556 bool GlWindowWin32::mWinRegisteredClass = false;
00557 WNDCLASS GlWindowWin32::mWinClass;           // The window class to register
00558 std::map<HWND, GlWindowWin32*> GlWindowWin32::mGlWinMap;
00559 
00560 
00561 bool GlWindowWin32::registerWindowClass()
00562 {
00563    if ( mWinRegisteredClass )
00564    {
00565       return true;
00566    }
00567 
00568    char lpszAppName[1024];
00569    GetModuleFileName(NULL,lpszAppName,sizeof(lpszAppName));
00570 
00571    mWinRegisteredClass = true;     // We have registered now
00572 
00573    HINSTANCE hInstance = GetModuleHandle(NULL);
00574 
00575    // Register Window style
00576    mWinClass.style       = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
00577    mWinClass.lpfnWndProc = (WNDPROC)GlWindowWin32::WndProc;
00578    mWinClass.cbClsExtra  = 0;
00579    mWinClass.cbWndExtra  = 0;
00580    mWinClass.hInstance   = hInstance;            // Get handle to the module that created current process
00581    mWinClass.hIcon       = LoadIcon(NULL, IDI_WINLOGO);;
00582    mWinClass.hCursor     = LoadCursor(NULL, IDC_ARROW);
00583 
00584    // No need for background brush for OpenGL window
00585    mWinClass.hbrBackground  = NULL;
00586 
00587    mWinClass.lpszMenuName   = NULL;
00588    mWinClass.lpszClassName  = GL_WINDOW_WIN32_CLASSNAME;
00589 
00590    // Register the window class
00591    if ( RegisterClass(&mWinClass) == 0 )
00592    {
00593       return false;
00594    }
00595    else
00596    {
00597       return true;
00598    }
00599 }
00600 
00601 //----------------------//
00602 //      WinList         //
00603 //----------------------//
00604 void GlWindowWin32::addWindow(HWND handle, GlWindowWin32* glWin)
00605 {
00606    vprASSERT(glWin != NULL);
00607 
00608    if ( mGlWinMap.find(handle) == mGlWinMap.end() )     // Not already there
00609    {
00610       mGlWinMap[handle] = glWin;
00611    }
00612    //else
00613    // vprASSERT(false);
00614 }
00615 
00616 void GlWindowWin32::removeWindow(HWND handle)
00617 {
00618    mGlWinMap.erase(handle);     // Erase the entry in the list
00619 }
00620 
00621 GlWindowWin32* GlWindowWin32::getGlWin(HWND handle)
00622 {
00623    std::map<HWND, GlWindowWin32*>::iterator glWinIter;
00624 
00625    glWinIter = mGlWinMap.find(handle);
00626    if ( glWinIter == mGlWinMap.end() )     // Not found
00627    {
00628       return NULL;
00629    }
00630    else
00631    {
00632       return(*glWinIter).second;                 // Return the found window
00633    }
00634 }
00635 
00636 } // End of vrj namespace

Generated on Sun May 2 15:10:17 2004 for VR Juggler by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002