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 | //=========================================================== |
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 | |
1bd04b5a |
190 | #ifdef _WIN32 |
191 | LRESULT CALLBACK WndProc(HWND theHWnd, UINT theUMsg, WPARAM theWParam, LPARAM theLParam); |
192 | #endif |
193 | |
52f99d93 |
194 | //=========================================================== |
195 | // Function : Enable |
196 | // Purpose : |
197 | //=========================================================== |
198 | void 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 | //=========================================================== |
227 | void 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 | { |
04232180 |
256 | anOutput << "Warning: there is no VTK pipeline registered for highlighted shape" << Message_EndLine; |
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 | //=========================================================== |
293 | void 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 | { |
04232180 |
321 | anOutput << "Warning: there is no VTK pipeline registered for picked shape" << Message_EndLine; |
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 | //=========================================================== |
360 | void 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 | //=========================================================== |
397 | void 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 | //=========================================================== |
419 | void 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 | //=========================================================== |
441 | void 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 | //=========================================================== |
468 | void 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 | //=========================================================== |
491 | void 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 | //=========================================================== |
516 | void 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 | //=========================================================== |
538 | void 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 | //=========================================================== |
564 | void 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 | //=========================================================== |
586 | void 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 | //=========================================================== |
601 | void 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 | //=========================================================== |
622 | LRESULT 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 | //=========================================================== |
645 | LRESULT 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 | //=========================================================== |
727 | Display* IVtkDraw_Interactor::GetDisplayId() const |
728 | { |
729 | return myDisplayId; |
730 | } |
731 | |
732 | //=========================================================== |
733 | // Function : GetMousePosition |
734 | // Purpose : |
735 | //=========================================================== |
736 | void 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 | //=========================================================== |
752 | Standard_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 | //=========================================================== |
999 | void 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 |