1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 // include windows.h first to have all definitions available
20 #include <WNT_Window.hxx>
22 #if defined(_WIN32) && !defined(OCCT_UWP)
24 #include <Aspect_ScrollDelta.hxx>
25 #include <Aspect_WindowDefinitionError.hxx>
26 #include <Aspect_WindowError.hxx>
27 #include <Aspect_WindowInputListener.hxx>
28 #include <Message.hxx>
29 #include <NCollection_LocalArray.hxx>
30 #include <TCollection_ExtendedString.hxx>
31 #include <WNT_WClass.hxx>
32 #include <WNT_HIDSpaceMouse.hxx>
34 IMPLEMENT_STANDARD_RTTIEXT(WNT_Window, Aspect_Window)
36 // =======================================================================
37 // function : WNT_Window
39 // =======================================================================
40 WNT_Window::WNT_Window (const Standard_CString theTitle,
41 const Handle(WNT_WClass)& theClass,
42 const WNT_Dword& theStyle,
43 const Standard_Integer thePxLeft,
44 const Standard_Integer thePxTop,
45 const Standard_Integer thePxWidth,
46 const Standard_Integer thePxHeight,
47 const Quantity_NameOfColor theBackColor,
48 const Aspect_Handle theParent,
49 const Aspect_Handle theMenu,
50 const Standard_Address theClientStruct)
54 myHParentWindow (NULL),
57 myXRight (thePxLeft + thePxWidth),
58 myYBottom (thePxTop + thePxHeight),
59 myIsForeign (Standard_False)
61 if (thePxWidth <= 0 || thePxHeight <= 0)
63 throw Aspect_WindowDefinitionError("Coordinate(s) out of range");
66 DWORD aStyle = theStyle;
67 if (theParent && !(theStyle & WS_CHILD))
69 aStyle |= WS_CHILD | WS_CLIPSIBLINGS;
71 else if (!theParent && !(theStyle & WS_CLIPCHILDREN))
73 aStyle |= WS_CLIPCHILDREN;
76 // include decorations in the window dimensions to reproduce same behavior of Xw_Window
79 aRect.bottom = myYBottom;
81 aRect.right = myXRight;
82 AdjustWindowRect (&aRect, aStyle, theMenu != NULL ? TRUE : FALSE);
85 myXRight = aRect.right;
86 myYBottom = aRect.bottom;
88 const TCollection_ExtendedString aTitleW (theTitle);
89 const TCollection_ExtendedString aClassNameW (myWClass->Name());
90 myHWindow = CreateWindowW (aClassNameW.ToWideString(), aTitleW.ToWideString(),
93 (myXRight - myXLeft), (myYBottom - myYTop),
96 (HINSTANCE )myWClass->Instance(),
100 throw Aspect_WindowDefinitionError("Unable to create window");
103 myHParentWindow = theParent;
104 SetBackground (theBackColor);
107 // =======================================================================
108 // function : WNT_Window
110 // =======================================================================
111 WNT_Window::WNT_Window (const Aspect_Handle theHandle,
112 const Quantity_NameOfColor theBackColor)
113 : myHWindow (theHandle),
114 myHParentWindow (GetParent ((HWND )theHandle)),
119 myIsForeign (Standard_True)
121 SetBackground (theBackColor);
123 WINDOWPLACEMENT aPlace = {};
124 aPlace.length = sizeof(WINDOWPLACEMENT);
125 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
127 myXLeft = aPlace.rcNormalPosition.left;
128 myYTop = aPlace.rcNormalPosition.top;
129 myXRight = aPlace.rcNormalPosition.right;
130 myYBottom = aPlace.rcNormalPosition.bottom;
133 // =======================================================================
134 // function : ~WNT_Window
136 // =======================================================================
137 WNT_Window::~WNT_Window()
139 if (myHWindow == NULL
145 DestroyWindow ((HWND )myHWindow);
146 myIsForeign = Standard_False;
149 // =======================================================================
150 // function : SetCursor
152 // =======================================================================
153 void WNT_Window::SetCursor (const Aspect_Handle theCursor) const
155 ::SetClassLongPtrW ((HWND )myHWindow, GCLP_HCURSOR, (LONG_PTR )theCursor);
158 // =======================================================================
159 // function : IsMapped
161 // =======================================================================
162 Standard_Boolean WNT_Window::IsMapped() const
166 return Standard_True;
169 WINDOWPLACEMENT aPlace = {};
170 aPlace.length = sizeof(WINDOWPLACEMENT);
171 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
172 return !(aPlace.showCmd == SW_HIDE
173 || aPlace.showCmd == SW_MINIMIZE);
176 // =======================================================================
179 // =======================================================================
180 void WNT_Window::Map() const
188 // =======================================================================
191 // =======================================================================
192 void WNT_Window::Map (const Standard_Integer theMapMode) const
199 ::ShowWindow ((HWND )myHWindow, theMapMode);
200 ::UpdateWindow ((HWND )myHWindow);
203 // =======================================================================
206 // =======================================================================
207 void WNT_Window::Unmap() const
212 // =======================================================================
213 // function : DoResize
215 // =======================================================================
216 Aspect_TypeOfResize WNT_Window::DoResize()
220 return Aspect_TOR_UNKNOWN;
223 WINDOWPLACEMENT aPlace = {};
224 aPlace.length = sizeof(WINDOWPLACEMENT);
225 GetWindowPlacement ((HWND )myHWindow, &aPlace);
226 if (aPlace.showCmd == SW_SHOWMINIMIZED)
228 return Aspect_TOR_UNKNOWN;
232 if (Abs ((int )aPlace.rcNormalPosition.left - myXLeft ) > 2) { aMask |= 1; }
233 if (Abs ((int )aPlace.rcNormalPosition.right - myXRight ) > 2) { aMask |= 2; }
234 if (Abs ((int )aPlace.rcNormalPosition.top - myYTop ) > 2) { aMask |= 4; }
235 if (Abs ((int )aPlace.rcNormalPosition.bottom - myYBottom) > 2) { aMask |= 8; }
237 myXLeft = aPlace.rcNormalPosition.left;
238 myXRight = aPlace.rcNormalPosition.right;
239 myYTop = aPlace.rcNormalPosition.top;
240 myYBottom = aPlace.rcNormalPosition.bottom;
243 case 0: return Aspect_TOR_NO_BORDER;
244 case 1: return Aspect_TOR_LEFT_BORDER;
245 case 2: return Aspect_TOR_RIGHT_BORDER;
246 case 4: return Aspect_TOR_TOP_BORDER;
247 case 5: return Aspect_TOR_LEFT_AND_TOP_BORDER;
248 case 6: return Aspect_TOR_TOP_AND_RIGHT_BORDER;
249 case 8: return Aspect_TOR_BOTTOM_BORDER;
250 case 9: return Aspect_TOR_BOTTOM_AND_LEFT_BORDER;
251 case 10: return Aspect_TOR_RIGHT_AND_BOTTOM_BORDER;
253 return Aspect_TOR_UNKNOWN;
256 // =======================================================================
259 // =======================================================================
260 Standard_Real WNT_Window::Ratio() const
264 return Standard_Real(myXRight - myXLeft)/ Standard_Real(myYBottom - myYTop);
268 GetClientRect ((HWND )myHWindow, &aRect);
269 return Standard_Real(aRect.right - aRect.left) / Standard_Real(aRect.bottom - aRect.top);
272 // =======================================================================
273 // function : Position
275 // =======================================================================
276 void WNT_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
277 Standard_Integer& theX2, Standard_Integer& theY2) const
289 ::GetClientRect ((HWND )myHWindow, &aRect);
291 POINT aPntLeft, aPntRight;
292 aPntLeft.x = aPntLeft.y = 0;
293 ::ClientToScreen ((HWND )myHWindow, &aPntLeft);
294 aPntRight.x = aRect.right;
295 aPntRight.y = aRect.bottom;
296 ::ClientToScreen ((HWND )myHWindow, &aPntRight);
298 if (myHParentWindow != NULL)
300 ::ScreenToClient ((HWND )myHParentWindow, &aPntLeft);
301 ::ScreenToClient ((HWND )myHParentWindow, &aPntRight);
310 // =======================================================================
313 // =======================================================================
314 void WNT_Window::Size (Standard_Integer& theWidth,
315 Standard_Integer& theHeight) const
319 theWidth = myXRight - myXLeft;
320 theHeight = myYBottom - myYTop;
325 ::GetClientRect ((HWND )myHWindow, &aRect);
326 theWidth = aRect.right;
327 theHeight = aRect.bottom;
330 // =======================================================================
333 // =======================================================================
334 void WNT_Window::SetPos (const Standard_Integer theX, const Standard_Integer theY,
335 const Standard_Integer theX1, const Standard_Integer theY1)
343 // =======================================================================
344 // function : SetTitle
346 // =======================================================================
347 void WNT_Window::SetTitle (const TCollection_AsciiString& theTitle)
349 const TCollection_ExtendedString aTitleW (theTitle);
350 SetWindowTextW ((HWND )myHWindow, aTitleW.ToWideString());
353 // =======================================================================
354 // function : InvalidateContent
356 // =======================================================================
357 void WNT_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& )
359 if (myHWindow != NULL)
361 ::InvalidateRect ((HWND )myHWindow, NULL, TRUE);
365 // =======================================================================
366 // function : VirtualKeyFromNative
368 // =======================================================================
369 Aspect_VKey WNT_Window::VirtualKeyFromNative (Standard_Integer theKey)
371 if (theKey >= Standard_Integer('0')
372 && theKey <= Standard_Integer('9'))
374 return Aspect_VKey((theKey - Standard_Integer('0')) + Aspect_VKey_0);
376 if (theKey >= Standard_Integer('A')
377 && theKey <= Standard_Integer('Z'))
379 // main latin alphabet keys
380 return Aspect_VKey((theKey - Standard_Integer('A')) + Aspect_VKey_A);
386 if (theKey <= VK_F12)
388 return Aspect_VKey((theKey - VK_F1) + Aspect_VKey_F1);
390 return Aspect_VKey_UNKNOWN;
392 if (theKey >= VK_NUMPAD0
393 && theKey <= VK_NUMPAD9)
396 return Aspect_VKey((theKey - VK_NUMPAD0) + Aspect_VKey_Numpad0);
407 return Aspect_VKey_UNKNOWN;
409 return Aspect_VKey_Backspace;
411 return Aspect_VKey_Tab;
413 return Aspect_VKey_UNKNOWN;
415 return Aspect_VKey_Enter;
417 return Aspect_VKey_Shift;
419 return Aspect_VKey_Control;
421 return Aspect_VKey_Alt; //Aspect_VKey_Menu;
424 return Aspect_VKey_UNKNOWN;
426 return Aspect_VKey_Escape;
431 return Aspect_VKey_UNKNOWN;
433 return Aspect_VKey_Space;
435 return Aspect_VKey_PageUp;
437 return Aspect_VKey_PageDown;
439 return Aspect_VKey_End;
441 return Aspect_VKey_Home;
443 return Aspect_VKey_Left;
445 return Aspect_VKey_Up;
447 return Aspect_VKey_Down;
449 return Aspect_VKey_Right;
454 return Aspect_VKey_UNKNOWN;
456 return Aspect_VKey_UNKNOWN; // Aspect_VKey_Insert
458 return Aspect_VKey_Delete;
464 return Aspect_VKey_UNKNOWN;
466 return Aspect_VKey_NumpadMultiply;
468 return Aspect_VKey_NumpadAdd;
471 return Aspect_VKey_UNKNOWN;
473 return Aspect_VKey_NumpadSubtract;
475 return Aspect_VKey_NumpadDivide;
477 return Aspect_VKey_Numlock;
479 return Aspect_VKey_Scroll;
486 return Aspect_VKey_UNKNOWN;
487 case VK_BROWSER_BACK:
488 return Aspect_VKey_BrowserBack;
489 case VK_BROWSER_FORWARD:
490 return Aspect_VKey_BrowserForward;
491 case VK_BROWSER_REFRESH:
492 return Aspect_VKey_BrowserRefresh;
493 case VK_BROWSER_STOP:
494 return Aspect_VKey_BrowserStop;
495 case VK_BROWSER_SEARCH:
496 return Aspect_VKey_BrowserSearch;
497 case VK_BROWSER_FAVORITES:
498 return Aspect_VKey_BrowserFavorites;
499 case VK_BROWSER_HOME:
500 return Aspect_VKey_BrowserHome;
502 return Aspect_VKey_VolumeMute;
504 return Aspect_VKey_VolumeDown;
506 return Aspect_VKey_VolumeUp;
507 case VK_MEDIA_NEXT_TRACK:
508 return Aspect_VKey_MediaNextTrack;
509 case VK_MEDIA_PREV_TRACK:
510 return Aspect_VKey_MediaPreviousTrack;
512 return Aspect_VKey_MediaStop;
513 case VK_MEDIA_PLAY_PAUSE:
514 return Aspect_VKey_MediaPlayPause;
516 return Aspect_VKey_Semicolon;
518 return Aspect_VKey_Plus;
520 return Aspect_VKey_Comma;
522 return Aspect_VKey_Minus;
524 return Aspect_VKey_Period;
526 return Aspect_VKey_Slash;
528 return Aspect_VKey_Tilde;
530 return Aspect_VKey_BracketLeft;
532 return Aspect_VKey_Backslash;
534 return Aspect_VKey_BracketRight;
536 return Aspect_VKey_Apostrophe;
538 return Aspect_VKey_UNKNOWN;
541 // =======================================================================
542 // function : MouseKeyFlagsFromEvent
544 // =======================================================================
545 Aspect_VKeyFlags WNT_Window::MouseKeyFlagsFromEvent (WPARAM theKeys)
547 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
548 if ((theKeys & MK_CONTROL) != 0)
550 aFlags |= Aspect_VKeyFlags_CTRL;
552 if ((theKeys & MK_SHIFT) != 0)
554 aFlags |= Aspect_VKeyFlags_SHIFT;
556 if (GetKeyState (VK_MENU) < 0)
558 aFlags |= Aspect_VKeyFlags_ALT;
563 // =======================================================================
564 // function : MouseKeyFlagsAsync
566 // =======================================================================
567 Aspect_VKeyFlags WNT_Window::MouseKeyFlagsAsync()
569 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
570 if ((GetAsyncKeyState (VK_CONTROL) & 0x8000) != 0)
572 aFlags |= Aspect_VKeyFlags_CTRL;
574 if ((GetAsyncKeyState (VK_SHIFT) & 0x8000) != 0)
576 aFlags |= Aspect_VKeyFlags_SHIFT;
578 if ((GetAsyncKeyState (VK_MENU) & 0x8000) != 0)
580 aFlags |= Aspect_VKeyFlags_ALT;
585 // =======================================================================
586 // function : MouseButtonsFromEvent
588 // =======================================================================
589 Aspect_VKeyMouse WNT_Window::MouseButtonsFromEvent (WPARAM theKeys)
591 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
592 if ((theKeys & MK_LBUTTON) != 0)
594 aButtons |= Aspect_VKeyMouse_LeftButton;
596 if ((theKeys & MK_MBUTTON) != 0)
598 aButtons |= Aspect_VKeyMouse_MiddleButton;
600 if ((theKeys & MK_RBUTTON) != 0)
602 aButtons |= Aspect_VKeyMouse_RightButton;
607 // =======================================================================
608 // function : MouseButtonsAsync
610 // =======================================================================
611 Aspect_VKeyMouse WNT_Window::MouseButtonsAsync()
613 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
614 const bool isSwapped = GetSystemMetrics (SM_SWAPBUTTON) != 0;
616 if ((GetAsyncKeyState (!isSwapped ? VK_LBUTTON : VK_RBUTTON) & 0x8000) != 0)
618 aButtons |= Aspect_VKeyMouse_LeftButton;
620 if ((GetAsyncKeyState (VK_MBUTTON) & 0x8000) != 0)
622 aButtons |= Aspect_VKeyMouse_MiddleButton;
624 if ((GetAsyncKeyState (!isSwapped ? VK_RBUTTON : VK_LBUTTON) & 0x8000) != 0)
626 aButtons |= Aspect_VKeyMouse_RightButton;
631 // =======================================================================
632 // function : RegisterRawInputDevices
634 // =======================================================================
635 int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask)
638 || myHWindow == NULL)
644 enum HidUsagePage { THE_HID_USAGE_PAGE_GENERIC = 0x01 }; // HID_USAGE_PAGE_GENERIC
647 THE_HID_USAGE_GENERIC_MOUSE = 0x02, // HID_USAGE_GENERIC_MOUSE
648 THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER = 0x08, // HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
652 RAWINPUTDEVICE aRawInDevList[2];
653 if ((theRawDeviceMask & RawInputMask_Mouse) != 0)
656 RAWINPUTDEVICE& aRawMouse = aRawInDevList[aNbDevices++];
657 aRawMouse.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
658 aRawMouse.usUsage = THE_HID_USAGE_GENERIC_MOUSE;
659 aRawMouse.dwFlags = RIDEV_INPUTSINK;
660 aRawMouse.hwndTarget = (HWND )myHWindow;
662 if ((theRawDeviceMask & RawInputMask_SpaceMouse) != 0)
665 RAWINPUTDEVICE& aRawSpace = aRawInDevList[aNbDevices++];
666 aRawSpace.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
667 aRawSpace.usUsage = THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER;
668 aRawSpace.dwFlags = 0; // RIDEV_DEVNOTIFY
669 aRawSpace.hwndTarget = (HWND )myHWindow;
672 for (int aTryIter = aNbDevices; aTryIter > 0; --aTryIter)
674 if (::RegisterRawInputDevices (aRawInDevList, aTryIter, sizeof(aRawInDevList[0])))
679 Message::SendTrace (aRawInDevList[aTryIter - 1].usUsage == THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
680 ? "Warning: RegisterRawInputDevices() failed to register RAW multi-axis controller input"
681 : "Warning: RegisterRawInputDevices() failed to register RAW mouse input");
686 // =======================================================================
687 // function : ProcessMessage
689 // =======================================================================
690 bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener,
693 switch (theMsg.message)
697 if (theMsg.hwnd == (HWND )myHWindow)
699 theListener.ProcessClose();
706 if (theMsg.hwnd == (HWND )myHWindow)
708 theListener.ProcessFocus (LOWORD(theMsg.wParam) == WA_CLICKACTIVE
709 || LOWORD(theMsg.wParam) == WA_ACTIVE);
717 BeginPaint(theMsg.hwnd, &aPaint);
718 EndPaint (theMsg.hwnd, &aPaint);
719 theListener.ProcessExpose();
727 theListener.ProcessConfigure (theMsg.message == WM_SIZE);
733 const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )theMsg.wParam);
734 if (aVKey != Aspect_VKey_UNKNOWN)
736 const double aTimeStamp = theListener.EventTime();
737 if (theMsg.message == WM_KEYDOWN)
739 theListener.KeyDown (aVKey, aTimeStamp);
743 theListener.KeyUp (aVKey, aTimeStamp);
745 theListener.ProcessInput();
756 const Graphic3d_Vec2i aPos (LOWORD(theMsg.lParam), HIWORD(theMsg.lParam));
757 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theMsg.wParam);
758 Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
759 switch (theMsg.message)
763 aButton = Aspect_VKeyMouse_LeftButton;
767 aButton = Aspect_VKeyMouse_MiddleButton;
771 aButton = Aspect_VKeyMouse_RightButton;
774 if (theMsg.message == WM_LBUTTONDOWN
775 || theMsg.message == WM_MBUTTONDOWN
776 || theMsg.message == WM_RBUTTONDOWN)
778 SetFocus (theMsg.hwnd);
779 SetCapture(theMsg.hwnd);
780 theListener.PressMouseButton (aPos, aButton, aFlags, false);
785 theListener.ReleaseMouseButton (aPos, aButton, aFlags, false);
787 theListener.ProcessInput();
792 const int aDelta = GET_WHEEL_DELTA_WPARAM (theMsg.wParam);
793 const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
794 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theMsg.wParam);
795 Graphic3d_Vec2i aPos (int(short(LOWORD(theMsg.lParam))), int(short(HIWORD(theMsg.lParam))));
796 POINT aCursorPnt = { aPos.x(), aPos.y() };
797 if (ScreenToClient (theMsg.hwnd, &aCursorPnt))
799 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
802 if (theMsg.hwnd != (HWND )myHWindow)
807 theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
808 theListener.ProcessInput();
813 Graphic3d_Vec2i aPos (LOWORD(theMsg.lParam), HIWORD(theMsg.lParam));
814 Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (theMsg.wParam);
815 Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theMsg.wParam);
817 // don't make a slide-show from input events - fetch the actual mouse cursor position
819 aCursor.cbSize = sizeof(aCursor);
820 if (::GetCursorInfo (&aCursor) != FALSE)
822 POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
823 if (ScreenToClient (theMsg.hwnd, &aCursorPnt))
825 // as we override mouse position, we need overriding also mouse state
826 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
827 aButtons = WNT_Window::MouseButtonsAsync();
828 aFlags = WNT_Window::MouseKeyFlagsAsync();
832 if (theMsg.hwnd != (HWND )myHWindow)
834 // mouse move events come also for inactive windows
838 theListener.UpdateMousePosition (aPos, aButtons, aFlags, false);
839 theListener.ProcessInput();
845 ::GetRawInputData ((HRAWINPUT )theMsg.lParam, RID_INPUT, NULL, &aSize, sizeof(RAWINPUTHEADER));
846 NCollection_LocalArray<BYTE> aRawData (aSize);
847 if (aSize == 0 || ::GetRawInputData ((HRAWINPUT )theMsg.lParam, RID_INPUT, aRawData, &aSize, sizeof(RAWINPUTHEADER)) != aSize)
852 const RAWINPUT* aRawInput = (RAWINPUT* )(BYTE* )aRawData;
853 if (aRawInput->header.dwType != RIM_TYPEHID)
858 RID_DEVICE_INFO aDevInfo;
859 aDevInfo.cbSize = sizeof(RID_DEVICE_INFO);
860 UINT aDevInfoSize = sizeof(RID_DEVICE_INFO);
861 if (::GetRawInputDeviceInfoW (aRawInput->header.hDevice, RIDI_DEVICEINFO, &aDevInfo, &aDevInfoSize) != sizeof(RID_DEVICE_INFO)
862 || (aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_LOGITECH
863 && aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_3DCONNEXION))
868 WNT_HIDSpaceMouse aSpaceData (aDevInfo.hid.dwProductId, aRawInput->data.hid.bRawData, aRawInput->data.hid.dwSizeHid);
869 if (theListener.Update3dMouse (aSpaceData))
871 InvalidateContent (Handle(Aspect_DisplayConnection)());