1 // Copyright (C) 2007-2013 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>
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 ( vi->visualid == XVisualIDFromVisual( (Visual*)QX11Info::appVisual() ) )
128 cout << "Using x11AppColormap" << endl;
130 return QX11Info::appColormap();
135 Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
136 if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
138 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
141 while ( i < n && x.cmap == 0 )
143 if ( c[i].visualid == vi->visual->visualid )
145 x.cmap = c[i].colormap;
154 #if !defined( _OS_SOLARIS_ )
157 if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
159 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
162 while ( i < n && x.cmap == 0 )
164 if ( c[i].visualid == vi->visualid )
166 x.cmap = c[i].colormap;
178 // no shared cmap found
179 x.cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
183 cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
188 int GLViewer_ViewPort::nCounter = 0;
189 QCursor* GLViewer_ViewPort::defCursor = 0;
190 QCursor* GLViewer_ViewPort::panglCursor = 0;
191 QCursor* GLViewer_ViewPort::handCursor = 0;
192 QCursor* GLViewer_ViewPort::panCursor = 0;
193 QCursor* GLViewer_ViewPort::zoomCursor = 0;
194 QCursor* GLViewer_ViewPort::rotCursor = 0;
195 QCursor* GLViewer_ViewPort::sketchCursor = 0;
198 Creates the necessary viewport cursors. [ static ]
200 void GLViewer_ViewPort::createCursors ()
202 defCursor = new QCursor( Qt::ArrowCursor );
203 panglCursor = new QCursor( Qt::CrossCursor );
204 handCursor = new QCursor( Qt::PointingHandCursor );
205 panCursor = new QCursor( Qt::SizeAllCursor );
207 SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
208 zoomCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ZOOM" ) ) );
209 rotCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ROTATE" ) ) );
210 sketchCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_SKETCH" ) ) );
214 Destroys the viewport cursors. [ static ]
216 void GLViewer_ViewPort::destroyCursors()
218 delete defCursor; defCursor = 0;
219 delete panglCursor; panglCursor = 0;
220 delete handCursor; handCursor = 0;
221 delete panCursor; panCursor = 0;
222 delete zoomCursor; zoomCursor = 0;
223 delete rotCursor; rotCursor = 0;
224 delete sketchCursor; sketchCursor = 0;
228 Sets new default cursor. [ static ]
230 void GLViewer_ViewPort::setDefaultCursor( const QCursor& newCursor )
233 defCursor = new QCursor();
234 *defCursor = newCursor;
238 Sets new cursor for drawing rectangle in the viewport. [ static ]
240 void GLViewer_ViewPort::setHandCursor( const QCursor& newCursor )
243 handCursor = new QCursor();
244 *handCursor = newCursor;
248 Sets new cursor for panning. [ static ]
250 void GLViewer_ViewPort::setPanCursor( const QCursor& newCursor )
253 panCursor = new QCursor();
254 *panCursor = newCursor;
258 Sets new cursor for global panning. [ static ]
260 void GLViewer_ViewPort::setPanglCursor( const QCursor& newCursor )
263 panglCursor = new QCursor();
264 *panglCursor = newCursor;
268 Sets new cursor for zooming. [ static ]
270 void GLViewer_ViewPort::setZoomCursor( const QCursor& newCursor )
273 zoomCursor = new QCursor();
274 *zoomCursor = newCursor;
278 Sets new cursor for rotating. [ static ]
280 void GLViewer_ViewPort::setRotCursor( const QCursor& newCursor )
283 rotCursor = new QCursor();
284 *rotCursor = newCursor;
288 Sets new cursor for rotating. [ static ]
290 void GLViewer_ViewPort::setSketchCursor( const QCursor& newCursor )
293 sketchCursor = new QCursor();
294 *sketchCursor = newCursor;
300 GLViewer_ViewPort::GLViewer_ViewPort( QWidget* parent )
301 : QWidget( parent, 0 )
309 GLViewer_ViewPort::~GLViewer_ViewPort()
315 Initializes viewport. [ private ]
317 void GLViewer_ViewPort::initialize()
319 if ( nCounter++ == 0 )
322 //myPopupActions.setAutoDelete( true );
323 myPaintersRedrawing = false;
324 myEnableSketching = false;
325 myEnableTransform = true;
327 setMouseTracking( true );
328 setBackgroundRole( QPalette::NoRole );//NoBackground );
330 setFocusPolicy( Qt::StrongFocus );
334 Cleans up the viewport. [ private ]
336 void GLViewer_ViewPort::cleanup()
338 if ( --nCounter == 0 )
343 Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
345 void GLViewer_ViewPort::selectVisualId( ViewType type )
348 XVisualInfo* pVisualInfo;
349 if ( QX11Info::display() )
351 /* Initialization with the default VisualID */
352 //Visual *v = DefaultVisual( x11Display(), DefaultScreen( x11Display() ) );
353 // int visualID = XVisualIDFromVisual( v ); unused
355 /* Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
356 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
357 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
359 pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
364 XSetWindowAttributes a;
366 a.colormap = choose_cmap( QX11Info::display(), pVisualInfo ); /* find best colormap */
367 a.background_pixel = QColormap::instance().pixel( backgroundColor() );
368 a.border_pixel = QColormap::instance().pixel( Qt::black );
369 Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
370 if ( parentWidget() )
371 p = parentWidget()->winId();
374 if ( type == Type2D ) // creating simple X window for 2d
376 unsigned long xbackground =
377 BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
378 unsigned long xforeground =
379 WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
381 w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
382 height(), 0, xforeground, xbackground );
384 else if ( type == Type3D )
386 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
387 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
388 CWBackPixel | CWBorderPixel | CWColormap, &a );
396 if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
398 cmw = new Window[count+1];
399 memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
400 XFree( (char*)cmwret );
403 for ( i = 0; i < count; i++ )
405 if ( cmw[i] == winId() ) /* replace old window */
412 if ( i >= count ) /* append new window */
418 cmw = new Window[count];
422 /* Creating new window (with good VisualID) for this widget */
424 XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
432 XFree( (char *)pVisualInfo );
434 XFlush( QX11Info::display() );
440 Sets the background 'color'. [ virtual ]
442 void GLViewer_ViewPort::setBackgroundColor( const QColor& color )
444 QPalette pal = palette();
445 pal.setColor( QPalette::Background, color );
451 Returns the background color. [ virtual ]
453 QColor GLViewer_ViewPort::backgroundColor() const
455 return palette().color( QPalette::Active, QPalette::Background );
459 Returns 'true' if sketching is enabled in this viewport. [ public ]
461 bool GLViewer_ViewPort::isSketchingEnabled() const
463 return myEnableSketching;
467 Enables / disables sketching [ public ]
469 void GLViewer_ViewPort::setSketchingEnabled( bool enable )
471 myEnableSketching = enable;
475 Returns 'true' if transformations ( rotation, zoom etc. )
476 are enabled in this viewport. [ public ]
478 bool GLViewer_ViewPort::isTransformEnabled() const
480 return myEnableTransform;
484 Enables / disables transformations. [ public ]
486 void GLViewer_ViewPort::setTransformEnabled( bool enable )
488 myEnableTransform = enable;
492 Emits 'mouseEvent' signal. [ virtual protected ]
494 void GLViewer_ViewPort::mousePressEvent( QMouseEvent *e )
496 emit vpMouseEvent( e );
500 Emits 'mouseEvent' signal. [ virtual protected ]
502 void GLViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
504 emit vpMouseEvent( e );
508 Emits 'mouseEvent' signal. [ virtual protected ]
510 void GLViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
512 emit vpMouseEvent( e );
514 /* show popup menu */
515 if ( e->button() == Qt::RightButton )
517 //QPopupMenu* popup = createPopup();
518 //if ( popup && popup->count() )
519 // popup->exec( QCursor::pos() );
520 //destroyPopup( /*popup*/ );
525 Emits 'mouseEvent' signal. [ virtual protected ]
527 void GLViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
529 emit vpMouseEvent( e );
533 Emits 'keyEvent' signal. [ virtual protected ]
535 void GLViewer_ViewPort::keyPressEvent( QKeyEvent *e )
537 emit vpKeyEvent( e );
541 Emits 'keyEvent' signal. [ virtual protected ]
543 void GLViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
545 emit vpKeyEvent( e );
549 Emits 'mouseEvent' signal. [ virtual protected ]
551 void GLViewer_ViewPort::wheelEvent( QWheelEvent *e )
553 emit vpWheelEvent( e );
557 Repaints the viewport. [ virtual protected ]
559 void GLViewer_ViewPort::paintEvent( QPaintEvent* )
561 if ( myPaintersRedrawing )
564 emit vpDrawExternal( &p );
565 myPaintersRedrawing = false;
570 Forces to redraw the viewport by an external painter. [ public ]
572 void GLViewer_ViewPort::redrawPainters()
574 myPaintersRedrawing = true;
579 Updates this view. Does nothing by default. [ virtual public ]
581 void GLViewer_ViewPort::onUpdate()
586 Sets the background color with color selection dialog. [ virtual protected slot ]
588 void GLViewer_ViewPort::onChangeBgColor()
590 QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
591 if ( selColor.isValid() )
592 setBackgroundColor( selColor );
596 Custom context menu event handler
598 void GLViewer_ViewPort::contextMenuEvent( QContextMenuEvent* e )
600 //if ( e->reason() != QContextMenuEvent::Mouse )
601 emit contextMenuRequested( e );