1 // Copyright (C) 2007-2016 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, or (at your option) any later version.
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>
45 #if !defined WIN32 && !defined __APPLE__
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>
66 XStandardColormap scmap;
72 CMapEntry::CMapEntry()
82 CMapEntry::~CMapEntry()
85 XFreeColormap( QX11Info::display(), cmap );
88 static QMultiHash<int,CMapEntry> *cmap_dict = 0;
89 static bool mesa_gl = false;
91 static void cleanup_cmaps()
95 //while (!cmap_dict->isEmpty())
96 // cmap_dict->erase(cmap_dict->begin());
102 static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
106 cmap_dict = new QMultiHash<int,CMapEntry>;
107 const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
108 mesa_gl = strstr( v,"Mesa" ) != 0;
109 qAddPostRoutine( cleanup_cmaps );
112 QHash<int,CMapEntry>::iterator itH = cmap_dict->find( (long)vi->visualid );
113 if ( itH != cmap_dict->end() ) // found colormap for visual
114 return itH.value().cmap;
118 XStandardColormap *c;
122 cout << "Choosing cmap for vID = " << vi->visualid << endl;
125 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
126 if ( vi->visualid == XVisualIDFromVisual( (Visual*)QX11Info::appVisual() ) )
129 cout << "Using x11AppColormap" << endl;
131 return QX11Info::appColormap();
134 if ( vi->visualid == XVisualIDFromVisual( XDefaultVisual( QX11Info::display(), -1 ) ) )
137 cout << "Using XDefaultColormap" << endl;
139 return XDefaultColormap( QX11Info::display(), -1 );
144 Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
145 if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
147 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
150 while ( i < n && x.cmap == 0 )
152 if ( c[i].visualid == vi->visual->visualid )
154 x.cmap = c[i].colormap;
163 #if !defined( _OS_SOLARIS_ )
166 if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
168 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
171 while ( i < n && x.cmap == 0 )
173 if ( c[i].visualid == vi->visualid )
175 x.cmap = c[i].colormap;
187 // no shared cmap found
188 x.cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
192 cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
197 int GLViewer_ViewPort::nCounter = 0;
198 QCursor* GLViewer_ViewPort::defCursor = 0;
199 QCursor* GLViewer_ViewPort::panglCursor = 0;
200 QCursor* GLViewer_ViewPort::handCursor = 0;
201 QCursor* GLViewer_ViewPort::panCursor = 0;
202 QCursor* GLViewer_ViewPort::zoomCursor = 0;
203 QCursor* GLViewer_ViewPort::rotCursor = 0;
204 QCursor* GLViewer_ViewPort::sketchCursor = 0;
207 Creates the necessary viewport cursors. [ static ]
209 void GLViewer_ViewPort::createCursors ()
211 defCursor = new QCursor( Qt::ArrowCursor );
212 panglCursor = new QCursor( Qt::CrossCursor );
213 handCursor = new QCursor( Qt::PointingHandCursor );
214 panCursor = new QCursor( Qt::SizeAllCursor );
216 SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
217 zoomCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ZOOM" ) ) );
218 rotCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ROTATE" ) ) );
219 sketchCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_SKETCH" ) ) );
223 Destroys the viewport cursors. [ static ]
225 void GLViewer_ViewPort::destroyCursors()
227 delete defCursor; defCursor = 0;
228 delete panglCursor; panglCursor = 0;
229 delete handCursor; handCursor = 0;
230 delete panCursor; panCursor = 0;
231 delete zoomCursor; zoomCursor = 0;
232 delete rotCursor; rotCursor = 0;
233 delete sketchCursor; sketchCursor = 0;
237 Sets new default cursor. [ static ]
239 void GLViewer_ViewPort::setDefaultCursor( const QCursor& newCursor )
242 defCursor = new QCursor();
243 *defCursor = newCursor;
247 Sets new cursor for drawing rectangle in the viewport. [ static ]
249 void GLViewer_ViewPort::setHandCursor( const QCursor& newCursor )
252 handCursor = new QCursor();
253 *handCursor = newCursor;
257 Sets new cursor for panning. [ static ]
259 void GLViewer_ViewPort::setPanCursor( const QCursor& newCursor )
262 panCursor = new QCursor();
263 *panCursor = newCursor;
267 Sets new cursor for global panning. [ static ]
269 void GLViewer_ViewPort::setPanglCursor( const QCursor& newCursor )
272 panglCursor = new QCursor();
273 *panglCursor = newCursor;
277 Sets new cursor for zooming. [ static ]
279 void GLViewer_ViewPort::setZoomCursor( const QCursor& newCursor )
282 zoomCursor = new QCursor();
283 *zoomCursor = newCursor;
287 Sets new cursor for rotating. [ static ]
289 void GLViewer_ViewPort::setRotCursor( const QCursor& newCursor )
292 rotCursor = new QCursor();
293 *rotCursor = newCursor;
297 Sets new cursor for rotating. [ static ]
299 void GLViewer_ViewPort::setSketchCursor( const QCursor& newCursor )
302 sketchCursor = new QCursor();
303 *sketchCursor = newCursor;
309 GLViewer_ViewPort::GLViewer_ViewPort( QWidget* parent )
310 : QWidget( parent, 0 )
318 GLViewer_ViewPort::~GLViewer_ViewPort()
324 Initializes viewport. [ private ]
326 void GLViewer_ViewPort::initialize()
328 if ( nCounter++ == 0 )
331 //myPopupActions.setAutoDelete( true );
332 myPaintersRedrawing = false;
333 myEnableSketching = false;
334 myEnableTransform = true;
336 setMouseTracking( true );
337 setBackgroundRole( QPalette::NoRole );//NoBackground );
339 setFocusPolicy( Qt::StrongFocus );
343 Cleans up the viewport. [ private ]
345 void GLViewer_ViewPort::cleanup()
347 if ( --nCounter == 0 )
352 Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
354 void GLViewer_ViewPort::selectVisualId( ViewType type )
356 #if !defined WIN32 && !defined __APPLE__
357 XVisualInfo* pVisualInfo;
358 if ( QX11Info::display() )
360 /* Initialization with the default VisualID */
361 //Visual *v = DefaultVisual( x11Display(), DefaultScreen( x11Display() ) );
362 // int visualID = XVisualIDFromVisual( v ); unused
364 /* Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
365 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
366 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
368 pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
373 XSetWindowAttributes a;
375 a.colormap = choose_cmap( QX11Info::display(), pVisualInfo ); /* find best colormap */
376 a.background_pixel = QColormap::instance().pixel( backgroundColor() );
377 a.border_pixel = QColormap::instance().pixel( Qt::black );
378 Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
379 if ( parentWidget() )
380 p = parentWidget()->winId();
383 if ( type == Type2D ) // creating simple X window for 2d
385 unsigned long xbackground =
386 BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
387 unsigned long xforeground =
388 WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
390 w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
391 height(), 0, xforeground, xbackground );
393 else if ( type == Type3D )
395 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
396 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
397 CWBackPixel | CWBorderPixel | CWColormap, &a );
405 if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
407 cmw = new Window[count+1];
408 memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
409 XFree( (char*)cmwret );
412 for ( i = 0; i < count; i++ )
414 if ( cmw[i] == winId() ) /* replace old window */
421 if ( i >= count ) /* append new window */
427 cmw = new Window[count];
431 /* Creating new window (with good VisualID) for this widget */
433 XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
441 XFree( (char *)pVisualInfo );
443 XFlush( QX11Info::display() );
449 Sets the background 'color'. [ virtual ]
451 void GLViewer_ViewPort::setBackgroundColor( const QColor& color )
453 QPalette pal = palette();
454 pal.setColor( QPalette::Background, color );
460 Returns the background color. [ virtual ]
462 QColor GLViewer_ViewPort::backgroundColor() const
464 return palette().color( QPalette::Active, QPalette::Background );
468 Returns 'true' if sketching is enabled in this viewport. [ public ]
470 bool GLViewer_ViewPort::isSketchingEnabled() const
472 return myEnableSketching;
476 Enables / disables sketching [ public ]
478 void GLViewer_ViewPort::setSketchingEnabled( bool enable )
480 myEnableSketching = enable;
484 Returns 'true' if transformations ( rotation, zoom etc. )
485 are enabled in this viewport. [ public ]
487 bool GLViewer_ViewPort::isTransformEnabled() const
489 return myEnableTransform;
493 Enables / disables transformations. [ public ]
495 void GLViewer_ViewPort::setTransformEnabled( bool enable )
497 myEnableTransform = enable;
501 Emits 'mouseEvent' signal. [ virtual protected ]
503 void GLViewer_ViewPort::mousePressEvent( QMouseEvent *e )
505 emit vpMouseEvent( e );
509 Emits 'mouseEvent' signal. [ virtual protected ]
511 void GLViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
513 emit vpMouseEvent( e );
517 Emits 'mouseEvent' signal. [ virtual protected ]
519 void GLViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
521 emit vpMouseEvent( e );
523 /* show popup menu */
524 if ( e->button() == Qt::RightButton )
526 //QPopupMenu* popup = createPopup();
527 //if ( popup && popup->count() )
528 // popup->exec( QCursor::pos() );
529 //destroyPopup( /*popup*/ );
534 Emits 'mouseEvent' signal. [ virtual protected ]
536 void GLViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
538 emit vpMouseEvent( e );
542 Emits 'keyEvent' signal. [ virtual protected ]
544 void GLViewer_ViewPort::keyPressEvent( QKeyEvent *e )
546 emit vpKeyEvent( e );
550 Emits 'keyEvent' signal. [ virtual protected ]
552 void GLViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
554 emit vpKeyEvent( e );
558 Emits 'mouseEvent' signal. [ virtual protected ]
560 void GLViewer_ViewPort::wheelEvent( QWheelEvent *e )
562 emit vpWheelEvent( e );
566 Repaints the viewport. [ virtual protected ]
568 void GLViewer_ViewPort::paintEvent( QPaintEvent* )
570 if ( myPaintersRedrawing )
573 emit vpDrawExternal( &p );
574 myPaintersRedrawing = false;
579 Forces to redraw the viewport by an external painter. [ public ]
581 void GLViewer_ViewPort::redrawPainters()
583 myPaintersRedrawing = true;
588 Updates this view. Does nothing by default. [ virtual public ]
590 void GLViewer_ViewPort::onUpdate()
595 Sets the background color with color selection dialog. [ virtual protected slot ]
597 void GLViewer_ViewPort::onChangeBgColor()
599 QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
600 if ( selColor.isValid() )
601 setBackgroundColor( selColor );
605 Custom context menu event handler
607 void GLViewer_ViewPort::contextMenuEvent( QContextMenuEvent* e )
609 //if ( e->reason() != QContextMenuEvent::Mouse )
610 emit contextMenuRequested( e );