7fef1f9427ab21b5bef6f9e93140f08657496450
[occt.git] / src / IVtkDraw / IVtkDraw_Interactor.cxx
1 // Created on: 2012-05-28 
2 // 
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS 
4 // 
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifdef _WIN32
17 #define _WIN32_WINNT 0x0400  // for trackmouseevent support  requires Win95 with IE 3.0 or greater.
18 #include <windows.h>
19 #include <vtkWin32RenderWindowInteractor.h>
20 #include <vtkWin32OpenGLRenderWindow.h>
21 #endif
22
23 #include <IVtkTools_ShapePicker.hxx>
24 #include <IVtkTools_SubPolyDataFilter.hxx>
25 #include <IVtkTools_DisplayModeFilter.hxx>
26 #include <IVtkTools_ShapeObject.hxx>
27 #include <IVtkTools_ShapeDataSource.hxx>
28 #include <IVtkDraw_Interactor.hxx>
29
30 #include <Message.hxx>
31 #include <Message_Messenger.hxx>
32
33 #include <vtkActor.h>
34 #include <vtkActorCollection.h>
35 #include <vtkCommand.h>
36 #include <vtkObjectFactory.h>
37 #include <vtkSmartPointer.h>
38
39 #ifndef _WIN32
40 #include <X11/X.h>
41 #include <X11/Shell.h>
42 #include <X11/Xlib.h>
43 #include <GL/glx.h>
44 #include <vtkXRenderWindowInteractor.h>
45 #include <vtkXOpenGLRenderWindow.h>
46 #include <X11/Xutil.h>
47 #include <tk.h>
48 #endif
49
50 //===========================================================
51 // Function : ClearHighlightAndSelection
52 // Purpose  :
53 //===========================================================
54 static void ClearHighlightAndSelection (const Handle(ShapePipelineMap)& theMap,
55                                          const Standard_Boolean doHighlighting,
56                                          const Standard_Boolean doSelection)
57 {
58   if (!doHighlighting && !doSelection)
59   {
60     return;
61   }
62
63   for (ShapePipelineMap::Iterator anIt (*theMap); anIt.More(); anIt.Next())
64   {
65     const Handle(IVtkDraw_HighlightAndSelectionPipeline)& aPL = anIt.Value();
66
67     if (doHighlighting)
68     {
69       aPL->ClearHighlightFilters();
70     }
71
72     if (doSelection)
73     {
74       aPL->ClearSelectionFilters();
75     }
76   }
77 }
78
79 vtkStandardNewMacro(IVtkDraw_Interactor)
80
81 //===========================================================
82 // Function : Constructor
83 // Purpose  :
84 //===========================================================
85 IVtkDraw_Interactor::IVtkDraw_Interactor()
86 :
87 #ifdef _WIN32
88   myWindowId (NULL),
89   myMouseInWindow (0)
90 #else
91   myIsLeftButtonPressed (Standard_False)
92 #endif
93 { }
94
95 //===========================================================
96 // Function : Destructor
97 // Purpose  :
98 //===========================================================
99 IVtkDraw_Interactor::~IVtkDraw_Interactor()
100 {
101 }
102
103 //===========================================================
104 // Function : SetShapePicker
105 // Purpose  :
106 //===========================================================
107 void IVtkDraw_Interactor::SetShapePicker (const PSelector& theSelector)
108 {
109   mySelector = theSelector;
110 }
111
112 //===========================================================
113 // Function : SetPipelines
114 // Purpose  :
115 //===========================================================
116 void IVtkDraw_Interactor::SetPipelines (const Handle(ShapePipelineMap)& thePipelines)
117 {
118   myPipelines = thePipelines;
119 }
120
121 //===========================================================
122 // Function : SetOCCWindow
123 // Purpose  :
124 //===========================================================
125 void IVtkDraw_Interactor::SetOCCWindow (const Handle(Aspect_Window)& theWindow)
126 {
127   myWindow = theWindow;
128 }
129
130 //===========================================================
131 // Function : GetOCCWindow
132 // Purpose  :
133 //===========================================================
134 const Handle(Aspect_Window)& IVtkDraw_Interactor::GetOCCWindow() const
135 {
136   return myWindow;
137 }
138
139 //===========================================================
140 // Function : IsEnabled
141 // Purpose  :
142 //===========================================================
143 Standard_Boolean IVtkDraw_Interactor::IsEnabled() const
144 {
145   return Enabled;
146 }
147
148 //===========================================================
149 // Function : Initialize
150 // Purpose  :
151 //===========================================================
152 void IVtkDraw_Interactor::Initialize()
153 {
154   // Make sure we have a RenderWindow and camera
155   if (!this->RenderWindow)
156   {
157     vtkErrorMacro(<<"No renderer defined!");
158     return;
159   }
160
161   if (this->Initialized)
162   {
163     return;
164   }
165
166   this->Initialized = 1;
167   
168   // Get the info we need from the RenderingWindow
169   Standard_Integer *aSize;
170 #ifdef _WIN32
171   vtkWin32OpenGLRenderWindow *aRenWin;
172   aRenWin = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow);
173   aRenWin->Start();
174   aSize = aRenWin->GetSize();
175   aRenWin->GetPosition();
176   this->myWindowId = aRenWin->GetWindowId();
177 #else
178   vtkXOpenGLRenderWindow *aRenWin;
179   aRenWin = static_cast<vtkXOpenGLRenderWindow *>(this->RenderWindow);
180   this->myDisplayId = aRenWin->GetDisplayId();
181   this->myWindowId = aRenWin->GetWindowId();
182   aSize = aRenWin->GetSize();
183   aRenWin->Start();
184 #endif
185
186   this->Enable();
187   this->Size[0] = aSize[0];
188   this->Size[1] = aSize[1];
189 }
190
191 //===========================================================
192 // Function : Enable
193 // Purpose  :
194 //===========================================================
195 void IVtkDraw_Interactor::Enable()
196 {
197   if (this->Enabled)
198   {
199     return;
200   }
201
202   // Add event handlers
203 #ifdef _WIN32
204   SetWindowLongPtr(this->myWindowId, GWLP_USERDATA, (LONG_PTR)this);
205   SetWindowLongPtr(this->myWindowId, GWLP_WNDPROC, (LONG_PTR)WndProc);
206 #else
207   #if TCL_MAJOR_VERSION  < 8
208     Tk_CreateFileHandler((void*)ConnectionNumber(this->myDisplayId),
209       TK_READABLE, ProcessEvents, (ClientData) this);
210   #else
211     Tk_CreateFileHandler(ConnectionNumber(this->myDisplayId),
212       TK_READABLE, ProcessEvents, (ClientData) this);
213   #endif
214 #endif
215
216   this->Enabled = 1;
217   this->Modified();
218 }
219
220 //===========================================================
221 // Function : MoveTo
222 // Purpose  :
223 //===========================================================
224 void IVtkDraw_Interactor::MoveTo (Standard_Integer theX, Standard_Integer theY)
225 {
226   // Processing highlighting
227   mySelector->Pick (theX, theY, 0.0);
228   vtkActorCollection* anActorCollection = mySelector->GetPickedActors();
229
230   if (anActorCollection)
231   {
232     // Highlight picked subshapes
233     ClearHighlightAndSelection (myPipelines, Standard_True, Standard_False);
234     anActorCollection->InitTraversal();
235     while (vtkActor* anActor = anActorCollection->GetNextActor())
236     {
237       IVtkTools_ShapeDataSource* aDataSource = IVtkTools_ShapeObject::GetShapeSource (anActor);
238       if (!aDataSource)
239       {
240         continue;
241       }
242
243       IVtkOCC_Shape::Handle anOccShape = aDataSource->GetShape();
244       if (anOccShape.IsNull())
245       {
246         continue;
247       }
248
249       IVtk_IdType aShapeID = anOccShape->GetId();
250       Handle(Message_Messenger) anOutput = Message::DefaultMessenger();
251       if (!myPipelines->IsBound(aShapeID))
252       {
253         anOutput << "Warning: there is no VTK pipeline registered for highlighted shape" << endl;
254         continue;
255       }
256
257       const Handle(IVtkDraw_HighlightAndSelectionPipeline)& aPL = myPipelines->Find (aShapeID);
258
259       // Add a subpolydata filter to the highlight pipeline for the shape data source.
260       IVtkTools_SubPolyDataFilter* aFilter = aPL->GetHighlightFilter();
261
262       // Set the selected sub-shapes ids to subpolydata filter.
263       IVtk_ShapeIdList aSubShapeIds = mySelector->GetPickedSubShapesIds(aShapeID);
264
265       // Get ids of cells for picked subshapes.
266       IVtk_ShapeIdList aSubIds;
267       IVtk_ShapeIdList::Iterator aMetaIds (aSubShapeIds);
268       for (; aMetaIds.More(); aMetaIds.Next())
269       {
270         IVtk_ShapeIdList aSubSubIds = anOccShape->GetSubIds (aMetaIds.Value());
271         aSubIds.Append (aSubSubIds);
272       }
273
274       aFilter->SetDoFiltering (!aSubIds.IsEmpty());
275       aFilter->SetData (aSubIds);
276       if (!aFilter->GetInput())
277       {
278         aFilter->SetInputConnection (aDataSource->GetOutputPort());
279       }
280       aFilter->Modified();
281     }
282   }
283   this->Render();
284 }
285
286 //===========================================================
287 // Function : OnSelection
288 // Purpose  :
289 //===========================================================
290 void IVtkDraw_Interactor::OnSelection()
291 {
292   // Processing selection
293   vtkActorCollection* anActorCollection = mySelector->GetPickedActors();
294
295   if (anActorCollection)
296   {
297     // Highlight picked subshapes.
298     ClearHighlightAndSelection (myPipelines, Standard_False, Standard_True);
299     anActorCollection->InitTraversal();
300     while (vtkActor* anActor = anActorCollection->GetNextActor())
301     {
302       IVtkTools_ShapeDataSource* aDataSource = IVtkTools_ShapeObject::GetShapeSource (anActor);
303       if (!aDataSource)
304       {
305         continue;
306       }
307
308       IVtkOCC_Shape::Handle anOccShape = aDataSource->GetShape();
309       if (anOccShape.IsNull())
310       {
311         continue;
312       }
313
314       IVtk_IdType aShapeID = anOccShape->GetId();
315       Handle(Message_Messenger) anOutput = Message::DefaultMessenger();
316       if (!myPipelines->IsBound (aShapeID))
317       {
318         anOutput << "Warning: there is no VTK pipeline registered for picked shape" << endl;
319         continue;
320       }
321
322       const Handle(IVtkDraw_HighlightAndSelectionPipeline)& aPL = myPipelines->Find (aShapeID);
323
324       // Add a subpolydata filter to the selection pipeline for the shape data source.
325       IVtkTools_SubPolyDataFilter* aFilter = aPL->GetSelectionFilter();
326
327       // Set the selected sub-shapes ids to subpolydata filter.
328       IVtk_ShapeIdList aSubShapeIds = mySelector->GetPickedSubShapesIds(aShapeID);
329
330       // Get ids of cells for picked subshapes.
331       IVtk_ShapeIdList aSubIds;
332       IVtk_ShapeIdList::Iterator aMetaIds (aSubShapeIds);
333       for (; aMetaIds.More(); aMetaIds.Next())
334       {
335         IVtk_ShapeIdList aSubSubIds = anOccShape->GetSubIds (aMetaIds.Value());
336         aSubIds.Append (aSubSubIds);
337       }
338
339       aFilter->SetDoFiltering (!aSubIds.IsEmpty());
340       aFilter->SetData (aSubIds);
341       if (!aFilter->GetInput())
342       {
343         aFilter->SetInputConnection (aDataSource->GetOutputPort());
344       }
345       aFilter->Modified();
346     }
347   }
348   this->Render();
349 }
350
351 #ifdef _WIN32
352
353 //===========================================================
354 // Function : OnMouseMove
355 // Purpose  :
356 //===========================================================
357 void IVtkDraw_Interactor::OnMouseMove (HWND theHWnd, UINT theNFlags,
358                                        Standard_Integer theX,
359                                        Standard_Integer theY)
360 {
361   if (!this->Enabled)
362   {
363     return;
364   }
365
366   this->SetEventInformationFlipY (theX,
367                                   theY,
368                                   theNFlags & MK_CONTROL,
369                                   theNFlags & MK_SHIFT);
370   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
371   if (!this->myMouseInWindow && 
372       (theX >= 0 && theX < this->Size[0] && theY >= 0 && theY < this->Size[1]))
373   {
374     this->InvokeEvent (vtkCommand::EnterEvent, NULL);
375     this->myMouseInWindow = 1;
376     // request WM_MOUSELEAVE generation
377     TRACKMOUSEEVENT aTme;
378     aTme.cbSize = sizeof (TRACKMOUSEEVENT);
379     aTme.dwFlags = TME_LEAVE;
380     aTme.hwndTrack = theHWnd;
381     TrackMouseEvent (&aTme);
382   }
383
384   if (!(theNFlags & MK_LBUTTON))
385     this->MoveTo (theX, this->Size[1] - theY - 1);
386
387   this->InvokeEvent (vtkCommand::MouseMoveEvent, NULL);
388 }
389
390 //===========================================================
391 // Function : OnMouseWheelForward
392 // Purpose  :
393 //===========================================================
394 void IVtkDraw_Interactor::OnMouseWheelForward (HWND, UINT theNFlags,
395                                                Standard_Integer theX,
396                                                Standard_Integer theY)
397 {
398   if (!this->Enabled)
399   {
400     return;
401   }
402
403   this->SetEventInformationFlipY (theX,
404                                   theY,
405                                   theNFlags & MK_CONTROL,
406                                   theNFlags & MK_SHIFT);
407
408   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
409   this->InvokeEvent (vtkCommand::MouseWheelForwardEvent, NULL);
410 }
411
412 //===========================================================
413 // Function : OnMouseWheelBackward
414 // Purpose  :
415 //===========================================================
416 void IVtkDraw_Interactor::OnMouseWheelBackward (HWND, UINT theNFlags,
417                                                 Standard_Integer theX,
418                                                 Standard_Integer theY)
419 {
420   if (!this->Enabled)
421   {
422     return;
423   }
424
425   this->SetEventInformationFlipY (theX,
426                                   theY,
427                                   theNFlags & MK_CONTROL,
428                                   theNFlags & MK_SHIFT);
429
430   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
431   this->InvokeEvent (vtkCommand::MouseWheelBackwardEvent, NULL);
432 }
433
434 //===========================================================
435 // Function : OnLButtonDown
436 // Purpose  :
437 //===========================================================
438 void IVtkDraw_Interactor::OnLButtonDown (HWND theHWnd, UINT theNFlags,
439                                          Standard_Integer theX,
440                                          Standard_Integer theY,
441                                          Standard_Integer theRepeat)
442 {
443   if (!this->Enabled)
444   {
445     return;
446   }
447   SetFocus (theHWnd);
448   SetCapture (theHWnd);
449   this->SetEventInformationFlipY (theX,
450                                   theY,
451                                   theNFlags & MK_CONTROL,
452                                   theNFlags & MK_SHIFT,
453                                   0, theRepeat);
454   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
455
456   OnSelection ();
457
458   this->InvokeEvent (vtkCommand::LeftButtonPressEvent, NULL);
459 }
460
461 //===========================================================
462 // Function : OnLButtonUp
463 // Purpose  :
464 //===========================================================
465 void IVtkDraw_Interactor::OnLButtonUp (HWND, UINT theNFlags,
466                                        Standard_Integer theX,
467                                        Standard_Integer theY)
468 {
469   if (!this->Enabled)
470   {
471     return;
472   }
473
474   this->SetEventInformationFlipY (theX,
475                                   theY,
476                                   theNFlags & MK_CONTROL,
477                                   theNFlags & MK_SHIFT);
478
479   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
480   this->InvokeEvent (vtkCommand::LeftButtonReleaseEvent, NULL);
481   ReleaseCapture();
482 }
483
484 //===========================================================
485 // Function : OnMButtonDown
486 // Purpose  :
487 //===========================================================
488 void IVtkDraw_Interactor::OnMButtonDown (HWND theHWnd, UINT theNFlags,
489                                          Standard_Integer theX,
490                                          Standard_Integer theY,
491                                          Standard_Integer theRepeat)
492 {
493   if (!this->Enabled)
494   {
495     return;
496   }
497
498   SetFocus (theHWnd);
499   SetCapture (theHWnd);
500   this->SetEventInformationFlipY (theX,
501                                   theY,
502                                   theNFlags & MK_CONTROL,
503                                   theNFlags & MK_SHIFT,
504                                   0, theRepeat);
505   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
506   this->InvokeEvent (vtkCommand::MiddleButtonPressEvent, NULL);
507 }
508
509 //===========================================================
510 // Function : OnMButtonUp
511 // Purpose  :
512 //===========================================================
513 void IVtkDraw_Interactor::OnMButtonUp (HWND, UINT theNFlags,
514                                        Standard_Integer theX,
515                                        Standard_Integer theY)
516 {
517   if (!this->Enabled)
518   {
519     return;
520   }
521   this->SetEventInformationFlipY (theX,
522                                   theY,
523                                   theNFlags & MK_CONTROL,
524                                   theNFlags & MK_SHIFT);
525
526   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
527   this->InvokeEvent (vtkCommand::MiddleButtonReleaseEvent, NULL);
528   ReleaseCapture();
529 }
530
531 //===========================================================
532 // Function : OnRButtonDown
533 // Purpose  :
534 //===========================================================
535 void IVtkDraw_Interactor::OnRButtonDown (HWND theHWnd, UINT theNFlags,
536                                          Standard_Integer theX,
537                                          Standard_Integer theY,
538                                          Standard_Integer theRepeat)
539 {
540   if (!this->Enabled)
541   {
542     return;
543   }
544
545   SetFocus(theHWnd);
546   SetCapture(theHWnd);
547   this->SetEventInformationFlipY (theX,
548                                   theY,
549                                   theNFlags & MK_CONTROL,
550                                   theNFlags & MK_SHIFT,
551                                   0, theRepeat);
552
553   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
554   this->InvokeEvent (vtkCommand::RightButtonPressEvent, NULL);
555 }
556
557 //===========================================================
558 // Function : OnRButtonUp
559 // Purpose  :
560 //===========================================================
561 void IVtkDraw_Interactor::OnRButtonUp (HWND, UINT theNFlags,
562                                        Standard_Integer theX,
563                                        Standard_Integer theY)
564 {
565   if (!this->Enabled)
566   {
567     return;
568   }
569   this->SetEventInformationFlipY (theX,
570                                   theY,
571                                   theNFlags & MK_CONTROL,
572                                   theNFlags & MK_SHIFT);
573
574   this->SetAltKey (GetKeyState(VK_MENU) & (~1));
575   this->InvokeEvent (vtkCommand::RightButtonReleaseEvent, NULL);
576   ReleaseCapture();
577 }
578
579 //===========================================================
580 // Function : OnSize
581 // Purpose  :
582 //===========================================================
583 void IVtkDraw_Interactor::OnSize (HWND, UINT,
584                                   Standard_Integer theX,
585                                   Standard_Integer theY)
586 {
587   this->UpdateSize (theX, theY);
588   if (this->Enabled)
589   {
590     this->InvokeEvent (vtkCommand::ConfigureEvent, NULL);
591   }
592 }
593
594 //===========================================================
595 // Function : OnTimer
596 // Purpose  :
597 //===========================================================
598 void IVtkDraw_Interactor::OnTimer (HWND, UINT theTimerId)
599 {
600   if (!this->Enabled)
601   {
602     return;
603   }
604
605   Standard_Integer aTid = static_cast<Standard_Integer>(theTimerId);
606   this->InvokeEvent (vtkCommand::TimerEvent, (void*)&aTid);
607
608   // Here we deal with one-shot versus repeating timers
609   if (this->IsOneShotTimer(aTid))
610   {
611     KillTimer (this->myWindowId, aTid); //'cause windows timers are always repeating
612   }
613 }
614
615 //===========================================================
616 // Function : WndProc
617 // Purpose  :
618 //===========================================================
619 LRESULT CALLBACK WndProc (HWND theHWnd,UINT theUMsg,
620                           WPARAM theWParam,
621                           LPARAM theLParam)
622 {
623   LRESULT aRes = 0;
624   IVtkDraw_Interactor *anInteractor = 0;
625
626   anInteractor = (IVtkDraw_Interactor *)GetWindowLongPtr (theHWnd, GWLP_USERDATA);
627
628   if (anInteractor && anInteractor->GetReferenceCount() > 0)
629   {
630     anInteractor->Register (anInteractor);
631     aRes = ViewerWindowProc (theHWnd, theUMsg, theWParam, theLParam, anInteractor);
632     anInteractor->UnRegister (anInteractor);
633   }
634
635   return aRes;
636 }
637
638 //===========================================================
639 // Function : ViewerWindowProc
640 // Purpose  :
641 //===========================================================
642 LRESULT CALLBACK ViewerWindowProc (HWND theHWnd,
643                                    UINT theMsg,
644                                    WPARAM theWParam,
645                                    LPARAM theLParam,
646                                    IVtkDraw_Interactor *theInteractor)
647 {
648   switch (theMsg)
649   {
650   case WM_CLOSE:
651     theInteractor->GetOCCWindow ()->Unmap ();
652     return 0;
653   case WM_PAINT:
654     theInteractor->Render();
655     break;
656   case WM_SIZE:
657     theInteractor->OnSize (theHWnd, theWParam, LOWORD(theLParam), HIWORD(theLParam));
658     break;
659   case WM_LBUTTONDBLCLK:
660     theInteractor->OnLButtonDown (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y, 1);
661     break;
662   case WM_LBUTTONDOWN:
663     theInteractor->OnLButtonDown (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y, 0);
664     break;
665   case WM_LBUTTONUP:
666     theInteractor->OnLButtonUp (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y);
667     break;
668   case WM_MBUTTONDBLCLK:
669     theInteractor->OnMButtonDown (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y, 1);
670     break;
671   case WM_MBUTTONDOWN:
672     theInteractor->OnMButtonDown (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y, 0);
673     break;
674   case WM_MBUTTONUP:
675     theInteractor->OnMButtonUp (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y);
676     break;
677   case WM_RBUTTONDBLCLK:
678     theInteractor->OnRButtonDown (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y, 1);
679     break;
680   case WM_RBUTTONDOWN:
681     theInteractor->OnRButtonDown (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y, 0);
682     break;
683   case WM_RBUTTONUP:
684     theInteractor->OnRButtonUp (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y);
685     break;
686   case WM_MOUSELEAVE:
687     {
688       theInteractor->InvokeEvent (vtkCommand::LeaveEvent, NULL);
689       theInteractor->myMouseInWindow = 0;
690     }
691     break;
692   case WM_MOUSEMOVE:
693     theInteractor->OnMouseMove (theHWnd, theWParam, MAKEPOINTS(theLParam).x, MAKEPOINTS(theLParam).y);
694     break;
695   case WM_MOUSEWHEEL:
696     {
697       POINT pt;
698       pt.x = MAKEPOINTS(theLParam).x;
699       pt.y = MAKEPOINTS(theLParam).y;
700       ::ScreenToClient(theHWnd, &pt);
701       if( GET_WHEEL_DELTA_WPARAM(theWParam) > 0)
702       {
703         theInteractor->OnMouseWheelForward (theHWnd, theWParam, pt.x, pt.y);
704       }
705       else
706       {
707         theInteractor->OnMouseWheelBackward (theHWnd, theWParam, pt.x, pt.y);
708       }
709     }
710     break;
711   case WM_TIMER:
712     theInteractor->OnTimer (theHWnd, theWParam);
713     break;
714   }
715   return DefWindowProc(theHWnd, theMsg, theWParam, theLParam);
716 }
717
718 #else
719
720 //===========================================================
721 // Function : GetDisplayId
722 // Purpose  :
723 //===========================================================
724 Display* IVtkDraw_Interactor::GetDisplayId() const
725 {
726   return myDisplayId;
727 }
728
729 //===========================================================
730 // Function : GetMousePosition
731 // Purpose  :
732 //===========================================================
733 void IVtkDraw_Interactor::GetMousePosition (Standard_Integer *theX,
734                                             Standard_Integer *theY)
735 {
736   Window aRoot, aChild;
737   Standard_Integer aRoot_x, aRoot_y;
738   unsigned int aKeys;
739
740   XQueryPointer (this->myDisplayId, this->myWindowId,
741                  &aRoot, &aChild, &aRoot_x, &aRoot_y, theX, theY, &aKeys);
742
743 }
744
745 //===========================================================
746 // Function : ViewerMainLoop
747 // Purpose  :
748 //===========================================================
749 Standard_Integer IVtkDraw_Interactor::ViewerMainLoop (Standard_Integer theArgNum, const char** /*theArgs*/)
750 {
751   Standard_Integer aXp, aYp;
752   Standard_Boolean aPick = theArgNum > 0;
753
754   static XEvent anEvent;
755   XNextEvent (myDisplayId, &anEvent);
756
757   switch (anEvent.type)
758   {
759   case Expose:
760     {
761       if (!this->Enabled)
762       {
763         return aPick;
764       }
765       XEvent aResult;
766       while (XCheckTypedWindowEvent (this->myDisplayId,
767                                      this->myWindowId,
768                                      Expose,
769                                      &aResult))
770       {
771         // just getting the expose configure event
772         anEvent = aResult;
773       }
774
775       this->SetEventSize (anEvent.xexpose.width, anEvent.xexpose.height);
776
777
778       aXp = anEvent.xexpose.x;
779       aYp = this->Size[1] - anEvent.xexpose.y - 1;
780       this->SetEventPosition (aXp, aYp);
781       
782       // only render if we are currently accepting events
783       if (this->Enabled)
784       {
785         this->InvokeEvent(vtkCommand::ExposeEvent,NULL);
786         this->Render();
787       }
788     }
789     break;
790
791   case MapNotify:
792     {
793       // only render if we are currently accepting events
794       if (this->Enabled && this->GetRenderWindow()->GetNeverRendered())
795       {
796         this->Render();
797       }
798     }
799     break;
800
801   case ConfigureNotify:
802     {
803       XEvent aResult;
804       while (XCheckTypedWindowEvent(this->myDisplayId,
805                                     this->myWindowId,
806                                     ConfigureNotify,
807                                     &aResult))
808       {
809         // just getting the last configure event
810         anEvent = aResult;
811       }
812       Standard_Integer aWidth = anEvent.xconfigure.width;
813       Standard_Integer aHeight = anEvent.xconfigure.height;
814       if (aWidth != this->Size[0] || aHeight != this->Size[1])
815       {
816         Standard_Boolean toResizeSmaller = aWidth <= this->Size[0] && aHeight <= this->Size[1];
817         this->UpdateSize (aWidth, aHeight);
818         aXp = anEvent.xbutton.x;
819         aYp = anEvent.xbutton.y;
820
821         SetEventPosition (aXp, this->Size[1] - aYp - 1);
822
823         // only render if we are currently accepting events
824         if (Enabled)
825         {
826           this->InvokeEvent(vtkCommand::ConfigureEvent,NULL);
827           if (toResizeSmaller)
828           {
829             // Don't call Render when the window is resized to be larger:
830             //
831             // - if the window is resized to be larger, an Expose event will
832             // be trigged by the X server which will trigger a call to
833             // Render().
834             // - if the window is resized to be smaller, no Expose event will
835             // be trigged by the X server, as no new area become visible.
836             // only in this case, we need to explicitly call Render()
837             // in ConfigureNotify.
838             this->Render();
839           }
840         }
841       }
842     }
843     break;
844
845   case ButtonPress:
846     {
847       if (!this->Enabled)
848       {
849         return aPick;
850       }
851       
852       Standard_Integer aCtrl = anEvent.xbutton.state & ControlMask ? 1 : 0;
853       Standard_Integer aShift = anEvent.xbutton.state & ShiftMask ? 1 : 0;
854       Standard_Integer anAlt = anEvent.xbutton.state & Mod1Mask ? 1 : 0;
855       aXp = anEvent.xbutton.x;
856       aYp = anEvent.xbutton.y;
857
858       // check for double click
859       static Standard_Integer aMousePressTime = 0;
860       Standard_Integer aRepeat = 0;
861       // 400 ms threshold by default is probably good to start
862       Standard_Integer anEventTime = static_cast<int>(anEvent.xbutton.time);
863       if ((anEventTime - aMousePressTime) < 400)
864       {
865         aMousePressTime -= 2000;  // no double click next time
866         aRepeat = 1;
867       }
868       else
869       {
870         aMousePressTime = anEventTime;
871       }
872
873       this->SetEventInformationFlipY (aXp, aYp, aCtrl, aShift, 0, aRepeat);
874       this->SetAltKey (anAlt);
875
876       switch (anEvent.xbutton.button)
877       {
878         case Button1:
879           this->OnSelection ();
880           this->myIsLeftButtonPressed = 1;
881           this->InvokeEvent (vtkCommand::LeftButtonPressEvent,NULL);
882           break;
883         case Button2:
884           this->InvokeEvent (vtkCommand::MiddleButtonPressEvent,NULL);
885           break;
886         case Button3:
887           this->InvokeEvent (vtkCommand::RightButtonPressEvent,NULL);
888           break;
889         case Button4:
890           this->InvokeEvent (vtkCommand::MouseWheelForwardEvent,NULL);
891           break;
892         case Button5:
893           this->InvokeEvent (vtkCommand::MouseWheelBackwardEvent,NULL);
894           break;
895       }
896       this->Render();
897     }
898     break;
899
900   case ButtonRelease:
901     {
902       if (!this->Enabled)
903       {
904         return aPick;
905       }
906       Standard_Integer aCtrl = anEvent.xbutton.state & ControlMask ? 1 : 0;
907       Standard_Integer aShift = anEvent.xbutton.state & ShiftMask ? 1 : 0;
908       Standard_Integer anAlt = anEvent.xbutton.state & Mod1Mask ? 1 : 0;
909       aXp = anEvent.xbutton.x;
910       aYp = anEvent.xbutton.y;
911       
912       this->SetEventInformationFlipY (aXp, aYp, aCtrl, aShift);
913       this->SetAltKey (anAlt);
914       switch (anEvent.xbutton.button)
915       {
916         case Button1:
917           this->InvokeEvent (vtkCommand::LeftButtonReleaseEvent,NULL);
918           this->myIsLeftButtonPressed = False;
919           break;
920         case Button2:
921           this->InvokeEvent (vtkCommand::MiddleButtonReleaseEvent,NULL);
922           break;
923         case Button3:
924           this->InvokeEvent (vtkCommand::RightButtonReleaseEvent,NULL);
925           break;
926       }
927       this->Render();
928     }
929     break;
930
931   case EnterNotify:
932     {
933       if (this->Enabled)
934       {
935         XEnterWindowEvent *anEnterEvent = reinterpret_cast<XEnterWindowEvent *>(&anEvent);
936         this->SetEventInformationFlipY (anEnterEvent->x,
937                                         anEnterEvent->y,
938                                         (anEnterEvent->state & ControlMask) != 0,
939                                         (anEnterEvent->state & ShiftMask) != 0);
940                                         
941         this->SetAltKey (anEvent.xbutton.state & Mod1Mask ? 1 : 0);
942         this->InvokeEvent (vtkCommand::EnterEvent, NULL);
943       }
944       this->Render();
945     }
946     break;
947
948   case LeaveNotify:
949     {
950       if (this->Enabled)
951       {
952         XLeaveWindowEvent *aLeaveEvent = reinterpret_cast<XLeaveWindowEvent *>(&anEvent);
953         this->SetEventInformationFlipY (aLeaveEvent->x,
954                                         aLeaveEvent->y,
955                                         (aLeaveEvent->state & ControlMask) != 0,
956                                         (aLeaveEvent->state & ShiftMask) != 0);
957                                         
958         this->SetAltKey (anEvent.xbutton.state & Mod1Mask ? 1 : 0);
959         this->InvokeEvent(vtkCommand::LeaveEvent, NULL);
960       }
961       this->Render();
962     }
963     break;
964
965   case MotionNotify:
966     {
967       if (!this->Enabled)
968       {
969         return aPick;
970       }
971       
972       Standard_Integer aCtrl = anEvent.xbutton.state & ControlMask ? 1 : 0;
973       Standard_Integer aShift = anEvent.xbutton.state & ShiftMask ? 1 : 0;
974       Standard_Integer anAlt = anEvent.xbutton.state & Mod1Mask ? 1 : 0;
975
976       // Note that even though the (x,y) location of the pointer is event structure,
977       // we must call XQueryPointer for the hints (motion event compression) to
978       // work properly.
979       this->GetMousePosition (&aXp, &aYp);
980       this->SetEventInformationFlipY (aXp, aYp, aCtrl, aShift);
981       this->SetAltKey (anAlt);
982       if (!myIsLeftButtonPressed)
983         MoveTo (aXp, this->Size[1]- aYp - 1); 
984       this->InvokeEvent (vtkCommand::MouseMoveEvent, NULL);
985     }
986     break;
987   }
988
989   return aPick;
990 }
991
992 //===========================================================
993 // Function : ProcessEvents
994 // Purpose  :
995 //===========================================================
996 void IVtkDraw_Interactor::ProcessEvents (ClientData theData, int)
997 {
998   IVtkDraw_Interactor *anInteractor = (IVtkDraw_Interactor *)theData;
999   // test for X Event
1000   while (XPending(anInteractor->GetDisplayId()))
1001   {
1002     anInteractor->ViewerMainLoop (0, NULL);
1003   }
1004 }
1005
1006 #endif