1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // Author : OPEN CASCADE
24 // File: GLViewer_ViewPort.cxx
25 // Created: November, 2004
26 //#include <GLViewerAfx.h>
28 #include "GLViewer_ViewPort.h"
30 #include "SUIT_ResourceMgr.h"
31 #include "SUIT_Session.h"
38 #include <QColorDialog>
40 #include <QMouseEvent>
41 #include <QCoreApplication>
49 #include <X11/Xutil.h>
50 #include <X11/Xatom.h>
51 #include <X11/Xmu/StdCmap.h>
52 #undef QT_CLEAN_NAMESPACE
53 #include <Xw_Window.hxx>
54 #include <Graphic3d_GraphicDevice.hxx>
67 XStandardColormap scmap;
73 CMapEntry::CMapEntry()
83 CMapEntry::~CMapEntry()
86 XFreeColormap( QX11Info::display(), cmap );
89 static QMultiHash<int,CMapEntry> *cmap_dict = 0;
90 static bool mesa_gl = false;
92 static void cleanup_cmaps()
96 //while (!cmap_dict->isEmpty())
97 // cmap_dict->erase(cmap_dict->begin());
103 static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
107 cmap_dict = new QMultiHash<int,CMapEntry>;
108 const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
109 mesa_gl = strstr( v,"Mesa" ) != 0;
110 qAddPostRoutine( cleanup_cmaps );
113 QHash<int,CMapEntry>::iterator itH = cmap_dict->find( (long)vi->visualid );
114 if ( itH != cmap_dict->end() ) // found colormap for visual
115 return itH.value().cmap;
119 XStandardColormap *c;
123 cout << "Choosing cmap for vID = " << vi->visualid << endl;
126 if ( vi->visualid == XVisualIDFromVisual( (Visual*)QX11Info::appVisual() ) )
129 cout << "Using x11AppColormap" << endl;
131 return QX11Info::appColormap();
136 Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
137 if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
139 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
142 while ( i < n && x.cmap == 0 )
144 if ( c[i].visualid == vi->visual->visualid )
146 x.cmap = c[i].colormap;
155 #if !defined( _OS_SOLARIS_ )
158 if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
160 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
163 while ( i < n && x.cmap == 0 )
165 if ( c[i].visualid == vi->visualid )
167 x.cmap = c[i].colormap;
179 // no shared cmap found
180 x.cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
184 cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
189 int GLViewer_ViewPort::nCounter = 0;
190 QCursor* GLViewer_ViewPort::defCursor = 0;
191 QCursor* GLViewer_ViewPort::panglCursor = 0;
192 QCursor* GLViewer_ViewPort::handCursor = 0;
193 QCursor* GLViewer_ViewPort::panCursor = 0;
194 QCursor* GLViewer_ViewPort::zoomCursor = 0;
195 QCursor* GLViewer_ViewPort::rotCursor = 0;
196 QCursor* GLViewer_ViewPort::sketchCursor = 0;
199 Creates the necessary viewport cursors. [ static ]
201 void GLViewer_ViewPort::createCursors ()
203 defCursor = new QCursor( Qt::ArrowCursor );
204 panglCursor = new QCursor( Qt::CrossCursor );
205 handCursor = new QCursor( Qt::PointingHandCursor );
206 panCursor = new QCursor( Qt::SizeAllCursor );
208 SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
209 zoomCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ZOOM" ) ) );
210 rotCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ROTATE" ) ) );
211 sketchCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_SKETCH" ) ) );
215 Destroys the viewport cursors. [ static ]
217 void GLViewer_ViewPort::destroyCursors()
219 delete defCursor; defCursor = 0;
220 delete panglCursor; panglCursor = 0;
221 delete handCursor; handCursor = 0;
222 delete panCursor; panCursor = 0;
223 delete zoomCursor; zoomCursor = 0;
224 delete rotCursor; rotCursor = 0;
225 delete sketchCursor; sketchCursor = 0;
229 Sets new default cursor. [ static ]
231 void GLViewer_ViewPort::setDefaultCursor( const QCursor& newCursor )
234 defCursor = new QCursor();
235 *defCursor = newCursor;
239 Sets new cursor for drawing rectangle in the viewport. [ static ]
241 void GLViewer_ViewPort::setHandCursor( const QCursor& newCursor )
244 handCursor = new QCursor();
245 *handCursor = newCursor;
249 Sets new cursor for panning. [ static ]
251 void GLViewer_ViewPort::setPanCursor( const QCursor& newCursor )
254 panCursor = new QCursor();
255 *panCursor = newCursor;
259 Sets new cursor for global panning. [ static ]
261 void GLViewer_ViewPort::setPanglCursor( const QCursor& newCursor )
264 panglCursor = new QCursor();
265 *panglCursor = newCursor;
269 Sets new cursor for zooming. [ static ]
271 void GLViewer_ViewPort::setZoomCursor( const QCursor& newCursor )
274 zoomCursor = new QCursor();
275 *zoomCursor = newCursor;
279 Sets new cursor for rotating. [ static ]
281 void GLViewer_ViewPort::setRotCursor( const QCursor& newCursor )
284 rotCursor = new QCursor();
285 *rotCursor = newCursor;
289 Sets new cursor for rotating. [ static ]
291 void GLViewer_ViewPort::setSketchCursor( const QCursor& newCursor )
294 sketchCursor = new QCursor();
295 *sketchCursor = newCursor;
301 GLViewer_ViewPort::GLViewer_ViewPort( QWidget* parent )
302 : QWidget( parent, 0 )
310 GLViewer_ViewPort::~GLViewer_ViewPort()
316 Initializes viewport. [ private ]
318 void GLViewer_ViewPort::initialize()
320 if ( nCounter++ == 0 )
323 //myPopupActions.setAutoDelete( true );
324 myPaintersRedrawing = false;
325 myEnableSketching = false;
326 myEnableTransform = true;
328 setMouseTracking( true );
329 setBackgroundRole( QPalette::NoRole );//NoBackground );
331 setFocusPolicy( Qt::StrongFocus );
335 Cleans up the viewport. [ private ]
337 void GLViewer_ViewPort::cleanup()
339 if ( --nCounter == 0 )
344 Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
346 void GLViewer_ViewPort::selectVisualId( ViewType type )
349 XVisualInfo* pVisualInfo;
350 if ( QX11Info::display() )
352 /* Initialization with the default VisualID */
353 //Visual *v = DefaultVisual( x11Display(), DefaultScreen( x11Display() ) );
354 // int visualID = XVisualIDFromVisual( v ); unused
356 /* Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
357 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
358 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
360 pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
365 XSetWindowAttributes a;
367 a.colormap = choose_cmap( QX11Info::display(), pVisualInfo ); /* find best colormap */
368 a.background_pixel = QColormap::instance().pixel( backgroundColor() );
369 a.border_pixel = QColormap::instance().pixel( Qt::black );
370 Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
371 if ( parentWidget() )
372 p = parentWidget()->winId();
375 if ( type == Type2D ) // creating simple X window for 2d
377 unsigned long xbackground =
378 BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
379 unsigned long xforeground =
380 WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
382 w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
383 height(), 0, xforeground, xbackground );
385 else if ( type == Type3D )
387 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
388 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
389 CWBackPixel | CWBorderPixel | CWColormap, &a );
397 if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
399 cmw = new Window[count+1];
400 memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
401 XFree( (char*)cmwret );
404 for ( i = 0; i < count; i++ )
406 if ( cmw[i] == winId() ) /* replace old window */
413 if ( i >= count ) /* append new window */
419 cmw = new Window[count];
423 /* Creating new window (with good VisualID) for this widget */
425 XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
433 XFree( (char *)pVisualInfo );
435 XFlush( QX11Info::display() );
441 Sets the background 'color'. [ virtual ]
443 void GLViewer_ViewPort::setBackgroundColor( const QColor& color )
445 QPalette pal = palette();
446 pal.setColor( QPalette::Background, color );
452 Returns the background color. [ virtual ]
454 QColor GLViewer_ViewPort::backgroundColor() const
456 return palette().color( QPalette::Active, QPalette::Background );
460 Returns 'true' if sketching is enabled in this viewport. [ public ]
462 bool GLViewer_ViewPort::isSketchingEnabled() const
464 return myEnableSketching;
468 Enables / disables sketching [ public ]
470 void GLViewer_ViewPort::setSketchingEnabled( bool enable )
472 myEnableSketching = enable;
476 Returns 'true' if transformations ( rotation, zoom etc. )
477 are enabled in this viewport. [ public ]
479 bool GLViewer_ViewPort::isTransformEnabled() const
481 return myEnableTransform;
485 Enables / disables transformations. [ public ]
487 void GLViewer_ViewPort::setTransformEnabled( bool enable )
489 myEnableTransform = enable;
493 Emits 'mouseEvent' signal. [ virtual protected ]
495 void GLViewer_ViewPort::mousePressEvent( QMouseEvent *e )
497 emit vpMouseEvent( e );
501 Emits 'mouseEvent' signal. [ virtual protected ]
503 void GLViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
505 emit vpMouseEvent( e );
509 Emits 'mouseEvent' signal. [ virtual protected ]
511 void GLViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
513 emit vpMouseEvent( e );
515 /* show popup menu */
516 if ( e->button() == Qt::RightButton )
518 //QPopupMenu* popup = createPopup();
519 //if ( popup && popup->count() )
520 // popup->exec( QCursor::pos() );
521 //destroyPopup( /*popup*/ );
526 Emits 'mouseEvent' signal. [ virtual protected ]
528 void GLViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
530 emit vpMouseEvent( e );
534 Emits 'keyEvent' signal. [ virtual protected ]
536 void GLViewer_ViewPort::keyPressEvent( QKeyEvent *e )
538 emit vpKeyEvent( e );
542 Emits 'keyEvent' signal. [ virtual protected ]
544 void GLViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
546 emit vpKeyEvent( e );
550 Emits 'mouseEvent' signal. [ virtual protected ]
552 void GLViewer_ViewPort::wheelEvent( QWheelEvent *e )
554 emit vpWheelEvent( e );
558 Repaints the viewport. [ virtual protected ]
560 void GLViewer_ViewPort::paintEvent( QPaintEvent* )
562 if ( myPaintersRedrawing )
565 emit vpDrawExternal( &p );
566 myPaintersRedrawing = false;
571 Forces to redraw the viewport by an external painter. [ public ]
573 void GLViewer_ViewPort::redrawPainters()
575 myPaintersRedrawing = true;
580 Updates this view. Does nothing by default. [ virtual public ]
582 void GLViewer_ViewPort::onUpdate()
587 Sets the background color with color selection dialog. [ virtual protected slot ]
589 void GLViewer_ViewPort::onChangeBgColor()
591 QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
592 if ( selColor.isValid() )
593 setBackgroundColor( selColor );
597 Custom context menu event handler
599 void GLViewer_ViewPort::contextMenuEvent( QContextMenuEvent* e )
601 //if ( e->reason() != QContextMenuEvent::Mouse )
602 emit contextMenuRequested( e );