Show
Ignore:
Timestamp:
06/19/08 15:49:36 (7 years ago)
Author:
robert
Message:

From Paul Melis, "Here is a reworked version of the osgviewerWX example. It changes the GraphicsWindowWX to only inherit from osgViewer::GraphicsWindow? and adds a standalone widget, called OSGCanvas, that derives from wxGLCanvas. This solves a problem with the GraphicsWindowWX instance being destructed twice (see "Crash in osgviewerWX" of June 12th on osg-users). At program exit, the main frame deletes all of its children widgets and therefore calls GraphicsWindowWX's destructor, bypassing OSG's reference counting. The GraphicsWindowWX instance is then later destructed a second time when the reference held by osg::Camera goes to zero. This bug isn't exposed by the example directly, but if people are going to use the example as a basis (like the poster in the mentioned thread) they very likely will run into this problem.
"

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgviewerWX/osgviewerWX.cpp

    r8350 r8459  
    99#include "wx/wx.h" 
    1010#endif 
     11 
     12// For wxCURSOR_BLANK below, but isn't used a.t.m. 
     13//#ifdef WIN32 
     14//#include "wx/msw/wx.rc" 
     15//#endif 
    1116 
    1217#include "osgviewerWX.h" 
     
    4146    //    - initialize 
    4247 
    43     int *attributes = new int[6]; 
     48    int *attributes = new int[7]; 
    4449    attributes[0] = int(WX_GL_DOUBLEBUFFER); 
    4550    attributes[1] = WX_GL_RGBA; 
     
    4853    attributes[4] = WX_GL_STENCIL_SIZE; 
    4954    attributes[5] = 8; 
    50  
    51     GraphicsWindowWX* gw = new GraphicsWindowWX(frame, wxID_ANY, wxDefaultPosition, 
    52                                                 wxSize(width, height), wxSUNKEN_BORDER, wxT("osgviewerWX"), attributes); 
     55    attributes[6] = 0; 
     56 
     57    OSGCanvas *canvas = new OSGCanvas(frame, wxID_ANY, wxDefaultPosition, 
     58        wxSize(width, height), wxSUNKEN_BORDER, wxT("osgviewerWX"), attributes); 
     59 
     60    GraphicsWindowWX* gw = new GraphicsWindowWX(canvas); 
     61 
     62    canvas->SetGraphicsWindow(gw); 
    5363 
    5464    osgViewer::Viewer *viewer = new osgViewer::Viewer; 
     
    102112} 
    103113 
    104 BEGIN_EVENT_TABLE(GraphicsWindowWX, wxGLCanvas) 
    105     EVT_SIZE                (GraphicsWindowWX::OnSize) 
    106     EVT_PAINT               (GraphicsWindowWX::OnPaint) 
    107     EVT_ERASE_BACKGROUND    (GraphicsWindowWX::OnEraseBackground) 
    108  
    109     EVT_CHAR                (GraphicsWindowWX::OnChar) 
    110     EVT_KEY_UP              (GraphicsWindowWX::OnKeyUp) 
    111  
    112     EVT_ENTER_WINDOW    (GraphicsWindowWX::OnMouseEnter) 
    113     EVT_LEFT_DOWN       (GraphicsWindowWX::OnMouseDown) 
    114     EVT_MIDDLE_DOWN     (GraphicsWindowWX::OnMouseDown) 
    115     EVT_RIGHT_DOWN      (GraphicsWindowWX::OnMouseDown) 
    116     EVT_LEFT_UP         (GraphicsWindowWX::OnMouseUp) 
    117     EVT_MIDDLE_UP       (GraphicsWindowWX::OnMouseUp) 
    118     EVT_RIGHT_UP        (GraphicsWindowWX::OnMouseUp) 
    119     EVT_MOTION          (GraphicsWindowWX::OnMouseMotion) 
     114BEGIN_EVENT_TABLE(OSGCanvas, wxGLCanvas) 
     115    EVT_SIZE                (OSGCanvas::OnSize) 
     116    EVT_PAINT               (OSGCanvas::OnPaint) 
     117    EVT_ERASE_BACKGROUND    (OSGCanvas::OnEraseBackground) 
     118 
     119    EVT_CHAR                (OSGCanvas::OnChar) 
     120    EVT_KEY_UP              (OSGCanvas::OnKeyUp) 
     121 
     122    EVT_ENTER_WINDOW        (OSGCanvas::OnMouseEnter) 
     123    EVT_LEFT_DOWN           (OSGCanvas::OnMouseDown) 
     124    EVT_MIDDLE_DOWN         (OSGCanvas::OnMouseDown) 
     125    EVT_RIGHT_DOWN          (OSGCanvas::OnMouseDown) 
     126    EVT_LEFT_UP             (OSGCanvas::OnMouseUp) 
     127    EVT_MIDDLE_UP           (OSGCanvas::OnMouseUp) 
     128    EVT_RIGHT_UP            (OSGCanvas::OnMouseUp) 
     129    EVT_MOTION              (OSGCanvas::OnMouseMotion) 
    120130END_EVENT_TABLE() 
    121131 
    122 GraphicsWindowWX::GraphicsWindowWX(wxWindow *parent, wxWindowID id, 
     132OSGCanvas::OSGCanvas(wxWindow *parent, wxWindowID id, 
    123133    const wxPoint& pos, const wxSize& size, long style, const wxString& name, int *attributes) 
    124134    : wxGLCanvas(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name, attributes) 
     
    126136    // default cursor to standard 
    127137    _oldCursor = *wxSTANDARD_CURSOR; 
     138} 
     139 
     140OSGCanvas::~OSGCanvas() 
     141{ 
     142} 
     143 
     144void OSGCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) ) 
     145{ 
     146    /* must always be here */ 
     147    wxPaintDC dc(this); 
     148} 
     149 
     150void OSGCanvas::OnSize(wxSizeEvent& event) 
     151{ 
     152    // this is also necessary to update the context on some platforms 
     153    wxGLCanvas::OnSize(event); 
     154 
     155    // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...) 
     156    int width, height; 
     157    GetClientSize(&width, &height); 
     158 
     159    if (_graphics_window.valid()) 
     160    { 
     161        // update the window dimensions, in case the window has been resized. 
     162        _graphics_window->getEventQueue()->windowResize(0, 0, width, height); 
     163        _graphics_window->resized(0,0,width,height); 
     164    } 
     165} 
     166 
     167void OSGCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) 
     168{ 
     169    /* Do nothing, to avoid flashing on MSW */ 
     170} 
     171 
     172void OSGCanvas::OnChar(wxKeyEvent &event) 
     173{ 
     174#if wxUSE_UNICODE 
     175    int key = event.GetUnicodeKey(); 
     176#else 
     177    int key = event.GetKeyCode(); 
     178#endif 
     179 
     180    if (_graphics_window.valid()) 
     181        _graphics_window->getEventQueue()->keyPress(key); 
     182 
     183    // If this key event is not processed here, we should call 
     184    // event.Skip() to allow processing to continue. 
     185} 
     186 
     187void OSGCanvas::OnKeyUp(wxKeyEvent &event) 
     188{ 
     189#if wxUSE_UNICODE 
     190    int key = event.GetUnicodeKey(); 
     191#else 
     192    int key = event.GetKeyCode(); 
     193#endif 
     194 
     195    if (_graphics_window.valid()) 
     196        _graphics_window->getEventQueue()->keyRelease(key); 
     197 
     198    // If this key event is not processed here, we should call 
     199    // event.Skip() to allow processing to continue. 
     200} 
     201 
     202void OSGCanvas::OnMouseEnter(wxMouseEvent &event) 
     203{ 
     204    // Set focus to ourselves, so keyboard events get directed to us 
     205    SetFocus(); 
     206} 
     207 
     208void OSGCanvas::OnMouseDown(wxMouseEvent &event) 
     209{ 
     210    if (_graphics_window.valid()) 
     211    { 
     212        _graphics_window->getEventQueue()->mouseButtonPress(event.GetX(), event.GetY(), 
     213            event.GetButton()); 
     214    } 
     215} 
     216 
     217void OSGCanvas::OnMouseUp(wxMouseEvent &event) 
     218{ 
     219    if (_graphics_window.valid()) 
     220    { 
     221        _graphics_window->getEventQueue()->mouseButtonRelease(event.GetX(), event.GetY(), 
     222            event.GetButton()); 
     223    } 
     224} 
     225 
     226void OSGCanvas::OnMouseMotion(wxMouseEvent &event) 
     227{ 
     228    if (_graphics_window.valid()) 
     229        _graphics_window->getEventQueue()->mouseMotion(event.GetX(), event.GetY()); 
     230} 
     231 
     232void OSGCanvas::UseCursor(bool value) 
     233{ 
     234    if (value) 
     235    { 
     236        // show the old cursor 
     237        SetCursor(_oldCursor); 
     238    } 
     239    else 
     240    { 
     241        // remember the old cursor 
     242        _oldCursor = GetCursor(); 
     243 
     244        // hide the cursor 
     245        //    - can't find a way to do this neatly, so create a 1x1, transparent image 
     246        wxImage image(1,1); 
     247        image.SetMask(true); 
     248        image.SetMaskColour(0, 0, 0); 
     249        wxCursor cursor(image); 
     250        SetCursor(cursor); 
     251 
     252        // On wxGTK, only works as of version 2.7.0 
     253        // (http://trac.wxwidgets.org/ticket/2946) 
     254        // SetCursor( wxStockCursor( wxCURSOR_BLANK ) ); 
     255    } 
     256} 
     257 
     258GraphicsWindowWX::GraphicsWindowWX(OSGCanvas *canvas) 
     259{ 
     260    _canvas = canvas; 
    128261 
    129262    _traits = new GraphicsContext::Traits; 
     263 
     264    wxPoint pos = _canvas->GetPosition(); 
     265    wxSize  size = _canvas->GetSize(); 
     266 
    130267    _traits->x = pos.x; 
    131268    _traits->y = pos.y; 
     
    134271 
    135272    init(); 
    136  
     273} 
     274 
     275GraphicsWindowWX::~GraphicsWindowWX() 
     276{ 
    137277} 
    138278 
     
    156296} 
    157297 
    158 GraphicsWindowWX::~GraphicsWindowWX() 
    159 { 
    160 } 
    161  
    162 void GraphicsWindowWX::OnPaint( wxPaintEvent& WXUNUSED(event) ) 
    163 { 
    164     /* must always be here */ 
    165     wxPaintDC dc(this); 
    166 } 
    167  
    168 void GraphicsWindowWX::OnSize(wxSizeEvent& event) 
    169 { 
    170     // this is also necessary to update the context on some platforms 
    171     wxGLCanvas::OnSize(event); 
    172  
    173     // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...) 
    174     int width, height; 
    175     GetClientSize(&width, &height); 
    176  
    177     // update the window dimensions, in case the window has been resized. 
    178     getEventQueue()->windowResize(0, 0, width, height); 
    179     resized(0,0,width,height); 
    180 } 
    181  
    182 void GraphicsWindowWX::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) 
    183 { 
    184     /* Do nothing, to avoid flashing on MSW */ 
    185 } 
    186  
    187 void GraphicsWindowWX::OnChar(wxKeyEvent &event) 
    188 { 
    189 #if wxUSE_UNICODE 
    190     int key = event.GetUnicodeKey(); 
    191 #else 
    192     int key = event.GetKeyCode(); 
    193 #endif 
    194     getEventQueue()->keyPress(key); 
    195  
    196     // If this key event is not processed here, we should call 
    197     // event.Skip() to allow processing to continue. 
    198 } 
    199  
    200 void GraphicsWindowWX::OnKeyUp(wxKeyEvent &event) 
    201 { 
    202 #if wxUSE_UNICODE 
    203     int key = event.GetUnicodeKey(); 
    204 #else 
    205     int key = event.GetKeyCode(); 
    206 #endif 
    207     getEventQueue()->keyRelease(key); 
    208  
    209     // If this key event is not processed here, we should call 
    210     // event.Skip() to allow processing to continue. 
    211 } 
    212  
    213 void GraphicsWindowWX::OnMouseEnter(wxMouseEvent &event) 
    214 { 
    215     // Set focus to ourselves, so keyboard events get directed to us 
    216     SetFocus(); 
    217 } 
    218  
    219 void GraphicsWindowWX::OnMouseDown(wxMouseEvent &event) 
    220 { 
    221     getEventQueue()->mouseButtonPress(event.GetX(), event.GetY(), 
    222         event.GetButton()); 
    223 } 
    224  
    225 void GraphicsWindowWX::OnMouseUp(wxMouseEvent &event) 
    226 { 
    227     getEventQueue()->mouseButtonRelease(event.GetX(), event.GetY(), 
    228         event.GetButton()); 
    229 } 
    230  
    231 void GraphicsWindowWX::OnMouseMotion(wxMouseEvent &event) 
    232 { 
    233     getEventQueue()->mouseMotion(event.GetX(), event.GetY()); 
    234 } 
    235  
    236  
    237298void GraphicsWindowWX::grabFocus() 
    238299{ 
    239     // focus this window 
    240     SetFocus(); 
     300    // focus the canvas 
     301    _canvas->SetFocus(); 
    241302} 
    242303 
     
    245306    // focus this window, if the pointer is in the window 
    246307    wxPoint pos = wxGetMousePosition(); 
    247     if (this == wxFindWindowAtPoint(pos)) { 
    248         SetFocus(); 
    249     } 
     308    if (wxFindWindowAtPoint(pos) == _canvas) 
     309        _canvas->SetFocus(); 
    250310} 
    251311 
    252312void GraphicsWindowWX::useCursor(bool cursorOn) 
    253313{ 
    254     if (cursorOn) { 
    255  
    256         // show the old cursor 
    257         SetCursor(_oldCursor); 
    258     } 
    259     else { 
    260  
    261         // remember the old cursor 
    262         _oldCursor = GetCursor(); 
    263  
    264         // hide the cursor 
    265         //    - can't find a way to do this neatly, so create a 1x1, transparent image 
    266         wxImage image(1,1); 
    267         image.SetMask(true); 
    268         image.SetMaskColour(0, 0, 0); 
    269         wxCursor cursor(image); 
    270         SetCursor(cursor); 
    271     } 
     314    _canvas->UseCursor(cursorOn); 
    272315} 
    273316 
    274317bool GraphicsWindowWX::makeCurrentImplementation() 
    275318{ 
    276     SetCurrent(); 
     319    _canvas->SetCurrent(); 
    277320    return true; 
    278321} 
     
    280323void GraphicsWindowWX::swapBuffersImplementation() 
    281324{ 
    282     SwapBuffers(); 
    283 } 
     325    _canvas->SwapBuffers(); 
     326}