Changeset 8294

Show
Ignore:
Timestamp:
05/09/08 12:27:59
Author:
robert
Message:

From Jeremy Moles, fixed window resize problem

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • OpenSceneGraph/trunk/examples/osgviewerGTK/osggtkdrawingarea.cpp

    r8290 r8294  
    1 // by: Jeremy Moles <jeremy@emperorlinux.com> 2007 
    2  
    31#include "osggtkdrawingarea.h" 
    42 
     
    108_state    (0), 
    119_queue    (*getEventQueue()) { 
    12        setCameraManipulator(new osgGA::TrackballManipulator()); 
     10    setCameraManipulator(new osgGA::TrackballManipulator()); 
    1311} 
    1412 
     
    1715 
    1816bool OSGGTKDrawingArea::createWidget(int width, int height) { 
    19        _glconfig = gdk_gl_config_new_by_mode(static_cast<GdkGLConfigMode>( 
    20                GDK_GL_MODE_RGBA | 
    21                GDK_GL_MODE_DEPTH | 
    22                GDK_GL_MODE_DOUBLE 
    23        )); 
     17    _glconfig = gdk_gl_config_new_by_mode(static_cast<GdkGLConfigMode>( 
     18        GDK_GL_MODE_RGBA | 
     19        GDK_GL_MODE_DEPTH | 
     20        GDK_GL_MODE_DOUBLE 
     21    )); 
    2422 
    25        if(not _glconfig) { 
    26                osg::notify(osg::FATAL) << "Fail!" << std::endl; 
     23    if(not _glconfig) { 
     24        osg::notify(osg::FATAL) << "Fail!" << std::endl; 
    2725 
    28                return false; 
    29        
     26        return false; 
     27   
    3028 
    31        gtk_widget_set_size_request(_widget, width, height); 
     29    gtk_widget_set_size_request(_widget, width, height); 
    3230 
    33        gtk_widget_set_gl_capability( 
    34                _widget, 
    35                _glconfig, 
    36                0, 
    37                true, 
    38                GDK_GL_RGBA_TYPE 
    39        ); 
     31    gtk_widget_set_gl_capability( 
     32        _widget, 
     33        _glconfig, 
     34        0, 
     35        true, 
     36        GDK_GL_RGBA_TYPE 
     37    ); 
    4038 
    41        gtk_widget_add_events( 
    42                _widget, 
    43                GDK_BUTTON1_MOTION_MASK | 
    44                GDK_BUTTON2_MOTION_MASK | 
    45                GDK_BUTTON3_MOTION_MASK | 
    46                GDK_POINTER_MOTION_MASK | 
    47                GDK_BUTTON_PRESS_MASK | 
    48                GDK_BUTTON_RELEASE_MASK | 
    49                GDK_KEY_PRESS_MASK | 
    50                GDK_KEY_RELEASE_MASK | 
    51                GDK_VISIBILITY_NOTIFY_MASK 
    52        ); 
     39    gtk_widget_add_events( 
     40        _widget, 
     41        GDK_BUTTON1_MOTION_MASK | 
     42        GDK_BUTTON2_MOTION_MASK | 
     43        GDK_BUTTON3_MOTION_MASK | 
     44        GDK_POINTER_MOTION_MASK | 
     45        GDK_BUTTON_PRESS_MASK | 
     46        GDK_BUTTON_RELEASE_MASK | 
     47        GDK_KEY_PRESS_MASK | 
     48        GDK_KEY_RELEASE_MASK | 
     49        GDK_VISIBILITY_NOTIFY_MASK 
     50    ); 
    5351 
    54        // We do this so that we don't have to suck up ALL the input to the 
    55        // window, but instead just when the drawing area is focused. 
    56        g_object_set(_widget, "can-focus", true, NULL); 
     52    // We do this so that we don't have to suck up ALL the input to the 
     53    // window, but instead just when the drawing area is focused. 
     54    g_object_set(_widget, "can-focus", true, NULL); 
    5755 
    58        _connect("realize", G_CALLBACK(&OSGGTKDrawingArea::_srealize)); 
    59        _connect("unrealize", G_CALLBACK(&OSGGTKDrawingArea::_sunrealize)); 
    60        _connect("expose_event", G_CALLBACK(&OSGGTKDrawingArea::_sexpose_event)); 
    61        _connect("configure_event", G_CALLBACK(&OSGGTKDrawingArea::_sconfigure_event)); 
    62        _connect("motion_notify_event", G_CALLBACK(&OSGGTKDrawingArea::_smotion_notify_event)); 
    63        _connect("button_press_event", G_CALLBACK(&OSGGTKDrawingArea::_sbutton_press_event)); 
    64        _connect("button_release_event", G_CALLBACK(&OSGGTKDrawingArea::_sbutton_press_event)); 
    65        _connect("key_press_event", G_CALLBACK(&OSGGTKDrawingArea::_skey_press_event)); 
     56    _connect("realize", G_CALLBACK(&OSGGTKDrawingArea::_srealize)); 
     57    _connect("unrealize", G_CALLBACK(&OSGGTKDrawingArea::_sunrealize)); 
     58    _connect("expose_event", G_CALLBACK(&OSGGTKDrawingArea::_sexpose_event)); 
     59    _connect("configure_event", G_CALLBACK(&OSGGTKDrawingArea::_sconfigure_event)); 
     60    _connect("motion_notify_event", G_CALLBACK(&OSGGTKDrawingArea::_smotion_notify_event)); 
     61    _connect("button_press_event", G_CALLBACK(&OSGGTKDrawingArea::_sbutton_press_event)); 
     62    _connect("button_release_event", G_CALLBACK(&OSGGTKDrawingArea::_sbutton_press_event)); 
     63    _connect("key_press_event", G_CALLBACK(&OSGGTKDrawingArea::_skey_press_event)); 
    6664 
    67        setUpViewerAsEmbeddedInWindow(0, 0, width, height); 
     65    _gw = setUpViewerAsEmbeddedInWindow(0, 0, width, height); 
    6866 
    69        return true; 
     67    return true; 
    7068} 
    7169 
    7270void OSGGTKDrawingArea::_realize(GtkWidget* widget) { 
    73        _context  = gtk_widget_get_gl_context(widget); 
    74        _drawable = gtk_widget_get_gl_drawable(widget); 
     71    _context  = gtk_widget_get_gl_context(widget); 
     72    _drawable = gtk_widget_get_gl_drawable(widget); 
    7573 
    76        gtkRealize(); 
     74    gtkRealize(); 
    7775} 
    7876 
    7977void OSGGTKDrawingArea::_unrealize(GtkWidget* widget) { 
    80        gtkUnrealize(); 
     78    gtkUnrealize(); 
    8179} 
    8280 
    8381bool OSGGTKDrawingArea::_expose_event(GtkWidget* widget, GdkEventExpose* event) { 
    84        if(not gtkGLBegin()) return false; 
     82    if(not gtkGLBegin()) return false; 
    8583 
    86        frame(); 
     84    frame(); 
    8785 
    88        gtkGLSwap(); 
    89        gtkGLEnd(); 
     86    gtkGLSwap(); 
     87    gtkGLEnd(); 
    9088 
    91        return gtkExpose(); 
     89    return gtkExpose(); 
    9290} 
    9391 
    9492bool OSGGTKDrawingArea::_configure_event(GtkWidget* widget, GdkEventConfigure* event) { 
    95        gtkGLBegin(); 
     93    gtkGLBegin(); 
    9694 
    97        _queue.windowResize(0, 0, event->width, event->height); 
     95    _queue.windowResize(0, 0, event->width, event->height); 
    9896 
    99        gtkGLEnd(); 
     97    _gw->resized(0, 0, event->width, event->height); 
    10098 
    101         return gtkConfigure(event->width, event->height); 
     99    gtkGLEnd(); 
     100 
     101    return gtkConfigure(event->width, event->height); 
    102102} 
    103103 
    104104bool OSGGTKDrawingArea::_motion_notify_event(GtkWidget* widget, GdkEventMotion* event) { 
    105        _state = event->state; 
     105    _state = event->state; 
    106106 
    107        _queue.mouseMotion(event->x, event->y); 
     107    _queue.mouseMotion(event->x, event->y); 
    108108 
    109        return gtkMotionNotify(event->x, event->y); 
     109    return gtkMotionNotify(event->x, event->y); 
    110110} 
    111111 
    112112bool OSGGTKDrawingArea::_button_press_event(GtkWidget* widget, GdkEventButton* event) { 
    113        _state = event->state; 
     113    _state = event->state; 
    114114 
    115        if(event->type == GDK_BUTTON_PRESS) { 
    116                if(event->button == 1) gtk_widget_grab_focus(_widget); 
     115    if(event->type == GDK_BUTTON_PRESS) { 
     116        if(event->button == 1) gtk_widget_grab_focus(_widget); 
    117117 
    118                _queue.mouseButtonPress(event->x, event->y, event->button); 
     118        _queue.mouseButtonPress(event->x, event->y, event->button); 
    119119 
    120                return gtkButtonPress(event->x, event->y, event->button); 
    121        
     120        return gtkButtonPress(event->x, event->y, event->button); 
     121   
    122122 
    123        else if(event->type == GDK_BUTTON_RELEASE) { 
    124                _queue.mouseButtonRelease(event->x, event->y, event->button); 
     123    else if(event->type == GDK_BUTTON_RELEASE) { 
     124        _queue.mouseButtonRelease(event->x, event->y, event->button); 
    125125 
    126                return gtkButtonRelease(event->x, event->y, event->button); 
    127        
     126        return gtkButtonRelease(event->x, event->y, event->button); 
     127   
    128128 
    129        else return false; 
     129    else return false; 
    130130} 
    131131 
    132132bool OSGGTKDrawingArea::_key_press_event(GtkWidget* widget, GdkEventKey* event) { 
    133        _state = event->state; 
     133    _state = event->state; 
    134134 
    135        if(event->type == GDK_KEY_PRESS) { 
    136                _queue.keyPress(event->keyval); 
     135    if(event->type == GDK_KEY_PRESS) { 
     136        _queue.keyPress(event->keyval); 
    137137 
    138                return gtkKeyPress(event->keyval); 
    139        
     138        return gtkKeyPress(event->keyval); 
     139   
    140140 
    141        else if(event->type == GDK_KEY_RELEASE) { 
    142                _queue.keyRelease(event->keyval); 
     141    else if(event->type == GDK_KEY_RELEASE) { 
     142        _queue.keyRelease(event->keyval); 
    143143 
    144                return gtkKeyRelease(event->keyval); 
    145        
     144        return gtkKeyRelease(event->keyval); 
     145   
    146146 
    147        else return false; 
     147    else return false; 
    148148} 
  • OpenSceneGraph/trunk/examples/osgviewerGTK/osggtkdrawingarea.h

    r8290 r8294  
    1 // by: Jeremy Moles <jeremy@emperorlinux.com> 2007 
    2  
    31#include <gtk/gtk.h> 
    42#include <gtk/gtkgl.h> 
     
    1614// subclass implementation (see: osgviewerGTK). 
    1715class OSGGTKDrawingArea : public osgViewer::Viewer { 
    18         GtkWidget*     _widget; 
    19         GdkGLConfig*   _glconfig; 
    20         GdkGLContext*  _context; 
    21         GdkGLDrawable* _drawable; 
    22  
    23         unsigned int _state; 
    24  
    25         osgGA::EventQueue& _queue; 
    26  
    27         static OSGGTKDrawingArea* _self(gpointer self) { 
    28                 return static_cast<OSGGTKDrawingArea*>(self); 
    29         } 
    30  
    31         // A simple helper function to connect us to the various GTK signals. 
    32         void _connect(const char* name, GCallback callback) { 
    33                 g_signal_connect(G_OBJECT(_widget), name, callback, this); 
    34         } 
    35  
    36         void _realize             (GtkWidget*); 
    37         void _unrealize           (GtkWidget*); 
    38         bool _expose_event        (GtkWidget*, GdkEventExpose*); 
    39         bool _configure_event     (GtkWidget*, GdkEventConfigure*); 
    40         bool _motion_notify_event (GtkWidget*, GdkEventMotion*); 
    41         bool _button_press_event  (GtkWidget*, GdkEventButton*); 
    42         bool _key_press_event     (GtkWidget*, GdkEventKey*); 
    43  
    44         // The following functions are static "wrappers" so that we can invoke the 
    45         // bound methods of a class instance by passing the "this" pointer as the 
    46         // self argument and invoking it explicitly. 
    47         static void _srealize(GtkWidget* widget, gpointer self) { 
    48                 _self(self)->_realize(widget); 
    49         } 
    50  
    51         static void _sunrealize(GtkWidget* widget, gpointer self) { 
    52                 _self(self)->_unrealize(widget); 
    53         } 
    54  
    55         static bool _sexpose_event(GtkWidget* widget, GdkEventExpose* expose, gpointer self) { 
    56                 return _self(self)->_expose_event(widget, expose); 
    57         } 
    58  
    59         static bool _sconfigure_event( 
    60                 GtkWidget*         widget, 
    61                 GdkEventConfigure* event, 
    62                 gpointer           self 
    63         ) { 
    64                 return _self(self)->_configure_event(widget, event); 
    65         } 
    66  
    67         static bool _smotion_notify_event( 
    68                 GtkWidget*      widget, 
    69                 GdkEventMotion* event, 
    70                 gpointer        self 
    71         ) { 
    72                 return _self(self)->_motion_notify_event(widget, event); 
    73         } 
    74  
    75         static bool _sbutton_press_event( 
    76                 GtkWidget*      widget, 
    77                 GdkEventButton* event, 
    78                 gpointer        self 
    79         ) { 
    80                 return _self(self)->_button_press_event(widget, event); 
    81         } 
    82  
    83         static bool _skey_press_event( 
    84                 GtkWidget*   widget, 
    85                 GdkEventKey* event, 
    86                 gpointer     self 
    87         ) { 
    88                 return _self(self)->_key_press_event(widget, event); 
    89         } 
     16    GtkWidget*     _widget; 
     17    GdkGLConfig*   _glconfig; 
     18    GdkGLContext*  _context; 
     19    GdkGLDrawable* _drawable; 
     20     
     21    osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> _gw; 
     22 
     23    unsigned int _state; 
     24 
     25    osgGA::EventQueue& _queue; 
     26 
     27    static OSGGTKDrawingArea* _self(gpointer self) { 
     28        return static_cast<OSGGTKDrawingArea*>(self); 
     29    } 
     30 
     31    // A simple helper function to connect us to the various GTK signals. 
     32    void _connect(const char* name, GCallback callback) { 
     33        g_signal_connect(G_OBJECT(_widget), name, callback, this); 
     34    } 
     35 
     36    void _realize             (GtkWidget*); 
     37    void _unrealize           (GtkWidget*); 
     38    bool _expose_event        (GtkWidget*, GdkEventExpose*); 
     39    bool _configure_event     (GtkWidget*, GdkEventConfigure*); 
     40    bool _motion_notify_event (GtkWidget*, GdkEventMotion*); 
     41    bool _button_press_event  (GtkWidget*, GdkEventButton*); 
     42    bool _key_press_event     (GtkWidget*, GdkEventKey*); 
     43 
     44    // The following functions are static "wrappers" so that we can invoke the 
     45    // bound methods of a class instance by passing the "this" pointer as the 
     46    // self argument and invoking it explicitly. 
     47    static void _srealize(GtkWidget* widget, gpointer self) { 
     48        _self(self)->_realize(widget); 
     49    } 
     50 
     51    static void _sunrealize(GtkWidget* widget, gpointer self) { 
     52        _self(self)->_unrealize(widget); 
     53    } 
     54 
     55    static bool _sexpose_event(GtkWidget* widget, GdkEventExpose* expose, gpointer self) { 
     56        return _self(self)->_expose_event(widget, expose); 
     57    } 
     58 
     59    static bool _sconfigure_event( 
     60        GtkWidget*         widget, 
     61        GdkEventConfigure* event, 
     62        gpointer           self 
     63    ) { 
     64        return _self(self)->_configure_event(widget, event); 
     65    } 
     66 
     67    static bool _smotion_notify_event( 
     68        GtkWidget*      widget, 
     69        GdkEventMotion* event, 
     70        gpointer        self 
     71    ) { 
     72        return _self(self)->_motion_notify_event(widget, event); 
     73    } 
     74 
     75    static bool _sbutton_press_event( 
     76        GtkWidget*      widget, 
     77        GdkEventButton* event, 
     78        gpointer        self 
     79    ) { 
     80        return _self(self)->_button_press_event(widget, event); 
     81    } 
     82 
     83    static bool _skey_press_event( 
     84        GtkWidget*   widget, 
     85        GdkEventKey* event, 
     86        gpointer     self 
     87    ) { 
     88        return _self(self)->_key_press_event(widget, event); 
     89    } 
    9090 
    9191protected: 
    92        // You can override these in your subclass if you'd like. :) 
    93        // Right now they're fairly uninformative, but they could be easily extended. 
    94        // Note that the "state" information isn't passed around to each function 
    95        // but is instead stored and abstracted internally. See below. 
    96  
    97        virtual void gtkRealize   () {}; 
    98        virtual void gtkUnrealize () {}; 
    99        virtual bool gtkExpose    () { 
    100                return true; 
    101        }; 
    102  
    103        // The new width and height. 
    104        virtual bool gtkConfigure(int, int) { 
    105                return true; 
    106        }; 
    107  
    108        // The "normalized" coordinates of the mouse. 
    109        virtual bool gtkMotionNotify(double, double) { 
    110                return true; 
    111        }; 
    112  
    113        // The "normalized" coordinates of the mouse and the mouse button code on down. 
    114        virtual bool gtkButtonPress(double, double, unsigned int) { 
    115                return true; 
    116        }; 
    117  
    118        // The "normalized" coordinates of the mouse and mouse button code on release. 
    119        virtual bool gtkButtonRelease(double, double, unsigned int) { 
    120                return true; 
    121        
    122  
    123        // The X key value on down. 
    124        virtual bool gtkKeyPress(unsigned int) { 
    125                return true; 
    126        }; 
    127  
    128        // The X key value on release. 
    129        virtual bool gtkKeyRelease(unsigned int) { 
    130                return true; 
    131        }; 
    132  
    133        // These functions wrap state tests of the most recent state in the 
    134        // GtkDrawingArea. 
    135  
    136        inline bool stateShift() { 
    137                return _state & GDK_SHIFT_MASK; 
    138        
    139  
    140        inline bool stateLock() { 
    141                return _state & GDK_LOCK_MASK; 
    142        
    143  
    144        inline bool stateControl() { 
    145                return _state & GDK_CONTROL_MASK; 
    146        
    147  
    148        inline bool stateMod() { 
    149                return _state & ( 
    150                        GDK_MOD1_MASK | 
    151                        GDK_MOD2_MASK | 
    152                        GDK_MOD3_MASK | 
    153                        GDK_MOD4_MASK | 
    154                        GDK_MOD5_MASK 
    155                ); 
    156        
    157  
    158        inline bool stateButton() { 
    159                return _state & ( 
    160                        GDK_BUTTON1_MASK | 
    161                        GDK_BUTTON2_MASK | 
    162                        GDK_BUTTON3_MASK | 
    163                        GDK_BUTTON4_MASK | 
    164                        GDK_BUTTON5_MASK 
    165                ); 
    166        
     92    // You can override these in your subclass if you'd like. :) 
     93    // Right now they're fairly uninformative, but they could be easily extended. 
     94    // Note that the "state" information isn't passed around to each function 
     95    // but is instead stored and abstracted internally. See below. 
     96 
     97    virtual void gtkRealize   () {}; 
     98    virtual void gtkUnrealize () {}; 
     99    virtual bool gtkExpose    () { 
     100        return true; 
     101    }; 
     102 
     103    // The new width and height. 
     104    virtual bool gtkConfigure(int, int) { 
     105        return true; 
     106    }; 
     107 
     108    // The "normalized" coordinates of the mouse. 
     109    virtual bool gtkMotionNotify(double, double) { 
     110        return true; 
     111    }; 
     112 
     113    // The "normalized" coordinates of the mouse and the mouse button code on down. 
     114    virtual bool gtkButtonPress(double, double, unsigned int) { 
     115        return true; 
     116    }; 
     117 
     118    // The "normalized" coordinates of the mouse and mouse button code on release. 
     119    virtual bool gtkButtonRelease(double, double, unsigned int) { 
     120        return true; 
     121   
     122 
     123    // The X key value on down. 
     124    virtual bool gtkKeyPress(unsigned int) { 
     125        return true; 
     126    }; 
     127 
     128    // The X key value on release. 
     129    virtual bool gtkKeyRelease(unsigned int) { 
     130        return true; 
     131    }; 
     132 
     133    // These functions wrap state tests of the most recent state in the 
     134    // GtkDrawingArea. 
     135 
     136    inline bool stateShift() { 
     137        return _state & GDK_SHIFT_MASK; 
     138   
     139 
     140    inline bool stateLock() { 
     141        return _state & GDK_LOCK_MASK; 
     142   
     143 
     144    inline bool stateControl() { 
     145        return _state & GDK_CONTROL_MASK; 
     146   
     147 
     148    inline bool stateMod() { 
     149        return _state & ( 
     150            GDK_MOD1_MASK | 
     151            GDK_MOD2_MASK | 
     152            GDK_MOD3_MASK | 
     153            GDK_MOD4_MASK | 
     154            GDK_MOD5_MASK 
     155        ); 
     156   
     157 
     158    inline bool stateButton() { 
     159        return _state & ( 
     160            GDK_BUTTON1_MASK | 
     161            GDK_BUTTON2_MASK | 
     162            GDK_BUTTON3_MASK | 
     163            GDK_BUTTON4_MASK | 
     164            GDK_BUTTON5_MASK 
     165        ); 
     166   
    167167 
    168168public: 
    169        OSGGTKDrawingArea  (); 
    170        ~OSGGTKDrawingArea (); 
    171  
    172        bool createWidget(int, int); 
    173  
    174        GtkWidget* getWidget() { 
    175                return _widget; 
    176        
    177  
    178        bool gtkGLBegin() { 
    179                if(_drawable and _context) return gdk_gl_drawable_gl_begin(_drawable, _context); 
    180  
    181                else return false; 
    182        
    183  
    184        void gtkGLEnd() { 
    185                if(_drawable) gdk_gl_drawable_gl_end(_drawable); 
    186        
    187  
    188        // Because of GTK's internal double buffering, I'm not sure if we're really 
    189        // taking advantage of OpenGL's internal swapping. 
    190        bool gtkGLSwap() { 
    191                if(_drawable and gdk_gl_drawable_is_double_buffered(_drawable)) { 
    192                        gdk_gl_drawable_swap_buffers(_drawable); 
    193  
    194                        return true; 
    195                
    196  
    197                else { 
    198                        glFlush(); 
    199  
    200                        return false; 
    201                
    202        
    203  
    204        void queueDraw() { 
    205                gtk_widget_queue_draw(_widget); 
    206        
     169    OSGGTKDrawingArea  (); 
     170    ~OSGGTKDrawingArea (); 
     171 
     172    bool createWidget(int, int); 
     173 
     174    GtkWidget* getWidget() { 
     175        return _widget; 
     176   
     177 
     178    bool gtkGLBegin() { 
     179        if(_drawable and _context) return gdk_gl_drawable_gl_begin(_drawable, _context); 
     180 
     181        else return false; 
     182   
     183 
     184    void gtkGLEnd() { 
     185        if(_drawable) gdk_gl_drawable_gl_end(_drawable); 
     186   
     187 
     188    // Because of GTK's internal double buffering, I'm not sure if we're really 
     189    // taking advantage of OpenGL's internal swapping. 
     190    bool gtkGLSwap() { 
     191        if(_drawable and gdk_gl_drawable_is_double_buffered(_drawable)) { 
     192            gdk_gl_drawable_swap_buffers(_drawable); 
     193 
     194            return true; 
     195       
     196 
     197        else { 
     198            glFlush(); 
     199 
     200            return false; 
     201       
     202   
     203 
     204    void queueDraw() { 
     205        gtk_widget_queue_draw(_widget); 
     206   
    207207}; 
  • OpenSceneGraph/trunk/examples/osgviewerGTK/osgviewerGTK.cpp

    r8290 r8294  
    1 // by: Jeremy Moles <jeremy@emperorlinux.com> 2007 
    2  
    31#include <iostream> 
    42#include <string> 
     
    97 
    108const char* HELP_TEXT = 
    11        "Use CTRL or SHIFT plus right-click to pull up a fake menu.\n" 
    12        "Use the standard TrackballManipulator keys to rotate the loaded\n" 
    13        "model (with caveats; the model won't keep rotating).\n" 
    14        "\n" 
    15        "<b>OpenSceneGraph Project, 2008</b>" 
     9    "Use CTRL or SHIFT plus right-click to pull up a fake menu.\n" 
     10    "Use the standard TrackballManipulator keys to rotate the loaded\n" 
     11    "model (with caveats; the model won't keep rotating).\n" 
     12    "\n" 
     13    "<b>OpenSceneGraph Project, 2008</b>" 
    1614; 
    1715 
     
    2018// come up with. 
    2119bool activate(GtkWidget* widget, gpointer) { 
    22        GtkWidget* label = gtk_bin_get_child(GTK_BIN(widget)); 
    23  
    24        std::cout << "MENU: " << gtk_label_get_label(GTK_LABEL(label)) << std::endl; 
    25  
    26        return true; 
     20    GtkWidget* label = gtk_bin_get_child(GTK_BIN(widget)); 
     21 
     22    std::cout << "MENU: " << gtk_label_get_label(GTK_LABEL(label)) << std::endl; 
     23 
     24    return true; 
    2725} 
    2826 
     
    3533// itself. 
    3634class ExampleOSGGTKDrawingArea : public OSGGTKDrawingArea { 
    37        GtkWidget* _menu; 
    38          
    39        unsigned int _tid; 
    40  
    41        // A helper function to easily setup our menu entries. 
    42        void _menuAdd(const std::string& title) { 
    43                GtkWidget* item = gtk_menu_item_new_with_label(title.c_str()); 
    44                  
    45                gtk_menu_shell_append(GTK_MENU_SHELL(_menu), item); 
    46  
    47                g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(activate), 0); 
    48        
    49  
    50        bool _clicked(GtkWidget* widget) { 
    51                const char* text = gtk_label_get_label( 
    52                        GTK_LABEL(gtk_bin_get_child(GTK_BIN(widget))) 
    53                ); 
    54  
    55                if(not std::strncmp(text, "Close", 5)) gtk_main_quit(); 
    56          
    57                else if(not std::strncmp(text, "Open File", 9)) { 
    58                        GtkWidget* of = gtk_file_chooser_dialog_new( 
    59                                "Please select an OSG file...", 
    60                                GTK_WINDOW(gtk_widget_get_toplevel(getWidget())), 
    61                                GTK_FILE_CHOOSER_ACTION_OPEN, 
    62                                GTK_STOCK_CANCEL, 
    63                                GTK_RESPONSE_CANCEL, 
    64                                GTK_STOCK_OPEN, 
    65                                GTK_RESPONSE_ACCEPT, 
    66                                NULL 
    67                        ); 
    68  
    69                        if(gtk_dialog_run(GTK_DIALOG(of)) == GTK_RESPONSE_ACCEPT) { 
    70                                char* file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(of)); 
    71  
    72                                osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(file); 
    73  
    74                                if(model.valid()) { 
    75                                        setSceneData(model.get()); 
    76                                  
    77                                        queueDraw(); 
    78                                
    79  
    80                                g_free(file); 
    81                        
    82                          
    83                        gtk_widget_destroy(of); 
    84                
    85  
    86                // Assume we're wanting FPS toggling. 
    87                else { 
    88                        if(not _tid) { 
    89                                _tid = g_timeout_add( 
    90                                        15, 
    91                                        (GSourceFunc)(ExampleOSGGTKDrawingArea::timeout), 
    92                                        this 
    93                                ); 
    94  
    95                                gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (off)"); 
    96                        
    97  
    98                        else { 
    99                                g_source_remove(_tid); 
    100                                gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (on)"); 
    101  
    102                                _tid = 0; 
    103                        
    104                
    105  
    106                return true; 
    107        
     35    GtkWidget* _menu; 
     36     
     37    unsigned int _tid; 
     38 
     39    // A helper function to easily setup our menu entries. 
     40    void _menuAdd(const std::string& title) { 
     41        GtkWidget* item = gtk_menu_item_new_with_label(title.c_str()); 
     42         
     43        gtk_menu_shell_append(GTK_MENU_SHELL(_menu), item); 
     44 
     45        g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(activate), 0); 
     46   
     47 
     48    bool _clicked(GtkWidget* widget) { 
     49        const char* text = gtk_label_get_label( 
     50            GTK_LABEL(gtk_bin_get_child(GTK_BIN(widget))) 
     51        ); 
     52 
     53        if(not std::strncmp(text, "Close", 5)) gtk_main_quit(); 
     54     
     55        else if(not std::strncmp(text, "Open File", 9)) { 
     56            GtkWidget* of = gtk_file_chooser_dialog_new( 
     57                "Please select an OSG file...", 
     58                GTK_WINDOW(gtk_widget_get_toplevel(getWidget())), 
     59                GTK_FILE_CHOOSER_ACTION_OPEN, 
     60                GTK_STOCK_CANCEL, 
     61                GTK_RESPONSE_CANCEL, 
     62                GTK_STOCK_OPEN, 
     63                GTK_RESPONSE_ACCEPT, 
     64                NULL 
     65            ); 
     66 
     67            if(gtk_dialog_run(GTK_DIALOG(of)) == GTK_RESPONSE_ACCEPT) { 
     68                char* file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(of)); 
     69 
     70                osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(file); 
     71 
     72                if(model.valid()) { 
     73                    setSceneData(model.get()); 
     74                 
     75                    queueDraw(); 
     76               
     77 
     78                g_free(file); 
     79           
     80             
     81            gtk_widget_destroy(of); 
     82       
     83 
     84        // Assume we're wanting FPS toggling. 
     85        else { 
     86            if(not _tid) { 
     87                _tid = g_timeout_add( 
     88                    15, 
     89                    (GSourceFunc)(ExampleOSGGTKDrawingArea::timeout), 
     90                    this 
     91                ); 
     92 
     93                gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (off)"); 
     94           
     95 
     96            else { 
     97                g_source_remove(_tid); 
     98                gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (on)"); 
     99 
     100                _tid = 0; 
     101           
     102       
     103 
     104        return true; 
     105   
    108106 
    109107protected: 
    110        // Check right-click release to see if we need to popup our menu. 
    111        bool gtkButtonRelease(double, double, unsigned int button) { 
    112                if(button == 3 and (stateControl() or stateShift())) gtk_menu_popup( 
    113                        GTK_MENU(_menu), 
    114                        0, 
    115                        0, 
    116                        0, 
    117                        0, 
    118                        button, 
    119                        
    120                ); 
    121  
    122                return true; 
    123        
    124  
    125        // Our "main" drawing pump. Since our app is just a model viewer, we use 
    126        // click+motion as our criteria for issuing OpenGL refreshes. 
    127        bool gtkMotionNotify(double, double) { 
    128                if(stateButton()) queueDraw(); 
    129  
    130                return true; 
    131        
     108    // Check right-click release to see if we need to popup our menu. 
     109    bool gtkButtonRelease(double, double, unsigned int button) { 
     110        if(button == 3 and (stateControl() or stateShift())) gtk_menu_popup( 
     111            GTK_MENU(_menu), 
     112            0, 
     113            0, 
     114            0, 
     115            0, 
     116            button, 
     117           
     118        ); 
     119 
     120        return true; 
     121   
     122 
     123    // Our "main" drawing pump. Since our app is just a model viewer, we use 
     124    // click+motion as our criteria for issuing OpenGL refreshes. 
     125    bool gtkMotionNotify(double, double) { 
     126        if(stateButton()) queueDraw(); 
     127 
     128        return true; 
     129   
    132130 
    133131public: 
    134        ExampleOSGGTKDrawingArea(): 
    135        OSGGTKDrawingArea (), 
    136        _menu             (gtk_menu_new()), 
    137        _tid              (0) { 
    138                _menuAdd("Option"); 
    139                _menuAdd("Another Option"); 
    140                _menuAdd("Still More Options"); 
    141  
    142                gtk_widget_show_all(_menu); 
    143  
    144                getCamera()->setStats(new osg::Stats("omg")); 
    145        
    146  
    147        ~ExampleOSGGTKDrawingArea() {} 
    148  
    149        // Public so that we can use this as a callback in main(). 
    150        static bool clicked(GtkWidget* widget, gpointer self) { 
    151                return static_cast<ExampleOSGGTKDrawingArea*>(self)->_clicked(widget); 
    152        
    153  
    154        //static gboolean timeout(GtkWidget* widget) { 
    155        static bool timeout(void* self) { 
    156                static_cast<ExampleOSGGTKDrawingArea*>(self)->queueDraw(); 
    157  
    158                return true; 
    159        
     132    ExampleOSGGTKDrawingArea(): 
     133    OSGGTKDrawingArea (), 
     134    _menu             (gtk_menu_new()), 
     135    _tid              (0) { 
     136        _menuAdd("Option"); 
     137        _menuAdd("Another Option"); 
     138        _menuAdd("Still More Options"); 
     139 
     140        gtk_widget_show_all(_menu); 
     141 
     142        getCamera()->setStats(new osg::Stats("omg")); 
     143   
     144 
     145    ~ExampleOSGGTKDrawingArea() {} 
     146 
     147    // Public so that we can use this as a callback in main(). 
     148    static bool clicked(GtkWidget* widget, gpointer self) { 
     149        return static_cast<ExampleOSGGTKDrawingArea*>(self)->_clicked(widget); 
     150   
     151 
     152    //static gboolean timeout(GtkWidget* widget) { 
     153    static bool timeout(void* self) { 
     154        static_cast<ExampleOSGGTKDrawingArea*>(self)->queueDraw(); 
     155 
     156        return true; 
     157   
    160158}; 
    161159 
     
    164162// code or so. 
    165163int main(int argc, char** argv) { 
    166        gtk_init(&argc, &argv); 
    167        gtk_gl_init(&argc, &argv); 
    168  
    169        ExampleOSGGTKDrawingArea da; 
    170  
    171        if(da.createWidget(640, 480)) { 
    172                if(argc >= 2) { 
    173                        osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(argv[1]); 
    174  
    175                        if(model.valid()) da.setSceneData(model.get()); 
    176                
    177  
    178                GtkWidget* window    = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    179                GtkWidget* vbox1     = gtk_vbox_new(false, 3); 
    180                GtkWidget* vbox2     = gtk_vbox_new(false, 3); 
    181                GtkWidget* hbox      = gtk_hbox_new(false, 3); 
    182                GtkWidget* label     = gtk_label_new(""); 
    183                GtkWidget* buttons[] = { 
    184                        gtk_button_new_with_label("Open File"), 
    185                        gtk_button_new_with_label("Toggle 60 FPS (on)"), 
    186                        gtk_button_new_with_label("Close") 
    187                }; 
    188  
    189                gtk_label_set_use_markup(GTK_LABEL(label), true); 
    190                gtk_label_set_label(GTK_LABEL(label), HELP_TEXT); 
    191  
    192                for(unsigned int i = 0; i < sizeof(buttons) / sizeof(GtkWidget*); i++) { 
    193                        gtk_box_pack_start( 
    194                                GTK_BOX(vbox2), 
    195                                buttons[i], 
    196                                false, 
    197                                false, 
    198                                
    199                        ); 
    200  
    201                        g_signal_connect( 
    202                                G_OBJECT(buttons[i]), 
    203                                "clicked", 
    204                                G_CALLBACK(ExampleOSGGTKDrawingArea::clicked), 
    205                                &da 
    206                        ); 
    207                
    208  
    209                gtk_window_set_title(GTK_WINDOW(window), "osgviewerGTK"); 
    210  
    211                gtk_box_pack_start(GTK_BOX(hbox), vbox2, true, true, 2); 
    212                gtk_box_pack_start(GTK_BOX(hbox), label, true, true, 2); 
    213  
    214                gtk_box_pack_start(GTK_BOX(vbox1), da.getWidget(), true, true, 2); 
    215                gtk_box_pack_start(GTK_BOX(vbox1), hbox, false, false, 2); 
    216  
    217                gtk_container_set_reallocate_redraws(GTK_CONTAINER(window), true); 
    218                gtk_container_add(GTK_CONTAINER(window), vbox1); 
    219  
    220                g_signal_connect( 
    221                        G_OBJECT(window), 
    222                        "delete_event", 
    223                        G_CALLBACK(gtk_main_quit), 
    224                        
    225                ); 
    226  
    227                gtk_widget_show_all(window); 
    228                gtk_main(); 
    229        
    230  
    231        else return 1; 
    232  
    233        return 0; 
     164    gtk_init(&argc, &argv); 
     165    gtk_gl_init(&argc, &argv); 
     166 
     167    ExampleOSGGTKDrawingArea da; 
     168 
     169    if(da.createWidget(640, 480)) { 
     170        if(argc >= 2) { 
     171            osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(argv[1]); 
     172 
     173            if(model.valid()) da.setSceneData(model.get());