0027772: Foundation Classes - define Standard_Boolean using C++ type "bool" instead...
[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
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//===========================================================
54static 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
68858c7d 79vtkStandardNewMacro(IVtkDraw_Interactor)
52f99d93 80
81//===========================================================
82// Function : Constructor
83// Purpose :
84//===========================================================
85IVtkDraw_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//===========================================================
99IVtkDraw_Interactor::~IVtkDraw_Interactor()
100{
101}
102
103//===========================================================
52f99d93 104// Function : SetShapePicker
105// Purpose :
106//===========================================================
107void IVtkDraw_Interactor::SetShapePicker (const PSelector& theSelector)
108{
109 mySelector = theSelector;
110}
111
112//===========================================================
113// Function : SetPipelines
114// Purpose :
115//===========================================================
116void IVtkDraw_Interactor::SetPipelines (const Handle(ShapePipelineMap)& thePipelines)
117{
118 myPipelines = thePipelines;
119}
120
121//===========================================================
122// Function : SetOCCWindow
123// Purpose :
124//===========================================================
125void IVtkDraw_Interactor::SetOCCWindow (const Handle(Aspect_Window)& theWindow)
126{
127 myWindow = theWindow;
128}
129
130//===========================================================
131// Function : GetOCCWindow
132// Purpose :
133//===========================================================
134const Handle(Aspect_Window)& IVtkDraw_Interactor::GetOCCWindow() const
135{
136 return myWindow;
137}
138
139//===========================================================
140// Function : IsEnabled
141// Purpose :
142//===========================================================
143Standard_Boolean IVtkDraw_Interactor::IsEnabled() const
144{
dde68833 145 return (Enabled != 0);
52f99d93 146}
147
148//===========================================================
149// Function : Initialize
150// Purpose :
151//===========================================================
152void 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//===========================================================
195void 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//===========================================================
224void 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//===========================================================
290void 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//===========================================================
357void 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//===========================================================
394void 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//===========================================================
416void 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//===========================================================
438void 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//===========================================================
465void 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//===========================================================
488void 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//===========================================================
513void 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//===========================================================
535void 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//===========================================================
561void 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//===========================================================
583void 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//===========================================================
598void 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//===========================================================
619LRESULT 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//===========================================================
642LRESULT 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//===========================================================
724Display* IVtkDraw_Interactor::GetDisplayId() const
725{
726 return myDisplayId;
727}
728
729//===========================================================
730// Function : GetMousePosition
731// Purpose :
732//===========================================================
733void 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//===========================================================
749Standard_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//===========================================================
996void 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