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