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
24 #define QT_CLEAN_NAMESPACE /* avoid definition of INT32 and INT8 */
27 #include "OCCViewer_ViewPort.h"
29 #include "SUIT_Session.h"
37 #include <QColorDialog>
39 #include <QCoreApplication>
43 #if !defined WIN32 && !defined __APPLE__
47 #include <X11/Xutil.h>
48 #include <X11/Xatom.h>
49 #include <X11/Xmu/StdCmap.h>
50 #undef QT_CLEAN_NAMESPACE
51 #include <Xw_Window.hxx>
59 XStandardColormap scmap;
65 CMapEntry::CMapEntry()
75 CMapEntry::~CMapEntry()
78 XFreeColormap( QX11Info::display(), cmap );
81 static QMultiHash<int,CMapEntry> *cmap_dict = 0;
82 static bool mesa_gl = false;
84 static void cleanup_cmaps()
88 //while (!cmap_dict->isEmpty())
89 // cmap_dict->erase(cmap_dict->begin());
95 static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
99 cmap_dict = new QMultiHash<int,CMapEntry>;
100 const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
101 mesa_gl = strstr( v,"Mesa" ) != 0;
102 qAddPostRoutine( cleanup_cmaps );
105 QHash<int,CMapEntry>::iterator itH = cmap_dict->find( (long)vi->visualid );
106 if ( itH != cmap_dict->end() ) // found colormap for visual
107 return itH.value().cmap;
111 XStandardColormap *c;
115 //cout << "Choosing cmap for vID = " << vi->visualid << endl;
118 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
119 if ( vi->visualid == XVisualIDFromVisual( (Visual*)QX11Info::appVisual() ) )
122 // cout << "Using x11AppColormap" << endl;
124 return QX11Info::appColormap();
127 if ( vi->visualid == XVisualIDFromVisual( XDefaultVisual( QX11Info::display(), -1 ) ) )
130 // cout << "Using XDefaultColormap" << endl;
132 return XDefaultColormap( QX11Info::display(), -1 );
137 Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
138 if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
140 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
143 while ( i < n && x.cmap == 0 )
145 if ( c[i].visualid == vi->visual->visualid )
147 x.cmap = c[i].colormap;
156 #if !defined( _OS_SOLARIS_ )
159 if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
161 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
164 while ( i < n && x.cmap == 0 )
166 if ( c[i].visualid == vi->visualid )
168 x.cmap = c[i].colormap;
180 // no shared cmap found
181 x.cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
185 cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
194 OCCViewer_ViewPort::OCCViewer_ViewPort( QWidget* parent )
203 OCCViewer_ViewPort::~OCCViewer_ViewPort()
209 Initializes viewport. [ private ]
211 void OCCViewer_ViewPort::initialize()
213 myPaintersRedrawing = false;
214 myEnableSketching = true;
215 myEnableTransform = true;
217 setMouseTracking( true );
218 setBackgroundRole( QPalette::NoRole );//NoBackground );
219 // set focus policy to threat QContextMenuEvent from keyboard
220 setFocusPolicy( Qt::StrongFocus );
221 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0) && OCC_VERSION_LARGE < 0x07000000) || QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
222 setAttribute( Qt::WA_PaintOnScreen );
224 setAttribute( Qt::WA_NoSystemBackground );
228 Cleans up the viewport. [ private ]
230 void OCCViewer_ViewPort::cleanup()
235 Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
237 void OCCViewer_ViewPort::selectVisualId()
239 #if !defined WIN32 && !defined __APPLE__
240 XVisualInfo* pVisualInfo;
241 if ( QX11Info::display() )
243 /* Initialization with the default VisualID */
244 Visual *v = DefaultVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
245 /*int visualID = */XVisualIDFromVisual( v );
247 /* Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
248 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
249 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
251 pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
256 XSetWindowAttributes a;
258 a.colormap = choose_cmap( QX11Info::display(), pVisualInfo ); /* find best colormap */
259 a.background_pixel = QColormap::instance().pixel( backgroundColor() );
260 a.border_pixel = QColormap::instance().pixel( Qt::black );
261 Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
262 if ( parentWidget() )
263 p = parentWidget()->winId();
267 if ( type == Type2D ) // creating simple X window for 2d
269 unsigned long xbackground =
270 BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
271 unsigned long xforeground =
272 WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
274 w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
275 height(), 0, xforeground, xbackground );
277 else if ( type == Type3D )
279 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
280 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
281 CWBackPixel | CWBorderPixel | CWColormap, &a );
286 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
287 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
288 CWBackPixel | CWBorderPixel | CWColormap, &a );
293 if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
295 cmw = new Window[count+1];
296 memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
297 XFree( (char*)cmwret );
300 for ( i = 0; i < count; i++ )
302 if ( cmw[i] == winId() ) /* replace old window */
309 if ( i >= count ) /* append new window */
315 cmw = new Window[count];
319 /* Creating new window (with good VisualID) for this widget */
321 XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
328 XFree( (char *)pVisualInfo );
330 XFlush( QX11Info::display() );
336 Sets the background 'color'. [ virtual ]
338 void OCCViewer_ViewPort::setBackgroundColor( const QColor& color )
340 QPalette pal = palette();
341 pal.setColor( QPalette::Background, color );
344 emit vpChangeBGColor( color );
348 Returns the background color. [ virtual ]
350 QColor OCCViewer_ViewPort::backgroundColor() const
352 return palette().color( QPalette::Active, QPalette::Background );
356 Returns 'true' if sketching is enabled in this viewport. [ public ]
358 bool OCCViewer_ViewPort::isSketchingEnabled() const
360 return myEnableSketching;
364 Enables / disables sketching [ public ]
366 void OCCViewer_ViewPort::setSketchingEnabled( bool enable )
368 myEnableSketching = enable;
372 Returns 'true' if transformations ( rotation, zoom etc. )
373 are enabled in this viewport. [ public ]
375 bool OCCViewer_ViewPort::isTransformEnabled() const
377 return myEnableTransform;
381 Enables / disables transformations. [ public ]
383 void OCCViewer_ViewPort::setTransformEnabled( bool enable )
385 myEnableTransform = enable;
389 Emits 'mouseEvent' signal. [ virtual protected ]
391 void OCCViewer_ViewPort::mousePressEvent( QMouseEvent *e )
393 emit vpMouseEvent( e );
397 Emits 'mouseEvent' signal. [ virtual protected ]
399 void OCCViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
401 emit vpMouseEvent( e );
405 Emits 'mouseEvent' signal. [ virtual protected ]
407 void OCCViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
409 emit vpMouseEvent( e );
413 Emits 'mouseEvent' signal. [ virtual protected ]
415 void OCCViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
417 emit vpMouseEvent( e );
421 Emits 'keyEvent' signal. [ virtual protected ]
423 void OCCViewer_ViewPort::keyPressEvent( QKeyEvent *e )
425 emit vpKeyEvent( e );
429 Emits 'keyEvent' signal. [ virtual protected ]
431 void OCCViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
433 emit vpKeyEvent( e );
437 Repaints the viewport. [ virtual protected ]
439 void OCCViewer_ViewPort::paintEvent( QPaintEvent* )
441 if ( myPaintersRedrawing )
444 emit vpDrawExternal( &p );
445 myPaintersRedrawing = false;
450 Forces to redraw the viewport by an external painter. [ public ]
452 void OCCViewer_ViewPort::redrawPainters()
454 myPaintersRedrawing = true;
459 Updates this view. Does nothing by default. [ virtual public ]
461 void OCCViewer_ViewPort::onUpdate()
466 Get paint engine for the OpenGL viewer. [ virtual public ]
468 QPaintEngine* OCCViewer_ViewPort::paintEngine() const
474 Performs synchronization of view parameters with the specified view.
475 Returns \c true if synchronization is done successfully or \c false otherwise.
476 Default implementation does nothing (return \c false)
478 bool OCCViewer_ViewPort::synchronize( OCCViewer_ViewPort* )
484 Sets the background color with color selection dialog. [ virtual protected slot ]
486 void OCCViewer_ViewPort::onChangeBackground()
488 QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
489 if ( selColor.isValid() )
490 setBackgroundColor( selColor );