1 // Copyright (C) 2007-2023 CEA, EDF, 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;
124 if ( vi->visualid == XVisualIDFromVisual( XDefaultVisual( QX11Info::display(), -1 ) ) )
127 cout << "Using XDefaultColormap" << endl;
129 return XDefaultColormap( QX11Info::display(), -1 );
133 Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
134 if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
136 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
139 while ( i < n && x.cmap == 0 )
141 if ( c[i].visualid == vi->visual->visualid )
143 x.cmap = c[i].colormap;
152 #if !defined( _OS_SOLARIS_ )
155 if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
157 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
160 while ( i < n && x.cmap == 0 )
162 if ( c[i].visualid == vi->visualid )
164 x.cmap = c[i].colormap;
176 // no shared cmap found
177 x.cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
181 cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
186 int GLViewer_ViewPort::nCounter = 0;
187 QCursor* GLViewer_ViewPort::defCursor = 0;
188 QCursor* GLViewer_ViewPort::panglCursor = 0;
189 QCursor* GLViewer_ViewPort::handCursor = 0;
190 QCursor* GLViewer_ViewPort::panCursor = 0;
191 QCursor* GLViewer_ViewPort::zoomCursor = 0;
192 QCursor* GLViewer_ViewPort::rotCursor = 0;
193 QCursor* GLViewer_ViewPort::sketchCursor = 0;
196 Creates the necessary viewport cursors. [ static ]
198 void GLViewer_ViewPort::createCursors ()
200 defCursor = new QCursor( Qt::ArrowCursor );
201 panglCursor = new QCursor( Qt::CrossCursor );
202 handCursor = new QCursor( Qt::PointingHandCursor );
203 panCursor = new QCursor( Qt::SizeAllCursor );
205 SUIT_ResourceMgr* rmgr = SUIT_Session::session()->resourceMgr();
206 zoomCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ZOOM" ) ) );
207 rotCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_ROTATE" ) ) );
208 sketchCursor = new QCursor( rmgr->loadPixmap( "GLViewer", tr( "ICON_GL_CURSOR_SKETCH" ) ) );
212 Destroys the viewport cursors. [ static ]
214 void GLViewer_ViewPort::destroyCursors()
216 delete defCursor; defCursor = 0;
217 delete panglCursor; panglCursor = 0;
218 delete handCursor; handCursor = 0;
219 delete panCursor; panCursor = 0;
220 delete zoomCursor; zoomCursor = 0;
221 delete rotCursor; rotCursor = 0;
222 delete sketchCursor; sketchCursor = 0;
226 Sets new default cursor. [ static ]
228 void GLViewer_ViewPort::setDefaultCursor( const QCursor& newCursor )
231 defCursor = new QCursor();
232 *defCursor = newCursor;
236 Sets new cursor for drawing rectangle in the viewport. [ static ]
238 void GLViewer_ViewPort::setHandCursor( const QCursor& newCursor )
241 handCursor = new QCursor();
242 *handCursor = newCursor;
246 Sets new cursor for panning. [ static ]
248 void GLViewer_ViewPort::setPanCursor( const QCursor& newCursor )
251 panCursor = new QCursor();
252 *panCursor = newCursor;
256 Sets new cursor for global panning. [ static ]
258 void GLViewer_ViewPort::setPanglCursor( const QCursor& newCursor )
261 panglCursor = new QCursor();
262 *panglCursor = newCursor;
266 Sets new cursor for zooming. [ static ]
268 void GLViewer_ViewPort::setZoomCursor( const QCursor& newCursor )
271 zoomCursor = new QCursor();
272 *zoomCursor = newCursor;
276 Sets new cursor for rotating. [ static ]
278 void GLViewer_ViewPort::setRotCursor( const QCursor& newCursor )
281 rotCursor = new QCursor();
282 *rotCursor = newCursor;
286 Sets new cursor for rotating. [ static ]
288 void GLViewer_ViewPort::setSketchCursor( const QCursor& newCursor )
291 sketchCursor = new QCursor();
292 *sketchCursor = newCursor;
298 GLViewer_ViewPort::GLViewer_ViewPort( QWidget* parent )
299 : QWidget( parent, 0 )
307 GLViewer_ViewPort::~GLViewer_ViewPort()
313 Initializes viewport. [ private ]
315 void GLViewer_ViewPort::initialize()
317 if ( nCounter++ == 0 )
320 //myPopupActions.setAutoDelete( true );
321 myPaintersRedrawing = false;
322 myEnableSketching = false;
323 myEnableTransform = true;
325 setMouseTracking( true );
326 setBackgroundRole( QPalette::NoRole );//NoBackground );
328 setFocusPolicy( Qt::StrongFocus );
332 Cleans up the viewport. [ private ]
334 void GLViewer_ViewPort::cleanup()
336 if ( --nCounter == 0 )
341 Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
343 void GLViewer_ViewPort::selectVisualId( ViewType type )
345 #if !defined WIN32 && !defined __APPLE__
346 XVisualInfo* pVisualInfo;
347 if ( QX11Info::display() )
349 /* Initialization with the default VisualID */
350 //Visual *v = DefaultVisual( x11Display(), DefaultScreen( x11Display() ) );
351 // int visualID = XVisualIDFromVisual( v ); unused
353 /* Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
354 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
355 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
357 pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
362 XSetWindowAttributes a;
364 a.colormap = choose_cmap( QX11Info::display(), pVisualInfo ); /* find best colormap */
365 a.background_pixel = QColormap::instance().pixel( backgroundColor() );
366 a.border_pixel = QColormap::instance().pixel( Qt::black );
367 Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
368 if ( parentWidget() )
369 p = parentWidget()->winId();
372 if ( type == Type2D ) // creating simple X window for 2d
374 unsigned long xbackground =
375 BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
376 unsigned long xforeground =
377 WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
379 w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
380 height(), 0, xforeground, xbackground );
382 else if ( type == Type3D )
384 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
385 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
386 CWBackPixel | CWBorderPixel | CWColormap, &a );
394 if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
396 cmw = new Window[count+1];
397 memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
398 XFree( (char*)cmwret );
401 for ( i = 0; i < count; i++ )
403 if ( cmw[i] == winId() ) /* replace old window */
410 if ( i >= count ) /* append new window */
416 cmw = new Window[count];
420 /* Creating new window (with good VisualID) for this widget */
422 XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
430 XFree( (char *)pVisualInfo );
432 XFlush( QX11Info::display() );
438 Sets the background 'color'. [ virtual ]
440 void GLViewer_ViewPort::setBackgroundColor( const QColor& color )
442 QPalette pal = palette();
443 pal.setColor( QPalette::Background, color );
449 Returns the background color. [ virtual ]
451 QColor GLViewer_ViewPort::backgroundColor() const
453 return palette().color( QPalette::Active, QPalette::Background );
457 Returns 'true' if sketching is enabled in this viewport. [ public ]
459 bool GLViewer_ViewPort::isSketchingEnabled() const
461 return myEnableSketching;
465 Enables / disables sketching [ public ]
467 void GLViewer_ViewPort::setSketchingEnabled( bool enable )
469 myEnableSketching = enable;
473 Returns 'true' if transformations ( rotation, zoom etc. )
474 are enabled in this viewport. [ public ]
476 bool GLViewer_ViewPort::isTransformEnabled() const
478 return myEnableTransform;
482 Enables / disables transformations. [ public ]
484 void GLViewer_ViewPort::setTransformEnabled( bool enable )
486 myEnableTransform = enable;
490 Emits 'mouseEvent' signal. [ virtual protected ]
492 void GLViewer_ViewPort::mousePressEvent( QMouseEvent *e )
494 emit vpMouseEvent( e );
498 Emits 'mouseEvent' signal. [ virtual protected ]
500 void GLViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
502 emit vpMouseEvent( e );
506 Emits 'mouseEvent' signal. [ virtual protected ]
508 void GLViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
510 emit vpMouseEvent( e );
512 /* show popup menu */
513 if ( e->button() == Qt::RightButton )
515 //QPopupMenu* popup = createPopup();
516 //if ( popup && popup->count() )
517 // popup->exec( QCursor::pos() );
518 //destroyPopup( /*popup*/ );
523 Emits 'mouseEvent' signal. [ virtual protected ]
525 void GLViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
527 emit vpMouseEvent( e );
531 Emits 'keyEvent' signal. [ virtual protected ]
533 void GLViewer_ViewPort::keyPressEvent( QKeyEvent *e )
535 emit vpKeyEvent( e );
539 Emits 'keyEvent' signal. [ virtual protected ]
541 void GLViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
543 emit vpKeyEvent( e );
547 Emits 'mouseEvent' signal. [ virtual protected ]
549 void GLViewer_ViewPort::wheelEvent( QWheelEvent *e )
551 emit vpWheelEvent( e );
555 Repaints the viewport. [ virtual protected ]
557 void GLViewer_ViewPort::paintEvent( QPaintEvent* )
559 if ( myPaintersRedrawing )
562 emit vpDrawExternal( &p );
563 myPaintersRedrawing = false;
568 Forces to redraw the viewport by an external painter. [ public ]
570 void GLViewer_ViewPort::redrawPainters()
572 myPaintersRedrawing = true;
577 Updates this view. Does nothing by default. [ virtual public ]
579 void GLViewer_ViewPort::onUpdate()
584 Sets the background color with color selection dialog. [ virtual protected slot ]
586 void GLViewer_ViewPort::onChangeBgColor()
588 QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
589 if ( selColor.isValid() )
590 setBackgroundColor( selColor );
594 Custom context menu event handler
596 void GLViewer_ViewPort::contextMenuEvent( QContextMenuEvent* e )
598 //if ( e->reason() != QContextMenuEvent::Mouse )
599 emit contextMenuRequested( e );