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 setAttribute( Qt::WA_PaintOnScreen );
222 setAttribute( Qt::WA_NoSystemBackground );
226 Cleans up the viewport. [ private ]
228 void OCCViewer_ViewPort::cleanup()
233 Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
235 void OCCViewer_ViewPort::selectVisualId()
237 #if !defined WIN32 && !defined __APPLE__
238 XVisualInfo* pVisualInfo;
239 if ( QX11Info::display() )
241 /* Initialization with the default VisualID */
242 Visual *v = DefaultVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
243 /*int visualID = */XVisualIDFromVisual( v );
245 /* Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
246 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
247 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
249 pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
254 XSetWindowAttributes a;
256 a.colormap = choose_cmap( QX11Info::display(), pVisualInfo ); /* find best colormap */
257 a.background_pixel = QColormap::instance().pixel( backgroundColor() );
258 a.border_pixel = QColormap::instance().pixel( Qt::black );
259 Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
260 if ( parentWidget() )
261 p = parentWidget()->winId();
265 if ( type == Type2D ) // creating simple X window for 2d
267 unsigned long xbackground =
268 BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
269 unsigned long xforeground =
270 WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
272 w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
273 height(), 0, xforeground, xbackground );
275 else if ( type == Type3D )
277 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
278 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
279 CWBackPixel | CWBorderPixel | CWColormap, &a );
284 w = XCreateWindow( QX11Info::display(), p, x(), y(), width(), height(),
285 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
286 CWBackPixel | CWBorderPixel | CWColormap, &a );
291 if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
293 cmw = new Window[count+1];
294 memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
295 XFree( (char*)cmwret );
298 for ( i = 0; i < count; i++ )
300 if ( cmw[i] == winId() ) /* replace old window */
307 if ( i >= count ) /* append new window */
313 cmw = new Window[count];
317 /* Creating new window (with good VisualID) for this widget */
319 XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
326 XFree( (char *)pVisualInfo );
328 XFlush( QX11Info::display() );
334 Sets the background 'color'. [ virtual ]
336 void OCCViewer_ViewPort::setBackgroundColor( const QColor& color )
338 QPalette pal = palette();
339 pal.setColor( QPalette::Background, color );
342 emit vpChangeBGColor( color );
346 Returns the background color. [ virtual ]
348 QColor OCCViewer_ViewPort::backgroundColor() const
350 return palette().color( QPalette::Active, QPalette::Background );
354 Returns 'true' if sketching is enabled in this viewport. [ public ]
356 bool OCCViewer_ViewPort::isSketchingEnabled() const
358 return myEnableSketching;
362 Enables / disables sketching [ public ]
364 void OCCViewer_ViewPort::setSketchingEnabled( bool enable )
366 myEnableSketching = enable;
370 Returns 'true' if transformations ( rotation, zoom etc. )
371 are enabled in this viewport. [ public ]
373 bool OCCViewer_ViewPort::isTransformEnabled() const
375 return myEnableTransform;
379 Enables / disables transformations. [ public ]
381 void OCCViewer_ViewPort::setTransformEnabled( bool enable )
383 myEnableTransform = enable;
387 Emits 'mouseEvent' signal. [ virtual protected ]
389 void OCCViewer_ViewPort::mousePressEvent( QMouseEvent *e )
391 emit vpMouseEvent( e );
395 Emits 'mouseEvent' signal. [ virtual protected ]
397 void OCCViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
399 emit vpMouseEvent( e );
403 Emits 'mouseEvent' signal. [ virtual protected ]
405 void OCCViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
407 emit vpMouseEvent( e );
411 Emits 'mouseEvent' signal. [ virtual protected ]
413 void OCCViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
415 emit vpMouseEvent( e );
419 Emits 'keyEvent' signal. [ virtual protected ]
421 void OCCViewer_ViewPort::keyPressEvent( QKeyEvent *e )
423 emit vpKeyEvent( e );
427 Emits 'keyEvent' signal. [ virtual protected ]
429 void OCCViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
431 emit vpKeyEvent( e );
435 Repaints the viewport. [ virtual protected ]
437 void OCCViewer_ViewPort::paintEvent( QPaintEvent* )
439 if ( myPaintersRedrawing )
442 emit vpDrawExternal( &p );
443 myPaintersRedrawing = false;
448 Forces to redraw the viewport by an external painter. [ public ]
450 void OCCViewer_ViewPort::redrawPainters()
452 myPaintersRedrawing = true;
457 Updates this view. Does nothing by default. [ virtual public ]
459 void OCCViewer_ViewPort::onUpdate()
464 Get paint engine for the OpenGL viewer. [ virtual public ]
466 QPaintEngine* OCCViewer_ViewPort::paintEngine() const
472 Performs synchronization of view parameters with the specified view.
473 Returns \c true if synchronization is done successfully or \c false otherwise.
474 Default implementation does nothing (return \c false)
476 bool OCCViewer_ViewPort::synchronize( OCCViewer_ViewPort* )
482 Sets the background color with color selection dialog. [ virtual protected slot ]
484 void OCCViewer_ViewPort::onChangeBackground()
486 QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
487 if ( selColor.isValid() )
488 setBackgroundColor( selColor );