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