1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkWin32RenderWindowInteractor.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include <stdio.h>
16 #include <cstdlib>
17 #include <string.h>
18 #include <math.h>
19 
20 
21 #ifndef _WIN32_WINNT
22 #define _WIN32_WINNT 0x0501  // for trackmouseevent support, 0x0501 means target Windows XP or later
23 #endif
24 
25 #include "vtkWin32OpenGLRenderWindow.h"
26 
27 // Mouse wheel support
28 // In an ideal world we would just have to include <zmouse.h>, but it is not
29 // always available with all compilers/headers
30 #ifndef WM_MOUSEWHEEL
31 #  define WM_MOUSEWHEEL                   0x020A
32 #endif  //WM_MOUSEWHEEL
33 #ifndef GET_WHEEL_DELTA_WPARAM
34 #  define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
35 #endif  //GET_WHEEL_DELTA_WPARAM
36 
37 // MSVC does the right thing without the forward declaration when it
38 // sees it in the friend decl in vtkWin32RenderWindowInteractor, but
39 // GCC needs to see the declaration beforehand. It has to do with the
40 // CALLBACK attribute.
41 VTKRENDERINGOPENGL_EXPORT LRESULT CALLBACK vtkHandleMessage(HWND,UINT,WPARAM,LPARAM);
42 VTKRENDERINGOPENGL_EXPORT LRESULT CALLBACK vtkHandleMessage2(HWND,UINT,WPARAM,LPARAM,class vtkWin32RenderWindowInteractor*);
43 
44 #include "vtkWin32RenderWindowInteractor.h"
45 #include "vtkActor.h"
46 #include "vtkOpenGL.h"
47 #include "vtkObjectFactory.h"
48 #include "vtkCommand.h"
49 
50 #ifdef VTK_USE_TDX
51 #include "vtkTDxWinDevice.h"
52 #endif
53 
54 vtkStandardNewMacro(vtkWin32RenderWindowInteractor);
55 
56 void (*vtkWin32RenderWindowInteractor::ClassExitMethod)(void *) = (void (*)(void *))NULL;
57 void *vtkWin32RenderWindowInteractor::ClassExitMethodArg = (void *)NULL;
58 void (*vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)(void *) = (void (*)(void *))NULL;
59 
60 //----------------------------------------------------------------------------
61 // Construct object so that light follows camera motion.
vtkWin32RenderWindowInteractor()62 vtkWin32RenderWindowInteractor::vtkWin32RenderWindowInteractor()
63 {
64   this->WindowId           = 0;
65   this->InstallMessageProc = 1;
66   this->MouseInWindow = 0;
67   this->StartedMessageLoop = 0;
68 
69 #ifdef VTK_USE_TDX
70   this->Device=vtkTDxWinDevice::New();
71 #endif
72 }
73 
74 //----------------------------------------------------------------------------
~vtkWin32RenderWindowInteractor()75 vtkWin32RenderWindowInteractor::~vtkWin32RenderWindowInteractor()
76 {
77   vtkWin32OpenGLRenderWindow *tmp;
78 
79   // we need to release any hold we have on a windows event loop
80   if (this->WindowId && this->Enabled && this->InstallMessageProc)
81     {
82     vtkWin32OpenGLRenderWindow *ren;
83     ren = static_cast<vtkWin32OpenGLRenderWindow *>(this->RenderWindow);
84     tmp = (vtkWin32OpenGLRenderWindow *)(vtkGetWindowLong(this->WindowId,sizeof(vtkLONG)));
85     // watch for odd conditions
86     if ((tmp != ren) && (ren != NULL))
87       {
88       // OK someone else has a hold on our event handler
89       // so lets have them handle this stuff
90       // well send a USER message to the other
91       // event handler so that it can properly
92       // call this event handler if required
93       CallWindowProc(this->OldProc,this->WindowId,WM_USER+14,28,(intptr_t)this->OldProc);
94       }
95     else
96       {
97       vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(intptr_t)this->OldProc);
98       }
99     this->Enabled = 0;
100     }
101 #ifdef VTK_USE_TDX
102   this->Device->Delete();
103 #endif
104 }
105 
106 //----------------------------------------------------------------------------
StartEventLoop()107 void  vtkWin32RenderWindowInteractor::StartEventLoop()
108 {
109   // No need to do anything if this is a 'mapped' interactor
110   if (!this->Enabled || !this->InstallMessageProc)
111     {
112     return;
113     }
114 
115   this->StartedMessageLoop = 1;
116 
117   MSG msg;
118   while (GetMessage(&msg, NULL, 0, 0))
119     {
120     TranslateMessage(&msg);
121     DispatchMessage(&msg);
122     }
123 }
124 
125 //----------------------------------------------------------------------------
126 // Begin processing keyboard strokes.
Initialize()127 void vtkWin32RenderWindowInteractor::Initialize()
128 {
129   vtkWin32OpenGLRenderWindow *ren;
130   int *size;
131 
132   // make sure we have a RenderWindow and camera
133   if ( ! this->RenderWindow)
134     {
135     vtkErrorMacro(<<"No renderer defined!");
136     return;
137     }
138   if (this->Initialized)
139     {
140     return;
141     }
142   this->Initialized = 1;
143   // get the info we need from the RenderingWindow
144   ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow);
145   ren->Start();
146   size    = ren->GetSize();
147   ren->GetPosition();
148   this->WindowId = ren->GetWindowId();
149   this->Enable();
150   this->Size[0] = size[0];
151   this->Size[1] = size[1];
152 }
153 
154 //----------------------------------------------------------------------------
Enable()155 void vtkWin32RenderWindowInteractor::Enable()
156 {
157   vtkWin32OpenGLRenderWindow *ren;
158   vtkWin32OpenGLRenderWindow *tmp;
159   if (this->Enabled)
160     {
161     return;
162     }
163   if (this->InstallMessageProc)
164     {
165     // add our callback
166     ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow);
167     this->OldProc = (WNDPROC)vtkGetWindowLong(this->WindowId,vtkGWL_WNDPROC);
168     tmp=(vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(this->WindowId,sizeof(vtkLONG));
169     // watch for odd conditions
170     if (tmp != ren)
171       {
172       // OK someone else has a hold on our event handler
173       // so lets have them handle this stuff
174       // well send a USER message to the other
175       // event handler so that it can properly
176       // call this event handler if required
177       CallWindowProc(this->OldProc,this->WindowId,WM_USER+12,24,(intptr_t)vtkHandleMessage);
178       }
179     else
180       {
181       vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(intptr_t)vtkHandleMessage);
182       }
183 
184 #ifdef VTK_USE_TDX
185     if(this->UseTDx)
186       {
187       this->Device->SetInteractor(this);
188       this->Device->Initialize();
189       this->Device->StartListening();
190       }
191 #endif
192 
193     // in case the size of the window has changed while we were away
194     int *size;
195     size = ren->GetSize();
196     this->Size[0] = size[0];
197     this->Size[1] = size[1];
198     }
199   this->Enabled = 1;
200   this->Modified();
201 }
202 
203 
204 //----------------------------------------------------------------------------
Disable()205 void vtkWin32RenderWindowInteractor::Disable()
206 {
207   vtkWin32OpenGLRenderWindow *tmp;
208   if (!this->Enabled)
209     {
210     return;
211     }
212 
213   if (this->InstallMessageProc && this->Enabled && this->WindowId)
214     {
215     // we need to release any hold we have on a windows event loop
216     vtkWin32OpenGLRenderWindow *ren;
217     ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow);
218     tmp = (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(this->WindowId,sizeof(vtkLONG));
219     // watch for odd conditions
220     if ((tmp != ren) && (ren != NULL))
221       {
222       // OK someone else has a hold on our event handler
223       // so lets have them handle this stuff
224       // well send a USER message to the other
225       // event handler so that it can properly
226       // call this event handler if required
227       CallWindowProc(this->OldProc,this->WindowId,WM_USER+14,28,(intptr_t)this->OldProc);
228       }
229     else
230       {
231       vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(intptr_t)this->OldProc);
232       }
233 #ifdef VTK_USE_TDX
234     if(this->Device->GetInitialized())
235       {
236       this->Device->Close();
237       }
238 #endif
239     }
240   this->Enabled = 0;
241   this->Modified();
242 }
243 
244 //----------------------------------------------------------------------------
TerminateApp(void)245 void vtkWin32RenderWindowInteractor::TerminateApp(void)
246 {
247   // Only post a quit message if Start was called...
248   //
249   if (this->StartedMessageLoop)
250     {
251     PostQuitMessage(0);
252     }
253 }
254 
255 //----------------------------------------------------------------------------
InternalCreateTimer(int timerId,int vtkNotUsed (timerType),unsigned long duration)256 int vtkWin32RenderWindowInteractor::InternalCreateTimer(int timerId, int vtkNotUsed(timerType),
257                                                         unsigned long duration)
258 {
259   // Win32 always creates repeating timers
260   SetTimer(this->WindowId,timerId,duration,NULL);
261   return timerId;
262 }
263 
264 //----------------------------------------------------------------------------
InternalDestroyTimer(int platformTimerId)265 int vtkWin32RenderWindowInteractor::InternalDestroyTimer(int platformTimerId)
266 {
267   return KillTimer(this->WindowId,platformTimerId);
268 }
269 
270 //-------------------------------------------------------------
271 // Virtual Key Code to Unix KeySym Conversion
272 //-------------------------------------------------------------
273 
274 // this ascii code to keysym table is meant to mimic Tk
275 
276 static const char *AsciiToKeySymTable[] = {
277   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
278   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
279   "space", "exclam", "quotedbl", "numbersign",
280   "dollar", "percent", "ampersand", "quoteright",
281   "parenleft", "parenright", "asterisk", "plus",
282   "comma", "minus", "period", "slash",
283   "0", "1", "2", "3", "4", "5", "6", "7",
284   "8", "9", "colon", "semicolon", "less", "equal", "greater", "question",
285   "at", "A", "B", "C", "D", "E", "F", "G",
286   "H", "I", "J", "K", "L", "M", "N", "O",
287   "P", "Q", "R", "S", "T", "U", "V", "W",
288   "X", "Y", "Z", "bracketleft",
289   "backslash", "bracketright", "asciicircum", "underscore",
290   "quoteleft", "a", "b", "c", "d", "e", "f", "g",
291   "h", "i", "j", "k", "l", "m", "n", "o",
292   "p", "q", "r", "s", "t", "u", "v", "w",
293   "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete",
294   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
296   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
297   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
301   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
302 
303 // this virtual key code to keysym table is meant to mimic Tk
304 
305 static const char *VKeyCodeToKeySymTable[] = {
306   0, 0, 0, "Cancel", 0, 0, 0, 0,
307   "BackSpace", "Tab", 0, 0, "Clear", "Return", 0, 0,
308   "Shift_L", "Control_L", "Alt_L", "Pause", "Caps_Lock", 0,0,0,
309   0, 0, 0, "Escape", 0, 0, 0, 0,
310   "space", "Prior", "Next", "End", "Home", "Left", "Up", "Right",
311   "Down", "Select", 0, "Execute", "Snapshot", "Insert", "Delete", "Help",
312   "0", "1", "2", "3", "4", "5", "6", "7",
313   "8", "9", 0, 0, 0, 0, 0, 0,
314   0, "a", "b", "c", "d", "e", "f", "g",
315   "h", "i", "j", "k", "l", "m", "n", "o",
316   "p", "q", "r", "s", "t", "u", "v", "w",
317   "x", "y", "z", "Win_L", "Win_R", "App", 0, 0,
318   "KP_0", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7",
319   "KP_8", "KP_9", "asterisk", "plus", "bar", "minus", "period", "slash",
320   "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
321   "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16",
322   "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24",
323   0, 0, 0, 0, 0, 0, 0, 0,
324   "Num_Lock", "Scroll_Lock", 0, 0, 0, 0, 0, 0,
325   0, 0, 0, 0, 0, 0, 0, 0,
326   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
327   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
328   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
329   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
332 
333 //-------------------------------------------------------------
334 // Event loop handlers
335 //-------------------------------------------------------------
OnMouseMove(HWND hWnd,UINT nFlags,int X,int Y)336 void vtkWin32RenderWindowInteractor::OnMouseMove(HWND hWnd, UINT nFlags,
337                                                  int X, int Y)
338 {
339   if (!this->Enabled)
340     {
341     return;
342     }
343 
344   this->SetEventInformationFlipY(X,
345                                  Y,
346                                  nFlags & MK_CONTROL,
347                                  nFlags & MK_SHIFT);
348   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
349   if (!this->MouseInWindow &&
350       (X >= 0 && X < this->Size[0] && Y >= 0 && Y < this->Size[1]))
351     {
352     this->InvokeEvent(vtkCommand::EnterEvent, NULL);
353     this->MouseInWindow = 1;
354     // request WM_MOUSELEAVE generation
355     TRACKMOUSEEVENT tme;
356     tme.cbSize = sizeof(TRACKMOUSEEVENT);
357     tme.dwFlags = TME_LEAVE;
358     tme.hwndTrack = hWnd;
359     TrackMouseEvent(&tme);
360     }
361 
362   this->InvokeEvent(vtkCommand::MouseMoveEvent, NULL);
363 }
364 
365 //----------------------------------------------------------------------------
OnNCMouseMove(HWND,UINT nFlags,int X,int Y)366 void vtkWin32RenderWindowInteractor::OnNCMouseMove(HWND, UINT nFlags,
367                                                    int X, int Y)
368 {
369   if (!this->Enabled)
370     {
371     return;
372     }
373 
374   int *pos = this->RenderWindow->GetPosition();
375   if (this->MouseInWindow)
376     {
377     this->SetEventInformationFlipY(X - pos[0],
378                                    Y - pos[1],
379                                    nFlags & MK_CONTROL,
380                                    nFlags & MK_SHIFT);
381     this->SetAltKey(GetKeyState(VK_MENU) & (~1));
382     this->InvokeEvent(vtkCommand::LeaveEvent, NULL);
383     this->MouseInWindow = 0;
384     }
385 }
386 
387 //----------------------------------------------------------------------------
OnMouseWheelForward(HWND,UINT nFlags,int X,int Y)388 void vtkWin32RenderWindowInteractor::OnMouseWheelForward(HWND,UINT nFlags,
389                                                    int X, int Y)
390 {
391   if (!this->Enabled)
392     {
393     return;
394     }
395   this->SetEventInformationFlipY(X,
396                                  Y,
397                                  nFlags & MK_CONTROL,
398                                  nFlags & MK_SHIFT);
399   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
400   this->InvokeEvent(vtkCommand::MouseWheelForwardEvent,NULL);
401 }
402 
403 //----------------------------------------------------------------------------
OnMouseWheelBackward(HWND,UINT nFlags,int X,int Y)404 void vtkWin32RenderWindowInteractor::OnMouseWheelBackward(HWND,UINT nFlags,
405                                                    int X, int Y)
406 {
407   if (!this->Enabled)
408     {
409     return;
410     }
411   this->SetEventInformationFlipY(X,
412                                  Y,
413                                  nFlags & MK_CONTROL,
414                                  nFlags & MK_SHIFT);
415   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
416   this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent,NULL);
417 }
418 
419 //----------------------------------------------------------------------------
OnLButtonDown(HWND wnd,UINT nFlags,int X,int Y,int repeat)420 void vtkWin32RenderWindowInteractor::OnLButtonDown(HWND wnd,UINT nFlags,
421                                                    int X, int Y, int repeat)
422 {
423   if (!this->Enabled)
424     {
425     return;
426     }
427   SetFocus(wnd);
428   SetCapture(wnd);
429   this->SetEventInformationFlipY(X,
430                                  Y,
431                                  nFlags & MK_CONTROL,
432                                  nFlags & MK_SHIFT,
433                                  0, repeat);
434   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
435   this->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL);
436 }
437 
438 //----------------------------------------------------------------------------
OnLButtonUp(HWND,UINT nFlags,int X,int Y)439 void vtkWin32RenderWindowInteractor::OnLButtonUp(HWND,UINT nFlags,
440                                                  int X, int Y)
441 {
442   if (!this->Enabled)
443     {
444     return;
445     }
446   this->SetEventInformationFlipY(X,
447                                  Y,
448                                  nFlags & MK_CONTROL,
449                                  nFlags & MK_SHIFT);
450   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
451   this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL);
452   ReleaseCapture( );
453 }
454 
455 //----------------------------------------------------------------------------
OnMButtonDown(HWND wnd,UINT nFlags,int X,int Y,int repeat)456 void vtkWin32RenderWindowInteractor::OnMButtonDown(HWND wnd,UINT nFlags,
457                                                    int X, int Y, int repeat)
458 {
459   if (!this->Enabled)
460     {
461     return;
462     }
463   SetFocus(wnd);
464   SetCapture(wnd);
465   this->SetEventInformationFlipY(X,
466                                  Y,
467                                  nFlags & MK_CONTROL,
468                                  nFlags & MK_SHIFT,
469                                  0, repeat);
470   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
471   this->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL);
472 }
473 
474 //----------------------------------------------------------------------------
OnMButtonUp(HWND,UINT nFlags,int X,int Y)475 void vtkWin32RenderWindowInteractor::OnMButtonUp(HWND,UINT nFlags,
476                                                  int X, int Y)
477 {
478   if (!this->Enabled)
479     {
480     return;
481     }
482   this->SetEventInformationFlipY(X,
483                                  Y,
484                                  nFlags & MK_CONTROL,
485                                  nFlags & MK_SHIFT);
486   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
487   this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL);
488   ReleaseCapture( );
489 }
490 
491 //----------------------------------------------------------------------------
OnRButtonDown(HWND wnd,UINT nFlags,int X,int Y,int repeat)492 void vtkWin32RenderWindowInteractor::OnRButtonDown(HWND wnd,UINT nFlags,
493                                                    int X, int Y, int repeat)
494 {
495   if (!this->Enabled)
496     {
497     return;
498     }
499   SetFocus(wnd);
500   SetCapture(wnd);
501   this->SetEventInformationFlipY(X,
502                                  Y,
503                                  nFlags & MK_CONTROL,
504                                  nFlags & MK_SHIFT,
505                                  0, repeat);
506   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
507   this->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL);
508 }
509 
510 //----------------------------------------------------------------------------
OnRButtonUp(HWND,UINT nFlags,int X,int Y)511 void vtkWin32RenderWindowInteractor::OnRButtonUp(HWND,UINT nFlags,
512                                                  int X, int Y)
513 {
514   if (!this->Enabled)
515     {
516     return;
517     }
518   this->SetEventInformationFlipY(X,
519                                  Y,
520                                  nFlags & MK_CONTROL,
521                                  nFlags & MK_SHIFT);
522   this->SetAltKey(GetKeyState(VK_MENU) & (~1));
523   this->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL);
524   ReleaseCapture( );
525 }
526 
527 //----------------------------------------------------------------------------
OnSize(HWND,UINT,int X,int Y)528 void vtkWin32RenderWindowInteractor::OnSize(HWND,UINT, int X, int Y) {
529   this->UpdateSize(X,Y);
530   if (this->Enabled)
531     {
532     this->InvokeEvent(vtkCommand::ConfigureEvent,NULL);
533     }
534 }
535 
536 //----------------------------------------------------------------------------
OnTimer(HWND,UINT timerId)537 void vtkWin32RenderWindowInteractor::OnTimer(HWND,UINT timerId)
538 {
539   if (!this->Enabled)
540     {
541     return;
542     }
543   int tid = static_cast<int>(timerId);
544   this->InvokeEvent(vtkCommand::TimerEvent,(void*)&tid);
545 
546   // Here we deal with one-shot versus repeating timers
547   if ( this->IsOneShotTimer(tid) )
548     {
549     KillTimer(this->WindowId,tid); //'cause windows timers are always repeating
550     }
551 }
552 
553 //----------------------------------------------------------------------------
OnKeyDown(HWND,UINT vCode,UINT nRepCnt,UINT nFlags)554 void vtkWin32RenderWindowInteractor::OnKeyDown(HWND, UINT vCode, UINT nRepCnt, UINT nFlags)
555 {
556   if (!this->Enabled)
557     {
558     return;
559     }
560   int ctrl  = GetKeyState(VK_CONTROL) & (~1);
561   int shift = GetKeyState(VK_SHIFT) & (~1);
562   int alt = GetKeyState(VK_MENU) & (~1);
563   WORD nChar = 0;
564   {
565 #ifndef _WIN32_WCE
566     BYTE keyState[256];
567     GetKeyboardState(keyState);
568     if (ToAscii(vCode,nFlags & 0xff,keyState,&nChar,0) == 0)
569       {
570       nChar = 0;
571       }
572 #endif
573   }
574   const char *keysym = AsciiToKeySymTable[(unsigned char)nChar];
575   if (keysym == 0)
576     {
577     keysym = VKeyCodeToKeySymTable[(unsigned char)vCode];
578     }
579   if (keysym == 0)
580     {
581     keysym = "None";
582     }
583   this->SetKeyEventInformation(ctrl,
584                                shift,
585                                nChar,
586                                nRepCnt,
587                                keysym);
588   this->SetAltKey(alt);
589   this->InvokeEvent(vtkCommand::KeyPressEvent, NULL);
590 }
591 
592 //----------------------------------------------------------------------------
OnKeyUp(HWND,UINT vCode,UINT nRepCnt,UINT nFlags)593 void vtkWin32RenderWindowInteractor::OnKeyUp(HWND, UINT vCode, UINT nRepCnt, UINT nFlags)
594 {
595   if (!this->Enabled)
596     {
597     return;
598     }
599   int ctrl  = GetKeyState(VK_CONTROL) & (~1);
600   int shift = GetKeyState(VK_SHIFT) & (~1);
601   int alt = GetKeyState(VK_MENU) & (~1);
602   WORD nChar = 0;
603   {
604     BYTE keyState[256];
605 #ifndef _WIN32_WCE
606     GetKeyboardState(keyState);
607     if (ToAscii(vCode,nFlags & 0xff,keyState,&nChar,0) == 0)
608       {
609       nChar = 0;
610       }
611 #endif
612   }
613   const char *keysym = AsciiToKeySymTable[(unsigned char)nChar];
614   if (keysym == 0)
615     {
616     keysym = VKeyCodeToKeySymTable[(unsigned char)vCode];
617     }
618   if (keysym == 0)
619     {
620     keysym = "None";
621     }
622   this->SetKeyEventInformation(ctrl,
623                                shift,
624                                nChar,
625                                nRepCnt,
626                                keysym);
627   this->SetAltKey(alt);
628   this->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL);
629 }
630 
631 //----------------------------------------------------------------------------
OnChar(HWND,UINT nChar,UINT nRepCnt,UINT)632 void vtkWin32RenderWindowInteractor::OnChar(HWND,UINT nChar,
633                                             UINT nRepCnt, UINT)
634 {
635   if (!this->Enabled)
636     {
637     return;
638     }
639   int ctrl  = GetKeyState(VK_CONTROL) & (~1);
640   int shift = GetKeyState(VK_SHIFT) & (~1);
641   int alt = GetKeyState(VK_MENU) & (~1);
642   this->SetKeyEventInformation(ctrl,
643                                shift,
644                                nChar,
645                                nRepCnt);
646   this->SetAltKey(alt);
647   this->InvokeEvent(vtkCommand::CharEvent, NULL);
648 }
649 
650 //----------------------------------------------------------------------------
OnFocus(HWND,UINT)651 void vtkWin32RenderWindowInteractor::OnFocus(HWND,UINT)
652 {
653   if (!this->Enabled)
654     {
655     return;
656     }
657 
658 #ifdef VTK_USE_TDX
659   if(this->Device->GetInitialized() && !this->Device->GetIsListening())
660     {
661     this->Device->StartListening();
662     }
663 #endif
664 }
665 
666 //----------------------------------------------------------------------------
OnKillFocus(HWND,UINT)667 void vtkWin32RenderWindowInteractor::OnKillFocus(HWND,UINT)
668 {
669   if (!this->Enabled)
670     {
671     return;
672     }
673 #ifdef VTK_USE_TDX
674   if(this->Device->GetInitialized() && this->Device->GetIsListening())
675     {
676     this->Device->StopListening();
677     }
678 #endif
679 }
680 
681 //----------------------------------------------------------------------------
682 // This is only called when InstallMessageProc is true
vtkHandleMessage(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)683 LRESULT CALLBACK vtkHandleMessage(HWND hWnd,UINT uMsg, WPARAM wParam,
684                                   LPARAM lParam)
685 {
686   LRESULT res = 0;
687   vtkWin32OpenGLRenderWindow *ren;
688   vtkWin32RenderWindowInteractor *me = 0;
689 
690   ren = (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd,sizeof(vtkLONG));
691 
692   if (ren)
693     {
694     me = (vtkWin32RenderWindowInteractor *)ren->GetInteractor();
695     }
696 
697   if (me && me->GetReferenceCount()>0)
698     {
699     me->Register(me);
700     res = vtkHandleMessage2(hWnd,uMsg,wParam,lParam,me);
701     me->UnRegister(me);
702     }
703 
704   return res;
705 }
706 
707 #ifndef MAKEPOINTS
708 #define MAKEPOINTS(l)   (*((POINTS FAR *) & (l)))
709 #endif
710 
711 //----------------------------------------------------------------------------
vtkHandleMessage2(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,vtkWin32RenderWindowInteractor * me)712 LRESULT CALLBACK vtkHandleMessage2(HWND hWnd,UINT uMsg, WPARAM wParam,
713                                    LPARAM lParam,
714                                    vtkWin32RenderWindowInteractor *me)
715 {
716   if ((uMsg == WM_USER+13)&&(wParam == 26))
717     {
718     // someone is telling us to set our OldProc
719     me->OldProc = (WNDPROC)lParam;
720     return 1;
721     }
722 
723   switch (uMsg)
724     {
725     case WM_PAINT:
726       me->Render();
727       return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam);
728 
729     case WM_SIZE:
730       me->OnSize(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
731       return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam);
732 
733     case WM_LBUTTONDBLCLK:
734       me->OnLButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1);
735       break;
736 
737     case WM_LBUTTONDOWN:
738       me->OnLButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0);
739       break;
740 
741     case WM_LBUTTONUP:
742       me->OnLButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
743       break;
744 
745     case WM_MBUTTONDBLCLK:
746       me->OnMButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1);
747       break;
748 
749     case WM_MBUTTONDOWN:
750       me->OnMButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0);
751       break;
752 
753     case WM_MBUTTONUP:
754       me->OnMButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
755       break;
756 
757     case WM_RBUTTONDBLCLK:
758       me->OnRButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1);
759       break;
760 
761     case WM_RBUTTONDOWN:
762       me->OnRButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0);
763       break;
764 
765     case WM_RBUTTONUP:
766       me->OnRButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
767       break;
768 
769     case WM_MOUSELEAVE:
770       me->InvokeEvent(vtkCommand::LeaveEvent, NULL);
771       me->MouseInWindow = 0;
772       break;
773 
774     case WM_MOUSEMOVE:
775       me->OnMouseMove(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
776       break;
777 
778     case WM_MOUSEWHEEL:
779       {
780       POINT pt;
781       pt.x = MAKEPOINTS(lParam).x;
782       pt.y = MAKEPOINTS(lParam).y;
783       ::ScreenToClient(hWnd, &pt);
784       if( GET_WHEEL_DELTA_WPARAM(wParam) > 0)
785         me->OnMouseWheelForward(hWnd,wParam,pt.x,pt.y);
786       else
787         me->OnMouseWheelBackward(hWnd,wParam,pt.x,pt.y);
788       }
789       break;
790 
791 #ifdef WM_MCVMOUSEMOVE
792     case WM_NCMOUSEMOVE:
793       me->OnNCMouseMove(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
794       break;
795 #endif
796 
797     case WM_CLOSE:
798       me->ExitCallback();
799       break;
800 
801     case WM_CHAR:
802       me->OnChar(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
803       break;
804 
805     case WM_KEYDOWN:
806     case WM_SYSKEYDOWN:
807       me->OnKeyDown(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
808       break;
809 
810     case WM_KEYUP:
811     case WM_SYSKEYUP:
812       me->OnKeyUp(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
813       break;
814 
815     case WM_TIMER:
816       me->OnTimer(hWnd,wParam);
817       break;
818 
819     case WM_ACTIVATE:
820       if(wParam==WA_INACTIVE)
821         {
822         me->OnKillFocus(hWnd,wParam);
823         }
824       else
825         {
826         me->OnFocus(hWnd,wParam);
827         }
828       break;
829 
830     case WM_SETFOCUS:
831       // occurs when SetFocus() is called on the current window
832       me->OnFocus(hWnd,wParam);
833       break;
834 
835     case WM_KILLFOCUS:
836       // occurs when the focus was on the current window and SetFocus() is
837       // called on another window.
838       me->OnKillFocus(hWnd,wParam);
839       break;
840 
841     default:
842       if (me)
843         {
844         return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam);
845         }
846     };
847 
848   return 0;
849 }
850 
851 //----------------------------------------------------------------------------
852 // Specify the default function to be called when an interactor needs to exit.
853 // This callback is overridden by an instance ExitMethod that is defined.
854 void
SetClassExitMethod(void (* f)(void *),void * arg)855 vtkWin32RenderWindowInteractor::SetClassExitMethod(void (*f)(void *),void *arg)
856 {
857   if ( f != vtkWin32RenderWindowInteractor::ClassExitMethod
858        || arg != vtkWin32RenderWindowInteractor::ClassExitMethodArg)
859     {
860     // delete the current arg if there is a delete method
861     if ((vtkWin32RenderWindowInteractor::ClassExitMethodArg)
862         && (vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete))
863       {
864       (*vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)
865         (vtkWin32RenderWindowInteractor::ClassExitMethodArg);
866       }
867     vtkWin32RenderWindowInteractor::ClassExitMethod = f;
868     vtkWin32RenderWindowInteractor::ClassExitMethodArg = arg;
869 
870     // no call to this->Modified() since this is a class member function
871     }
872 }
873 
874 //----------------------------------------------------------------------------
875 // Set the arg delete method.  This is used to free user memory.
876 void
SetClassExitMethodArgDelete(void (* f)(void *))877 vtkWin32RenderWindowInteractor::SetClassExitMethodArgDelete(void (*f)(void *))
878 {
879   if (f != vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)
880     {
881     vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete = f;
882 
883     // no call to this->Modified() since this is a class member function
884     }
885 }
886 
887 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)888 void vtkWin32RenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
889 {
890   this->Superclass::PrintSelf(os,indent);
891   os << indent << "InstallMessageProc: " << this->InstallMessageProc << endl;
892   os << indent << "StartedMessageLoop: " << this->StartedMessageLoop << endl;
893 }
894 
895 //----------------------------------------------------------------------------
ExitCallback()896 void vtkWin32RenderWindowInteractor::ExitCallback()
897 {
898   if (this->HasObserver(vtkCommand::ExitEvent))
899     {
900     this->InvokeEvent(vtkCommand::ExitEvent,NULL);
901     }
902   else if (this->ClassExitMethod)
903     {
904     (*this->ClassExitMethod)(this->ClassExitMethodArg);
905     }
906 
907   this->TerminateApp();
908 }
909