Back to index

salome-gui  6.5.0
GLViewer_ViewPort.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  Author : OPEN CASCADE
00024 // File:      GLViewer_ViewPort.cxx
00025 // Created:   November, 2004
00026 //#include <GLViewerAfx.h>
00027 //
00028 #include "GLViewer_ViewPort.h"
00029 
00030 #include "SUIT_ResourceMgr.h"
00031 #include "SUIT_Session.h"
00032 
00033 #include <QRect>
00034 #include <QCursor>
00035 #include <QPainter>
00036 #include <QMultiHash>
00037 //#include <QMenu>
00038 #include <QColorDialog>
00039 #include <QColormap>
00040 #include <QMouseEvent>
00041 #include <QCoreApplication>
00042 
00043 #include <stdlib.h>
00044 
00045 #if !defined WIN32
00046 #include <QX11Info>
00047 #include <GL/glx.h>
00048 #include <X11/Xlib.h>
00049 #include <X11/Xutil.h>
00050 #include <X11/Xatom.h>
00051 #include <X11/Xmu/StdCmap.h>
00052 #undef QT_CLEAN_NAMESPACE
00053 #include <Xw_Window.hxx>
00054 #include <Graphic3d_GraphicDevice.hxx>
00055 
00061 struct CMapEntry
00062 {
00063     CMapEntry();
00064     ~CMapEntry();
00065     Colormap          cmap;
00066     bool              alloc;
00067     XStandardColormap scmap;
00068 };
00069 
00073 CMapEntry::CMapEntry()
00074 {
00075     cmap = 0;
00076     alloc = false;
00077     scmap.colormap = 0;
00078 }
00079 
00083 CMapEntry::~CMapEntry()
00084 {
00085     if ( alloc )
00086         XFreeColormap( QX11Info::display(), cmap );
00087 }
00088 
00089 static QMultiHash<int,CMapEntry> *cmap_dict = 0;
00090 static bool mesa_gl = false;
00091 
00092 static void cleanup_cmaps()
00093 {
00094     if ( !cmap_dict )
00095         return;
00096     //while (!cmap_dict->isEmpty())
00097     //  cmap_dict->erase(cmap_dict->begin());
00098     cmap_dict->clear();
00099     delete cmap_dict;
00100     cmap_dict = 0;
00101 }
00102 
00103 static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
00104 {
00105     if ( !cmap_dict )
00106     {
00107         cmap_dict = new QMultiHash<int,CMapEntry>;
00108         const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
00109         mesa_gl = strstr( v,"Mesa" ) != 0;
00110         qAddPostRoutine( cleanup_cmaps );
00111     }
00112 
00113     QHash<int,CMapEntry>::iterator itH = cmap_dict->find( (long)vi->visualid );
00114     if ( itH != cmap_dict->end() )  // found colormap for visual
00115         return itH.value().cmap;
00116 
00117     CMapEntry x;
00118 
00119     XStandardColormap *c;
00120     int n, i;
00121 
00122 #ifdef DEBUG
00123     cout << "Choosing cmap for vID = " << vi->visualid << endl;
00124 #endif
00125 
00126     if ( vi->visualid == XVisualIDFromVisual( (Visual*)QX11Info::appVisual() ) )
00127     {
00128 #ifdef DEBUG
00129         cout << "Using x11AppColormap" << endl;
00130 #endif
00131         return QX11Info::appColormap();
00132     }
00133 
00134     if ( mesa_gl )
00135     {
00136         Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
00137         if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
00138         {
00139             if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
00140             {
00141                 i = 0;
00142                 while ( i < n && x.cmap == 0 )
00143                 {
00144                     if ( c[i].visualid == vi->visual->visualid )
00145                     {
00146                         x.cmap = c[i].colormap;
00147                         x.scmap = c[i];
00148                     }
00149                     i++;
00150                 }
00151                 XFree( (char*)c );
00152             }
00153         }
00154     }
00155 #if !defined( _OS_SOLARIS_ )
00156     if ( !x.cmap )
00157     {
00158         if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
00159         {
00160             if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
00161             {
00162                 i = 0;
00163                 while ( i < n && x.cmap == 0 )
00164                 {
00165                     if ( c[i].visualid == vi->visualid )
00166                     {
00167                         x.cmap = c[i].colormap;
00168                         x.scmap = c[i];
00169                     }
00170                     i++;
00171                 }
00172                 XFree( (char *)c );
00173             }
00174         }
00175     }
00176 #endif
00177     if ( !x.cmap )
00178     {
00179         // no shared cmap found
00180         x.cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
00181         x.alloc = true;
00182     }
00183 
00184     cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
00185     return x.cmap;
00186 }
00187 #endif
00188 
00189 int GLViewer_ViewPort::nCounter = 0;
00190 QCursor* GLViewer_ViewPort::defCursor = 0;
00191 QCursor* GLViewer_ViewPort::panglCursor = 0;
00192 QCursor* GLViewer_ViewPort::handCursor = 0;
00193 QCursor* GLViewer_ViewPort::panCursor = 0;
00194 QCursor* GLViewer_ViewPort::zoomCursor = 0;
00195 QCursor* GLViewer_ViewPort::rotCursor = 0;
00196 QCursor* GLViewer_ViewPort::sketchCursor = 0;
00197 
00201 void GLViewer_ViewPort::createCursors ()
00202 {
00203     defCursor   = new QCursor( Qt::ArrowCursor );
00204     panglCursor = new QCursor( Qt::CrossCursor );
00205     handCursor  = new QCursor( Qt::PointingHandCursor );
00206     panCursor   = new QCursor( Qt::SizeAllCursor );
00207 
00208     SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
00209     zoomCursor   = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ZOOM" ) ) );
00210     rotCursor    = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ROTATE" ) ) );
00211     sketchCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_SKETCH" ) ) );
00212 }
00213 
00217 void GLViewer_ViewPort::destroyCursors()
00218 {
00219     delete defCursor;   defCursor   = 0;
00220     delete panglCursor; panglCursor = 0;
00221     delete handCursor;  handCursor  = 0;
00222     delete panCursor;   panCursor   = 0;
00223     delete zoomCursor;  zoomCursor  = 0;
00224     delete rotCursor;   rotCursor   = 0;
00225     delete sketchCursor; sketchCursor = 0;
00226 }
00227 
00231 void GLViewer_ViewPort::setDefaultCursor( const QCursor& newCursor )
00232 {
00233     if ( !defCursor )
00234         defCursor = new QCursor();
00235     *defCursor = newCursor;
00236 }
00237 
00241 void GLViewer_ViewPort::setHandCursor( const QCursor& newCursor )
00242 {
00243     if ( !handCursor )
00244         handCursor = new QCursor();
00245     *handCursor = newCursor;
00246 }
00247 
00251 void GLViewer_ViewPort::setPanCursor( const QCursor& newCursor )
00252 {
00253     if ( !panCursor )
00254         panCursor = new QCursor();
00255     *panCursor = newCursor;
00256 }
00257 
00261 void GLViewer_ViewPort::setPanglCursor( const QCursor& newCursor )
00262 {
00263     if ( !panglCursor )
00264         panglCursor = new QCursor();
00265     *panglCursor = newCursor;
00266 }
00267 
00271 void GLViewer_ViewPort::setZoomCursor( const QCursor& newCursor )
00272 {
00273     if ( !zoomCursor )
00274         zoomCursor = new QCursor();
00275     *zoomCursor = newCursor;
00276 }
00277 
00281 void GLViewer_ViewPort::setRotCursor( const QCursor& newCursor )
00282 {
00283     if ( !rotCursor )
00284         rotCursor = new QCursor();
00285     *rotCursor = newCursor;
00286 }
00287 
00291 void GLViewer_ViewPort::setSketchCursor( const QCursor& newCursor )
00292 {
00293     if ( !rotCursor )
00294         sketchCursor = new QCursor();
00295     *sketchCursor = newCursor;
00296 }
00297 
00301 GLViewer_ViewPort::GLViewer_ViewPort( QWidget* parent )
00302 : QWidget( parent, 0 )
00303 {
00304     initialize();
00305 }
00306 
00310 GLViewer_ViewPort::~GLViewer_ViewPort()
00311 {
00312     cleanup();
00313 }
00314 
00318 void GLViewer_ViewPort::initialize()
00319 {
00320     if ( nCounter++ == 0 )
00321         createCursors();
00322 
00323     //myPopupActions.setAutoDelete( true );
00324     myPaintersRedrawing = false;
00325     myEnableSketching = false;
00326     myEnableTransform = true;
00327 
00328     setMouseTracking( true );
00329     setBackgroundRole( QPalette::NoRole );//NoBackground );
00330 
00331     setFocusPolicy( Qt::StrongFocus );
00332 }
00333 
00337 void GLViewer_ViewPort::cleanup()
00338 {
00339     if ( --nCounter == 0 )
00340         destroyCursors();
00341 }
00342 
00346 void GLViewer_ViewPort::selectVisualId( ViewType type )
00347 {
00348 #if !defined WIN32
00349     XVisualInfo* pVisualInfo;
00350     if ( QX11Info::display() )
00351     {
00352         /* Initialization with the default VisualID */
00353         //Visual *v = DefaultVisual( x11Display(), DefaultScreen( x11Display() ) );
00354         // int visualID = XVisualIDFromVisual( v ); unused
00355 
00356         /*  Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
00357         int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
00358                              GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
00359 
00360         pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
00361 
00362         if ( isVisible() )
00363             hide();
00364 
00365         XSetWindowAttributes a;
00366 
00367         a.colormap = choose_cmap( QX11Info::display(), pVisualInfo );      /* find best colormap */
00368         a.background_pixel = QColormap::instance().pixel( backgroundColor() );
00369         a.border_pixel = QColormap::instance().pixel( Qt::black );
00370         Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
00371         if ( parentWidget() )
00372             p = parentWidget()->winId();
00373 
00374         Window w;
00375         if ( type == Type2D )  // creating simple X window for 2d
00376         {
00377             unsigned long xbackground =
00378                 BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
00379             unsigned long xforeground =
00380                 WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
00381 
00382             w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
00383                                       height(), 0, xforeground, xbackground );
00384         }
00385         else if ( type == Type3D )
00386         {
00387             w = XCreateWindow( QX11Info::display(), p,  x(), y(), width(), height(),
00388                                0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
00389                                CWBackPixel | CWBorderPixel | CWColormap, &a );
00390         }
00391         else
00392             return;
00393 
00394         Window *cmw;
00395         Window *cmwret;
00396         int count;
00397         if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
00398         {
00399             cmw = new Window[count+1];
00400             memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
00401             XFree( (char*)cmwret );
00402             int i;
00403 
00404             for ( i = 0; i < count; i++ )
00405             {
00406                 if ( cmw[i] == winId() ) /* replace old window */
00407                 {
00408                     cmw[i] = w;
00409                     break;
00410                 }
00411             }
00412 
00413             if ( i >= count )            /* append new window */
00414                 cmw[count++] = w;
00415         }
00416         else
00417         {
00418             count = 1;
00419             cmw = new Window[count];
00420             cmw[0] = w;
00421         }
00422 
00423         /* Creating new window (with good VisualID) for this widget */
00424         create(w);
00425         XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
00426         delete[] cmw;
00427 
00428         if ( isVisible() )
00429             show();
00430 
00431         if ( pVisualInfo )
00432         {
00433             XFree( (char *)pVisualInfo );
00434         }
00435         XFlush( QX11Info::display() );
00436     }
00437 #endif
00438 }
00439 
00443 void GLViewer_ViewPort::setBackgroundColor( const QColor& color )
00444 {
00445     QPalette pal = palette();
00446     pal.setColor( QPalette::Background, color );
00447     setPalette( pal );
00448     repaint();
00449 }
00450 
00454 QColor GLViewer_ViewPort::backgroundColor() const
00455 {
00456     return palette().color( QPalette::Active, QPalette::Background );
00457 }
00458 
00462 bool GLViewer_ViewPort::isSketchingEnabled() const
00463 {
00464     return myEnableSketching;
00465 }
00466 
00470 void GLViewer_ViewPort::setSketchingEnabled( bool enable )
00471 {
00472     myEnableSketching = enable;
00473 }
00474 
00479 bool GLViewer_ViewPort::isTransformEnabled() const
00480 {
00481     return myEnableTransform;
00482 }
00483 
00487 void GLViewer_ViewPort::setTransformEnabled( bool enable )
00488 {
00489     myEnableTransform = enable;
00490 }
00491 
00495 void GLViewer_ViewPort::mousePressEvent( QMouseEvent *e )
00496 {
00497     emit vpMouseEvent( e );
00498 }
00499 
00503 void GLViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
00504 {
00505     emit vpMouseEvent( e );
00506 }
00507 
00511 void GLViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
00512 {
00513     emit vpMouseEvent( e );
00514 
00515     /* show popup menu */
00516     if ( e->button() == Qt::RightButton )
00517     {
00518         //QPopupMenu* popup = createPopup();
00519         //if ( popup && popup->count() )
00520         //    popup->exec( QCursor::pos() );
00521         //destroyPopup( /*popup*/ );
00522     }
00523 }
00524 
00528 void GLViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
00529 {
00530     emit vpMouseEvent( e );
00531 }
00532 
00536 void GLViewer_ViewPort::keyPressEvent( QKeyEvent *e )
00537 {
00538     emit vpKeyEvent( e );
00539 }
00540 
00544 void GLViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
00545 {
00546     emit vpKeyEvent( e );
00547 }
00548 
00552 void GLViewer_ViewPort::wheelEvent( QWheelEvent *e )
00553 {
00554     emit vpWheelEvent( e );
00555 }
00556 
00560 void GLViewer_ViewPort::paintEvent( QPaintEvent* )
00561 {
00562     if ( myPaintersRedrawing )
00563     {
00564         QPainter p( this );
00565         emit vpDrawExternal( &p );
00566         myPaintersRedrawing = false;
00567     }
00568 }
00569 
00573 void GLViewer_ViewPort::redrawPainters()
00574 {
00575     myPaintersRedrawing = true;
00576     repaint();
00577 }
00578 
00582 void GLViewer_ViewPort::onUpdate()
00583 {
00584 }
00585 
00589 void GLViewer_ViewPort::onChangeBgColor()
00590 {
00591     QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
00592     if ( selColor.isValid() )
00593         setBackgroundColor( selColor );
00594 }
00595 
00599 void GLViewer_ViewPort::contextMenuEvent( QContextMenuEvent* e )
00600 {
00601   //if ( e->reason() != QContextMenuEvent::Mouse )
00602     emit contextMenuRequested( e );
00603 }