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_Convert.hxx>
25 #include <Aspect_ScrollDelta.hxx>
26 #include <Aspect_WindowDefinitionError.hxx>
27 #include <Aspect_WindowError.hxx>
28 #include <Aspect_WindowInputListener.hxx>
29 #include <Message.hxx>
30 #include <NCollection_LocalArray.hxx>
31 #include <TCollection_ExtendedString.hxx>
32 #include <WNT_WClass.hxx>
33 #include <WNT_HIDSpaceMouse.hxx>
35 IMPLEMENT_STANDARD_RTTIEXT(WNT_Window, Aspect_Window)
37 // =======================================================================
38 // function : WNT_Window
40 // =======================================================================
41 WNT_Window::WNT_Window (const Standard_CString theTitle,
42 const Handle(WNT_WClass)& theClass,
43 const WNT_Dword& theStyle,
44 const Standard_Integer thePxLeft,
45 const Standard_Integer thePxTop,
46 const Standard_Integer thePxWidth,
47 const Standard_Integer thePxHeight,
48 const Quantity_NameOfColor theBackColor,
49 const Aspect_Handle theParent,
50 const Aspect_Handle theMenu,
51 const Standard_Address theClientStruct)
55 myHParentWindow (NULL),
58 myXRight (thePxLeft + thePxWidth),
59 myYBottom (thePxTop + thePxHeight),
60 myIsForeign (Standard_False)
62 if (thePxWidth <= 0 || thePxHeight <= 0)
64 throw Aspect_WindowDefinitionError("Coordinate(s) out of range");
67 DWORD aStyle = theStyle;
68 if (theParent && !(theStyle & WS_CHILD))
70 aStyle |= WS_CHILD | WS_CLIPSIBLINGS;
72 else if (!theParent && !(theStyle & WS_CLIPCHILDREN))
74 aStyle |= WS_CLIPCHILDREN;
77 // include decorations in the window dimensions to reproduce same behavior of Xw_Window
80 aRect.bottom = myYBottom;
82 aRect.right = myXRight;
83 AdjustWindowRect (&aRect, aStyle, theMenu != NULL ? TRUE : FALSE);
86 myXRight = aRect.right;
87 myYBottom = aRect.bottom;
89 const TCollection_ExtendedString aTitleW (theTitle);
90 const TCollection_ExtendedString aClassNameW (myWClass->Name());
91 myHWindow = CreateWindowW (aClassNameW.ToWideString(), aTitleW.ToWideString(),
94 (myXRight - myXLeft), (myYBottom - myYTop),
97 (HINSTANCE )myWClass->Instance(),
101 throw Aspect_WindowDefinitionError("Unable to create window");
104 myHParentWindow = theParent;
105 SetBackground (theBackColor);
108 // =======================================================================
109 // function : WNT_Window
111 // =======================================================================
112 WNT_Window::WNT_Window (const Aspect_Handle theHandle,
113 const Quantity_NameOfColor theBackColor)
114 : myHWindow (theHandle),
115 myHParentWindow (GetParent ((HWND )theHandle)),
120 myIsForeign (Standard_True)
122 SetBackground (theBackColor);
124 WINDOWPLACEMENT aPlace = {};
125 aPlace.length = sizeof(WINDOWPLACEMENT);
126 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
128 myXLeft = aPlace.rcNormalPosition.left;
129 myYTop = aPlace.rcNormalPosition.top;
130 myXRight = aPlace.rcNormalPosition.right;
131 myYBottom = aPlace.rcNormalPosition.bottom;
134 // =======================================================================
135 // function : ~WNT_Window
137 // =======================================================================
138 WNT_Window::~WNT_Window()
140 if (myHWindow == NULL
146 DestroyWindow ((HWND )myHWindow);
147 myIsForeign = Standard_False;
150 // =======================================================================
151 // function : SetCursor
153 // =======================================================================
154 void WNT_Window::SetCursor (const Aspect_Handle theCursor) const
156 ::SetClassLongPtrW ((HWND )myHWindow, GCLP_HCURSOR, (LONG_PTR )theCursor);
159 // =======================================================================
160 // function : IsMapped
162 // =======================================================================
163 Standard_Boolean WNT_Window::IsMapped() const
167 return Standard_True;
170 WINDOWPLACEMENT aPlace = {};
171 aPlace.length = sizeof(WINDOWPLACEMENT);
172 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
173 return !(aPlace.showCmd == SW_HIDE
174 || aPlace.showCmd == SW_MINIMIZE);
177 // =======================================================================
180 // =======================================================================
181 void WNT_Window::Map() const
189 // =======================================================================
192 // =======================================================================
193 void WNT_Window::Map (const Standard_Integer theMapMode) const
200 ::ShowWindow ((HWND )myHWindow, theMapMode);
201 ::UpdateWindow ((HWND )myHWindow);
204 // =======================================================================
207 // =======================================================================
208 void WNT_Window::Unmap() const
213 // =======================================================================
214 // function : DoResize
216 // =======================================================================
217 Aspect_TypeOfResize WNT_Window::DoResize()
221 return Aspect_TOR_UNKNOWN;
224 WINDOWPLACEMENT aPlace = {};
225 aPlace.length = sizeof(WINDOWPLACEMENT);
226 GetWindowPlacement ((HWND )myHWindow, &aPlace);
227 if (aPlace.showCmd == SW_SHOWMINIMIZED)
229 return Aspect_TOR_UNKNOWN;
233 if (Abs ((int )aPlace.rcNormalPosition.left - myXLeft ) > 2) { aMask |= 1; }
234 if (Abs ((int )aPlace.rcNormalPosition.right - myXRight ) > 2) { aMask |= 2; }
235 if (Abs ((int )aPlace.rcNormalPosition.top - myYTop ) > 2) { aMask |= 4; }
236 if (Abs ((int )aPlace.rcNormalPosition.bottom - myYBottom) > 2) { aMask |= 8; }
238 myXLeft = aPlace.rcNormalPosition.left;
239 myXRight = aPlace.rcNormalPosition.right;
240 myYTop = aPlace.rcNormalPosition.top;
241 myYBottom = aPlace.rcNormalPosition.bottom;
244 case 0: return Aspect_TOR_NO_BORDER;
245 case 1: return Aspect_TOR_LEFT_BORDER;
246 case 2: return Aspect_TOR_RIGHT_BORDER;
247 case 4: return Aspect_TOR_TOP_BORDER;
248 case 5: return Aspect_TOR_LEFT_AND_TOP_BORDER;
249 case 6: return Aspect_TOR_TOP_AND_RIGHT_BORDER;
250 case 8: return Aspect_TOR_BOTTOM_BORDER;
251 case 9: return Aspect_TOR_BOTTOM_AND_LEFT_BORDER;
252 case 10: return Aspect_TOR_RIGHT_AND_BOTTOM_BORDER;
254 return Aspect_TOR_UNKNOWN;
257 // =======================================================================
260 // =======================================================================
261 Standard_Real WNT_Window::Ratio() const
265 return Standard_Real(myXRight - myXLeft)/ Standard_Real(myYBottom - myYTop);
269 GetClientRect ((HWND )myHWindow, &aRect);
270 return Standard_Real(aRect.right - aRect.left) / Standard_Real(aRect.bottom - aRect.top);
273 // =======================================================================
274 // function : Position
276 // =======================================================================
277 void WNT_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
278 Standard_Integer& theX2, Standard_Integer& theY2) const
290 ::GetClientRect ((HWND )myHWindow, &aRect);
292 POINT aPntLeft, aPntRight;
293 aPntLeft.x = aPntLeft.y = 0;
294 ::ClientToScreen ((HWND )myHWindow, &aPntLeft);
295 aPntRight.x = aRect.right;
296 aPntRight.y = aRect.bottom;
297 ::ClientToScreen ((HWND )myHWindow, &aPntRight);
299 if (myHParentWindow != NULL)
301 ::ScreenToClient ((HWND )myHParentWindow, &aPntLeft);
302 ::ScreenToClient ((HWND )myHParentWindow, &aPntRight);
311 // =======================================================================
314 // =======================================================================
315 void WNT_Window::Size (Standard_Integer& theWidth,
316 Standard_Integer& theHeight) const
320 theWidth = myXRight - myXLeft;
321 theHeight = myYBottom - myYTop;
326 ::GetClientRect ((HWND )myHWindow, &aRect);
327 theWidth = aRect.right;
328 theHeight = aRect.bottom;
331 // =======================================================================
334 // =======================================================================
335 void WNT_Window::SetPos (const Standard_Integer theX, const Standard_Integer theY,
336 const Standard_Integer theX1, const Standard_Integer theY1)
344 // =======================================================================
345 // function : SetTitle
347 // =======================================================================
348 void WNT_Window::SetTitle (const TCollection_AsciiString& theTitle)
350 const TCollection_ExtendedString aTitleW (theTitle);
351 SetWindowTextW ((HWND )myHWindow, aTitleW.ToWideString());
354 // =======================================================================
355 // function : InvalidateContent
357 // =======================================================================
358 void WNT_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& )
360 if (myHWindow != NULL)
362 ::InvalidateRect ((HWND )myHWindow, NULL, TRUE);
366 // =======================================================================
367 // function : VirtualKeyFromNative
369 // =======================================================================
370 Aspect_VKey WNT_Window::VirtualKeyFromNative (Standard_Integer theKey)
372 if (theKey >= Standard_Integer('0')
373 && theKey <= Standard_Integer('9'))
375 return Aspect_VKey((theKey - Standard_Integer('0')) + Aspect_VKey_0);
377 if (theKey >= Standard_Integer('A')
378 && theKey <= Standard_Integer('Z'))
380 // main latin alphabet keys
381 return Aspect_VKey((theKey - Standard_Integer('A')) + Aspect_VKey_A);
387 if (theKey <= VK_F12)
389 return Aspect_VKey((theKey - VK_F1) + Aspect_VKey_F1);
391 return Aspect_VKey_UNKNOWN;
393 if (theKey >= VK_NUMPAD0
394 && theKey <= VK_NUMPAD9)
397 return Aspect_VKey((theKey - VK_NUMPAD0) + Aspect_VKey_Numpad0);
408 return Aspect_VKey_UNKNOWN;
410 return Aspect_VKey_Backspace;
412 return Aspect_VKey_Tab;
414 return Aspect_VKey_UNKNOWN;
416 return Aspect_VKey_Enter;
418 return Aspect_VKey_Shift;
420 return Aspect_VKey_Control;
422 return Aspect_VKey_Alt; //Aspect_VKey_Menu;
425 return Aspect_VKey_UNKNOWN;
427 return Aspect_VKey_Escape;
432 return Aspect_VKey_UNKNOWN;
434 return Aspect_VKey_Space;
436 return Aspect_VKey_PageUp;
438 return Aspect_VKey_PageDown;
440 return Aspect_VKey_End;
442 return Aspect_VKey_Home;
444 return Aspect_VKey_Left;
446 return Aspect_VKey_Up;
448 return Aspect_VKey_Down;
450 return Aspect_VKey_Right;
455 return Aspect_VKey_UNKNOWN;
457 return Aspect_VKey_UNKNOWN; // Aspect_VKey_Insert
459 return Aspect_VKey_Delete;
465 return Aspect_VKey_UNKNOWN;
467 return Aspect_VKey_NumpadMultiply;
469 return Aspect_VKey_NumpadAdd;
472 return Aspect_VKey_UNKNOWN;
474 return Aspect_VKey_NumpadSubtract;
476 return Aspect_VKey_NumpadDivide;
478 return Aspect_VKey_Numlock;
480 return Aspect_VKey_Scroll;
487 return Aspect_VKey_UNKNOWN;
488 case VK_BROWSER_BACK:
489 return Aspect_VKey_BrowserBack;
490 case VK_BROWSER_FORWARD:
491 return Aspect_VKey_BrowserForward;
492 case VK_BROWSER_REFRESH:
493 return Aspect_VKey_BrowserRefresh;
494 case VK_BROWSER_STOP:
495 return Aspect_VKey_BrowserStop;
496 case VK_BROWSER_SEARCH:
497 return Aspect_VKey_BrowserSearch;
498 case VK_BROWSER_FAVORITES:
499 return Aspect_VKey_BrowserFavorites;
500 case VK_BROWSER_HOME:
501 return Aspect_VKey_BrowserHome;
503 return Aspect_VKey_VolumeMute;
505 return Aspect_VKey_VolumeDown;
507 return Aspect_VKey_VolumeUp;
508 case VK_MEDIA_NEXT_TRACK:
509 return Aspect_VKey_MediaNextTrack;
510 case VK_MEDIA_PREV_TRACK:
511 return Aspect_VKey_MediaPreviousTrack;
513 return Aspect_VKey_MediaStop;
514 case VK_MEDIA_PLAY_PAUSE:
515 return Aspect_VKey_MediaPlayPause;
517 return Aspect_VKey_Semicolon;
519 return Aspect_VKey_Plus;
521 return Aspect_VKey_Comma;
523 return Aspect_VKey_Minus;
525 return Aspect_VKey_Period;
527 return Aspect_VKey_Slash;
529 return Aspect_VKey_Tilde;
531 return Aspect_VKey_BracketLeft;
533 return Aspect_VKey_Backslash;
535 return Aspect_VKey_BracketRight;
537 return Aspect_VKey_Apostrophe;
539 return Aspect_VKey_UNKNOWN;
542 // =======================================================================
543 // function : MouseKeyFlagsFromEvent
545 // =======================================================================
546 Aspect_VKeyFlags WNT_Window::MouseKeyFlagsFromEvent (WPARAM theKeys)
548 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
549 if ((theKeys & MK_CONTROL) != 0)
551 aFlags |= Aspect_VKeyFlags_CTRL;
553 if ((theKeys & MK_SHIFT) != 0)
555 aFlags |= Aspect_VKeyFlags_SHIFT;
557 if (GetKeyState (VK_MENU) < 0)
559 aFlags |= Aspect_VKeyFlags_ALT;
564 // =======================================================================
565 // function : MouseKeyFlagsAsync
567 // =======================================================================
568 Aspect_VKeyFlags WNT_Window::MouseKeyFlagsAsync()
570 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
571 if ((GetAsyncKeyState (VK_CONTROL) & 0x8000) != 0)
573 aFlags |= Aspect_VKeyFlags_CTRL;
575 if ((GetAsyncKeyState (VK_SHIFT) & 0x8000) != 0)
577 aFlags |= Aspect_VKeyFlags_SHIFT;
579 if ((GetAsyncKeyState (VK_MENU) & 0x8000) != 0)
581 aFlags |= Aspect_VKeyFlags_ALT;
586 // =======================================================================
587 // function : MouseButtonsFromEvent
589 // =======================================================================
590 Aspect_VKeyMouse WNT_Window::MouseButtonsFromEvent (WPARAM theKeys)
592 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
593 if ((theKeys & MK_LBUTTON) != 0)
595 aButtons |= Aspect_VKeyMouse_LeftButton;
597 if ((theKeys & MK_MBUTTON) != 0)
599 aButtons |= Aspect_VKeyMouse_MiddleButton;
601 if ((theKeys & MK_RBUTTON) != 0)
603 aButtons |= Aspect_VKeyMouse_RightButton;
608 // =======================================================================
609 // function : MouseButtonsAsync
611 // =======================================================================
612 Aspect_VKeyMouse WNT_Window::MouseButtonsAsync()
614 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
615 const bool isSwapped = GetSystemMetrics (SM_SWAPBUTTON) != 0;
617 if ((GetAsyncKeyState (!isSwapped ? VK_LBUTTON : VK_RBUTTON) & 0x8000) != 0)
619 aButtons |= Aspect_VKeyMouse_LeftButton;
621 if ((GetAsyncKeyState (VK_MBUTTON) & 0x8000) != 0)
623 aButtons |= Aspect_VKeyMouse_MiddleButton;
625 if ((GetAsyncKeyState (!isSwapped ? VK_RBUTTON : VK_LBUTTON) & 0x8000) != 0)
627 aButtons |= Aspect_VKeyMouse_RightButton;
632 // =======================================================================
633 // function : RegisterRawInputDevices
635 // =======================================================================
636 int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask)
639 || myHWindow == NULL)
645 enum HidUsagePage { THE_HID_USAGE_PAGE_GENERIC = 0x01 }; // HID_USAGE_PAGE_GENERIC
648 THE_HID_USAGE_GENERIC_MOUSE = 0x02, // HID_USAGE_GENERIC_MOUSE
649 THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER = 0x08, // HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
653 RAWINPUTDEVICE aRawInDevList[2];
654 if ((theRawDeviceMask & RawInputMask_Mouse) != 0)
657 RAWINPUTDEVICE& aRawMouse = aRawInDevList[aNbDevices++];
658 aRawMouse.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
659 aRawMouse.usUsage = THE_HID_USAGE_GENERIC_MOUSE;
660 aRawMouse.dwFlags = RIDEV_INPUTSINK;
661 aRawMouse.hwndTarget = (HWND )myHWindow;
663 if ((theRawDeviceMask & RawInputMask_SpaceMouse) != 0)
666 RAWINPUTDEVICE& aRawSpace = aRawInDevList[aNbDevices++];
667 aRawSpace.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
668 aRawSpace.usUsage = THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER;
669 aRawSpace.dwFlags = 0; // RIDEV_DEVNOTIFY
670 aRawSpace.hwndTarget = (HWND )myHWindow;
673 for (int aTryIter = aNbDevices; aTryIter > 0; --aTryIter)
675 if (::RegisterRawInputDevices (aRawInDevList, aTryIter, sizeof(aRawInDevList[0])))
680 Message::SendTrace (aRawInDevList[aTryIter - 1].usUsage == THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
681 ? "Warning: RegisterRawInputDevices() failed to register RAW multi-axis controller input"
682 : "Warning: RegisterRawInputDevices() failed to register RAW mouse input");
687 // =======================================================================
688 // function : ProcessMessage
690 // =======================================================================
691 bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener,
694 switch (theMsg.message)
698 if (theMsg.hwnd == (HWND )myHWindow)
700 theListener.ProcessClose();
707 if (theMsg.hwnd == (HWND )myHWindow)
709 theListener.ProcessFocus (LOWORD(theMsg.wParam) == WA_CLICKACTIVE
710 || LOWORD(theMsg.wParam) == WA_ACTIVE);
718 BeginPaint(theMsg.hwnd, &aPaint);
719 EndPaint (theMsg.hwnd, &aPaint);
720 theListener.ProcessExpose();
728 theListener.ProcessConfigure (theMsg.message == WM_SIZE);
734 const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )theMsg.wParam);
735 if (aVKey != Aspect_VKey_UNKNOWN)
737 const double aTimeStamp = theListener.EventTime();
738 if (theMsg.message == WM_KEYDOWN)
740 theListener.KeyDown (aVKey, aTimeStamp);
744 theListener.KeyUp (aVKey, aTimeStamp);
746 theListener.ProcessInput();
757 const Graphic3d_Vec2i aPos (LOWORD(theMsg.lParam), HIWORD(theMsg.lParam));
758 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theMsg.wParam);
759 Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
760 switch (theMsg.message)
764 aButton = Aspect_VKeyMouse_LeftButton;
768 aButton = Aspect_VKeyMouse_MiddleButton;
772 aButton = Aspect_VKeyMouse_RightButton;
775 if (theMsg.message == WM_LBUTTONDOWN
776 || theMsg.message == WM_MBUTTONDOWN
777 || theMsg.message == WM_RBUTTONDOWN)
779 SetFocus (theMsg.hwnd);
780 SetCapture(theMsg.hwnd);
781 theListener.PressMouseButton (aPos, aButton, aFlags, false);
786 theListener.ReleaseMouseButton (aPos, aButton, aFlags, false);
788 theListener.ProcessInput();
793 const int aDelta = GET_WHEEL_DELTA_WPARAM (theMsg.wParam);
794 const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
795 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theMsg.wParam);
796 Graphic3d_Vec2i aPos (int(short(LOWORD(theMsg.lParam))), int(short(HIWORD(theMsg.lParam))));
797 POINT aCursorPnt = { aPos.x(), aPos.y() };
798 if (ScreenToClient (theMsg.hwnd, &aCursorPnt))
800 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
803 if (theMsg.hwnd != (HWND )myHWindow)
808 theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
809 theListener.ProcessInput();
814 Graphic3d_Vec2i aPos (LOWORD(theMsg.lParam), HIWORD(theMsg.lParam));
815 Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (theMsg.wParam);
816 Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(theMsg.wParam);
818 // don't make a slide-show from input events - fetch the actual mouse cursor position
820 aCursor.cbSize = sizeof(aCursor);
821 if (::GetCursorInfo (&aCursor) != FALSE)
823 POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
824 if (ScreenToClient (theMsg.hwnd, &aCursorPnt))
826 // as we override mouse position, we need overriding also mouse state
827 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
828 aButtons = WNT_Window::MouseButtonsAsync();
829 aFlags = WNT_Window::MouseKeyFlagsAsync();
833 if (theMsg.hwnd != (HWND )myHWindow)
835 // mouse move events come also for inactive windows
839 theListener.UpdateMousePosition (aPos, aButtons, aFlags, false);
840 theListener.ProcessInput();
846 ::GetRawInputData ((HRAWINPUT )theMsg.lParam, RID_INPUT, NULL, &aSize, sizeof(RAWINPUTHEADER));
847 NCollection_LocalArray<BYTE> aRawData (aSize);
848 if (aSize == 0 || ::GetRawInputData ((HRAWINPUT )theMsg.lParam, RID_INPUT, aRawData, &aSize, sizeof(RAWINPUTHEADER)) != aSize)
853 const RAWINPUT* aRawInput = (RAWINPUT* )(BYTE* )aRawData;
854 if (aRawInput->header.dwType != RIM_TYPEHID)
859 RID_DEVICE_INFO aDevInfo;
860 aDevInfo.cbSize = sizeof(RID_DEVICE_INFO);
861 UINT aDevInfoSize = sizeof(RID_DEVICE_INFO);
862 if (::GetRawInputDeviceInfoW (aRawInput->header.hDevice, RIDI_DEVICEINFO, &aDevInfo, &aDevInfoSize) != sizeof(RID_DEVICE_INFO)
863 || (aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_LOGITECH
864 && aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_3DCONNEXION))
869 WNT_HIDSpaceMouse aSpaceData (aDevInfo.hid.dwProductId, aRawInput->data.hid.bRawData, aRawInput->data.hid.dwSizeHid);
870 if (theListener.Update3dMouse (aSpaceData))
872 InvalidateContent (Handle(Aspect_DisplayConnection)());