Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewPort.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/
18 //
19
20 #if !defined WNT
21 #define QT_CLEAN_NAMESPACE         /* avoid definition of INT32 and INT8 */
22 #endif
23
24 #include "OCCViewer_ViewPort.h"
25
26 #include "SUIT_Session.h"
27
28 #include <qrect.h>
29 #include <qcursor.h>
30 #include <qpixmap.h>
31 #include <qpainter.h>
32 #include <qintdict.h>
33 #include <qpopupmenu.h>
34 #include <qcolordialog.h>
35
36 #include <stdlib.h>
37
38 #if !defined WNT
39 #include <GL/glx.h>
40 #include <X11/Xlib.h>
41 #include <X11/Xutil.h>
42 #include <X11/Xatom.h>
43 #include <X11/Xmu/StdCmap.h>
44 #undef QT_CLEAN_NAMESPACE
45 #include <Xw_Window.hxx>
46 #include <Graphic3d_GraphicDevice.hxx>
47
48 struct CMapEntry
49 {
50         CMapEntry();
51         ~CMapEntry();
52         Colormap          cmap;
53         bool              alloc;
54         XStandardColormap scmap;
55 };
56
57 /*!
58   Constructor
59 */
60 CMapEntry::CMapEntry()
61 {
62         cmap = 0;
63         alloc = false;
64         scmap.colormap = 0;
65 }
66
67 /*!
68   Destructor
69 */
70 CMapEntry::~CMapEntry()
71 {
72         if ( alloc )
73         XFreeColormap( QPaintDevice::x11AppDisplay(), cmap );
74 }
75
76 static QIntDict<CMapEntry> *cmap_dict = 0;
77 static bool mesa_gl = false;
78
79 static void cleanup_cmaps()
80 {
81         if ( !cmap_dict )
82                 return;
83         cmap_dict->setAutoDelete( true );
84         delete cmap_dict;
85         cmap_dict = 0;
86 }
87
88 static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
89 {
90         if ( !cmap_dict )
91         {
92                 cmap_dict = new QIntDict<CMapEntry>;
93                 const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
94                 mesa_gl = strstr( v,"Mesa" ) != 0;
95                 qAddPostRoutine( cleanup_cmaps );
96         }
97
98         CMapEntry *x = cmap_dict->find( (long)vi->visualid );
99     if ( x )                                    // found colormap for visual
100         return x->cmap;
101
102     x = new CMapEntry();
103
104     XStandardColormap *c;
105     int n, i;
106
107 #ifdef DEBUG
108     cout << "Choosing cmap for vID = " << vi->visualid << endl;
109 #endif
110
111     if ( vi->visualid == XVisualIDFromVisual( (Visual*)QPaintDevice::x11AppVisual() ) )
112         {
113 #ifdef DEBUG
114                 cout << "Using x11AppColormap" << endl;
115 #endif
116                 return QPaintDevice::x11AppColormap();
117     }
118
119     if ( mesa_gl )
120         {
121                 Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
122                 if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
123                 {
124                 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
125             {
126                         i = 0;
127                             while ( i < n && x->cmap == 0 )
128                 {
129                                 if ( c[i].visualid == vi->visual->visualid )
130                                     {
131                                         x->cmap = c[i].colormap;
132                                             x->scmap = c[i];
133                                 }
134                                     i++;
135                 }
136                             XFree( (char*)c );
137                 }
138         }
139         }
140 #if !defined( _OS_SOLARIS_ )
141     if ( !x->cmap )
142     {
143             if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
144         {
145                     if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
146             {
147                             i = 0;
148                                 while ( i < n && x->cmap == 0 )
149                                 {
150                                     if ( c[i].visualid == vi->visualid )
151                     {
152                                             x->cmap = c[i].colormap;
153                                                 x->scmap = c[i];
154                                     }
155                                         i++;
156                 }
157                                 XFree( (char *)c );
158             }
159         }
160     }
161 #endif
162         if ( !x->cmap )
163         {
164                 // no shared cmap found
165                 x->cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
166                 x->alloc = true;
167         }
168
169         cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
170         return x->cmap;
171 }
172 #endif
173
174
175 /*!
176     Constructor
177 */
178 OCCViewer_ViewPort::OCCViewer_ViewPort( QWidget* parent )
179 : QWidget( parent, 0, WRepaintNoErase | WResizeNoErase )
180 {
181         initialize();
182 }
183
184 /*!
185     Destructor
186 */
187 OCCViewer_ViewPort::~OCCViewer_ViewPort()
188 {
189         cleanup();
190 }
191
192 /*!
193     Initializes viewport. [ private ]
194 */
195 void OCCViewer_ViewPort::initialize()
196 {
197   myPopupActions.setAutoDelete( true );
198   myPaintersRedrawing = false;
199   myEnableSketching = false;
200   myEnableTransform = true;
201   
202   setMouseTracking( true );
203   setBackgroundMode( NoBackground );
204   // set focus policy to threat QContextMenuEvent from keyboard  
205   setFocusPolicy( StrongFocus );
206 }
207
208 /*!
209     Cleans up the viewport. [ private ]
210 */
211 void OCCViewer_ViewPort::cleanup()
212 {
213 }
214
215 /*!
216     Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
217 */
218 void OCCViewer_ViewPort::selectVisualId()
219 {
220 #if !defined WNT
221         XVisualInfo* pVisualInfo;
222         if ( x11Display() )
223         {
224                 /* Initialization with the default VisualID */
225                 Visual *v = DefaultVisual( x11Display(), DefaultScreen( x11Display() ) );
226                 int visualID = XVisualIDFromVisual( v );
227
228                 /*  Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
229                 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
230                                                          GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
231
232                 pVisualInfo = ::glXChooseVisual( x11Display(), DefaultScreen( x11Display() ), visualAttr );
233
234                 if ( isVisible() )
235             hide();
236
237                 XSetWindowAttributes a;
238
239                 a.colormap = choose_cmap( x11Display(), pVisualInfo );      /* find best colormap */
240                 a.background_pixel = backgroundColor().pixel();
241                 a.border_pixel = black.pixel();
242                 Window p = RootWindow( x11Display(), DefaultScreen( x11Display() ) );
243                 if ( parentWidget() )
244             p = parentWidget()->winId();
245
246         Window w;
247         /*        if ( type == Type2D )  // creating simple X window for 2d
248         {
249             unsigned long xbackground =
250                 BlackPixel( x11Display(), DefaultScreen( x11Display() ) );
251             unsigned long xforeground =
252                 WhitePixel( x11Display(), DefaultScreen( x11Display() ) );
253
254             w = XCreateSimpleWindow ( x11Display(), p, x(), y(), width(),
255                                       height(), 0, xforeground, xbackground );
256         }
257         else if ( type == Type3D )
258         {
259                     w = XCreateWindow( x11Display(), p,  x(), y(), width(), height(),
260                                0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
261                                CWBackPixel | CWBorderPixel | CWColormap, &a );
262                 }
263                 else
264                 return;*/
265         w = XCreateWindow( x11Display(), p,  x(), y(), width(), height(),
266                            0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
267                            CWBackPixel | CWBorderPixel | CWColormap, &a );
268         
269                 Window *cmw;
270                 Window *cmwret;
271                 int count;
272                 if ( XGetWMColormapWindows( x11Display(), topLevelWidget()->winId(), &cmwret, &count ) )
273                 {
274                         cmw = new Window[count+1];
275                         memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
276                         XFree( (char*)cmwret );
277             int i;
278
279                         for ( i = 0; i < count; i++ )
280                         {
281                                 if ( cmw[i] == winId() ) /* replace old window */
282                                 {
283                                         cmw[i] = w;
284                                         break;
285                                 }
286                         }
287
288                         if ( i >= count )                        /* append new window */
289                                 cmw[count++] = w;
290                 }
291                 else
292                 {
293                         count = 1;
294                         cmw = new Window[count];
295                         cmw[0] = w;
296                 }
297
298                 /* Creating new window (with good VisualID) for this widget */
299                 create(w);
300                 XSetWMColormapWindows( x11Display(), topLevelWidget()->winId(), cmw, count );
301                 delete[] cmw;
302
303                 if ( isVisible() )
304             show();
305
306                 if ( pVisualInfo )
307         {
308                         XFree( (char *)pVisualInfo );
309                 }
310                 XFlush( x11Display() );
311         }
312 #endif
313 }
314
315 /*!
316     Sets the background 'color'. [ virtual ]
317 */
318 void OCCViewer_ViewPort::setBackgroundColor( const QColor& color )
319 {
320     QPalette pal = palette();
321     pal.setColor( QColorGroup::Background, color );
322     setPalette( pal );
323     repaint();
324     emit vpChangeBGColor( color );
325 }
326
327 /*!
328     Returns the background color. [ virtual ]
329 */
330 QColor OCCViewer_ViewPort::backgroundColor() const
331 {
332     return palette().active().background();
333 }
334
335 /*!
336     Returns 'true' if sketching is enabled in  this viewport. [ public ]
337 */
338 bool OCCViewer_ViewPort::isSketchingEnabled() const
339 {
340     return myEnableSketching;
341 }
342
343 /*!
344     Enables / disables sketching  [ public ]
345 */
346 void OCCViewer_ViewPort::setSketchingEnabled( bool enable )
347 {
348         myEnableSketching = enable;
349 }
350
351 /*!
352     Returns 'true' if transformations ( rotation, zoom etc. )
353     are enabled in this viewport. [ public ]
354 */
355 bool OCCViewer_ViewPort::isTransformEnabled() const
356 {
357     return myEnableTransform;
358 }
359
360 /*!
361     Enables / disables transformations. [ public ]
362 */
363 void OCCViewer_ViewPort::setTransformEnabled( bool enable )
364 {
365         myEnableTransform = enable;
366 }
367
368 /*!
369     Emits 'mouseEvent' signal. [ virtual protected ]
370 */
371 void OCCViewer_ViewPort::mousePressEvent( QMouseEvent *e )
372 {
373     emit vpMouseEvent( e );
374 }
375
376 /*!
377     Emits 'mouseEvent' signal. [ virtual protected ]
378 */
379 void OCCViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
380 {
381     emit vpMouseEvent( e );
382 }
383
384 /*!
385     Emits 'mouseEvent' signal. [ virtual protected ]
386 */
387 void OCCViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
388 {
389     emit vpMouseEvent( e );
390 }
391
392 /*!
393     Emits 'mouseEvent' signal. [ virtual protected ]
394 */
395 void OCCViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
396 {
397     emit vpMouseEvent( e );
398 }
399
400 /*!
401     Emits 'keyEvent' signal. [ virtual protected ]
402 */
403 void OCCViewer_ViewPort::keyPressEvent( QKeyEvent *e )
404 {
405     emit vpKeyEvent( e );
406 }
407
408 /*!
409     Emits 'keyEvent' signal. [ virtual protected ]
410 */
411 void OCCViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
412 {
413     emit vpKeyEvent( e );
414 }
415
416 /*!
417     Repaints the viewport. [ virtual protected ]
418 */
419 void OCCViewer_ViewPort::paintEvent( QPaintEvent* )
420 {
421         if ( myPaintersRedrawing )
422         {
423                 QPainter p( this );
424                 emit vpDrawExternal( &p );
425                 myPaintersRedrawing = false;
426         }
427 }
428
429 /*!
430     Forces to redraw the viewport by an external painter. [ public ]
431 */
432 void OCCViewer_ViewPort::redrawPainters()
433 {
434         myPaintersRedrawing = true;
435         repaint();
436 }
437
438 /*!
439     Updates this view. Does nothing by default. [ virtual public ]
440 */
441 void OCCViewer_ViewPort::onUpdate()
442 {
443 }
444
445 /*!
446     Creates the popup. [ virtual protected ]
447 */
448 /*void OCCViewer_ViewPort::onCreatePopup( QPopupMenu* popup )
449 {
450         if ( popup )
451         {
452                 QtxAction* a = new QtxAction( "", tr( "MEN_VP_CHANGEBGR" ), 0, this );
453         a->setStatusTip( tr( "PRP_VP_CHANGEBGR" ) );
454                 connect( a, SIGNAL( activated() ), SLOT( onChangeBgColor()));
455                 myPopupActions.append( a );
456                 a->addTo( popup );
457         }
458 }*/
459
460 /*!
461     Destroys the popup. [ virtual protected ]
462 */
463 /*void OCCViewer_ViewPort::onDestroyPopup( QPopupMenu* popup )
464 {
465         if ( popup )
466         {
467                 for ( QtxAction* a = myPopupActions.first(); a; a = myPopupActions.next() )
468                         a->removeFrom( popup );
469                 myPopupActions.clear();
470         }
471 }*/
472
473 /*!
474     Sets the background color with color selection dialog. [ virtual protected slot ]
475 */
476 void OCCViewer_ViewPort::onChangeBgColor()
477 {
478     QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
479     if ( selColor.isValid() )
480         setBackgroundColor( selColor );
481 }