0032306: Draw Harness, ViewerTest - move window message processing to TKService
[occt.git] / src / WNT / WNT_Window.cxx
CommitLineData
b311480e 1// Copyright (c) 1998-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
cf4bee7c 15#if defined(_WIN32)
16 // include windows.h first to have all definitions available
17 #include <windows.h>
18#endif
7fd59977 19
1ce0716b 20#include <WNT_Window.hxx>
21
22#if defined(_WIN32) && !defined(OCCT_UWP)
7fd59977 23
7fd59977 24#include <Aspect_Convert.hxx>
e8e157df 25#include <Aspect_ScrollDelta.hxx>
42cf5bc1 26#include <Aspect_WindowDefinitionError.hxx>
27#include <Aspect_WindowError.hxx>
e8e157df 28#include <Aspect_WindowInputListener.hxx>
d6fbb2ab 29#include <Message.hxx>
e8e157df 30#include <NCollection_LocalArray.hxx>
ad03c234 31#include <TCollection_ExtendedString.hxx>
42cf5bc1 32#include <WNT_WClass.hxx>
e8e157df 33#include <WNT_HIDSpaceMouse.hxx>
7fd59977 34
ad03c234 35IMPLEMENT_STANDARD_RTTIEXT(WNT_Window, Aspect_Window)
f5f4ebd0 36
eaf5c5e0 37// =======================================================================
38// function : WNT_Window
39// purpose :
40// =======================================================================
dc3fe572 41WNT_Window::WNT_Window (const Standard_CString theTitle,
7fd59977 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)
dc3fe572 52: Aspect_Window(),
eaf5c5e0 53 myWClass (theClass),
e8e157df 54 myHWindow (NULL),
55 myHParentWindow (NULL),
56 myXLeft (thePxLeft),
57 myYTop (thePxTop),
58 myXRight (thePxLeft + thePxWidth),
59 myYBottom (thePxTop + thePxHeight),
eaf5c5e0 60 myIsForeign (Standard_False)
7fd59977 61{
7fd59977 62 if (thePxWidth <= 0 || thePxHeight <= 0)
63 {
9775fa61 64 throw Aspect_WindowDefinitionError("Coordinate(s) out of range");
7fd59977 65 }
66
ad03c234 67 DWORD aStyle = theStyle;
7fd59977 68 if (theParent && !(theStyle & WS_CHILD))
69 {
ad03c234 70 aStyle |= WS_CHILD | WS_CLIPSIBLINGS;
7fd59977 71 }
72 else if (!theParent && !(theStyle & WS_CLIPCHILDREN))
73 {
ad03c234 74 aStyle |= WS_CLIPCHILDREN;
7fd59977 75 }
76
ad03c234 77 // include decorations in the window dimensions to reproduce same behavior of Xw_Window
7fe83417 78 RECT aRect;
e8e157df 79 aRect.top = myYTop;
80 aRect.bottom = myYBottom;
81 aRect.left = myXLeft;
82 aRect.right = myXRight;
ad03c234 83 AdjustWindowRect (&aRect, aStyle, theMenu != NULL ? TRUE : FALSE);
e8e157df 84 myXLeft = aRect.left;
85 myYTop = aRect.top;
86 myXRight = aRect.right;
87 myYBottom = aRect.bottom;
7fd59977 88
ad03c234 89 const TCollection_ExtendedString aTitleW (theTitle);
90 const TCollection_ExtendedString aClassNameW (myWClass->Name());
91 myHWindow = CreateWindowW (aClassNameW.ToWideString(), aTitleW.ToWideString(),
92 aStyle,
e8e157df 93 myXLeft, myYTop,
94 (myXRight - myXLeft), (myYBottom - myYTop),
ad03c234 95 (HWND )theParent,
96 (HMENU )theMenu,
97 (HINSTANCE )myWClass->Instance(),
98 theClientStruct);
7fd59977 99 if (!myHWindow)
100 {
9775fa61 101 throw Aspect_WindowDefinitionError("Unable to create window");
7fd59977 102 }
103
7fd59977 104 myHParentWindow = theParent;
7fd59977 105 SetBackground (theBackColor);
eaf5c5e0 106}
dc3fe572 107
eaf5c5e0 108// =======================================================================
109// function : WNT_Window
110// purpose :
111// =======================================================================
112WNT_Window::WNT_Window (const Aspect_Handle theHandle,
113 const Quantity_NameOfColor theBackColor)
e8e157df 114: myHWindow (theHandle),
115 myHParentWindow (GetParent ((HWND )theHandle)),
116 myXLeft (0),
117 myYTop (0),
118 myXRight (0),
119 myYBottom (0),
120 myIsForeign (Standard_True)
eaf5c5e0 121{
eaf5c5e0 122 SetBackground (theBackColor);
7fd59977 123
e8e157df 124 WINDOWPLACEMENT aPlace = {};
125 aPlace.length = sizeof(WINDOWPLACEMENT);
eaf5c5e0 126 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
127
e8e157df 128 myXLeft = aPlace.rcNormalPosition.left;
129 myYTop = aPlace.rcNormalPosition.top;
130 myXRight = aPlace.rcNormalPosition.right;
131 myYBottom = aPlace.rcNormalPosition.bottom;
7fd59977 132}
133
eaf5c5e0 134// =======================================================================
e6f550da 135// function : ~WNT_Window
eaf5c5e0 136// purpose :
137// =======================================================================
e6f550da 138WNT_Window::~WNT_Window()
dc3fe572 139{
eaf5c5e0 140 if (myHWindow == NULL
141 || myIsForeign)
142 {
143 return;
144 }
7fd59977 145
eaf5c5e0 146 DestroyWindow ((HWND )myHWindow);
147 myIsForeign = Standard_False;
148}
7fd59977 149
eaf5c5e0 150// =======================================================================
151// function : SetCursor
152// purpose :
153// =======================================================================
154void WNT_Window::SetCursor (const Aspect_Handle theCursor) const
155{
ad03c234 156 ::SetClassLongPtrW ((HWND )myHWindow, GCLP_HCURSOR, (LONG_PTR )theCursor);
eaf5c5e0 157}
7fd59977 158
eaf5c5e0 159// =======================================================================
160// function : IsMapped
161// purpose :
162// =======================================================================
163Standard_Boolean WNT_Window::IsMapped() const
dc3fe572 164{
eaf5c5e0 165 if (IsVirtual())
7fd59977 166 {
587630c5 167 return Standard_True;
7fd59977 168 }
169
e8e157df 170 WINDOWPLACEMENT aPlace = {};
171 aPlace.length = sizeof(WINDOWPLACEMENT);
eaf5c5e0 172 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
173 return !(aPlace.showCmd == SW_HIDE
174 || aPlace.showCmd == SW_MINIMIZE);
175}
dc3fe572 176
eaf5c5e0 177// =======================================================================
178// function : Map
179// purpose :
180// =======================================================================
181void WNT_Window::Map() const
182{
183 if (!IsVirtual())
184 {
185 Map (SW_SHOW);
7fd59977 186 }
eaf5c5e0 187}
188
189// =======================================================================
190// function : Map
191// purpose :
192// =======================================================================
193void WNT_Window::Map (const Standard_Integer theMapMode) const
194{
195 if (IsVirtual())
196 {
7fd59977 197 return;
198 }
7fd59977 199
eaf5c5e0 200 ::ShowWindow ((HWND )myHWindow, theMapMode);
201 ::UpdateWindow ((HWND )myHWindow);
202}
7fd59977 203
eaf5c5e0 204// =======================================================================
205// function : Unmap
206// purpose :
207// =======================================================================
208void WNT_Window::Unmap() const
209{
210 Map (SW_HIDE);
211}
dc3fe572 212
eaf5c5e0 213// =======================================================================
214// function : DoResize
215// purpose :
216// =======================================================================
1a5007a9 217Aspect_TypeOfResize WNT_Window::DoResize()
dc3fe572 218{
62e1beed 219 if (IsVirtual())
220 {
221 return Aspect_TOR_UNKNOWN;
222 }
223
e8e157df 224 WINDOWPLACEMENT aPlace = {};
225 aPlace.length = sizeof(WINDOWPLACEMENT);
226 GetWindowPlacement ((HWND )myHWindow, &aPlace);
227 if (aPlace.showCmd == SW_SHOWMINIMIZED)
dc3fe572 228 {
e8e157df 229 return Aspect_TOR_UNKNOWN;
230 }
dc3fe572 231
e8e157df 232 int aMask = 0;
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; }
237
238 myXLeft = aPlace.rcNormalPosition.left;
239 myXRight = aPlace.rcNormalPosition.right;
240 myYTop = aPlace.rcNormalPosition.top;
241 myYBottom = aPlace.rcNormalPosition.bottom;
242 switch (aMask)
243 {
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;
253 }
254 return Aspect_TOR_UNKNOWN;
7fd59977 255}
256
eaf5c5e0 257// =======================================================================
258// function : Ratio
259// purpose :
260// =======================================================================
ee2be2a8 261Standard_Real WNT_Window::Ratio() const
dc3fe572 262{
62e1beed 263 if (IsVirtual())
264 {
e8e157df 265 return Standard_Real(myXRight - myXLeft)/ Standard_Real(myYBottom - myYTop);
62e1beed 266 }
267
e8e157df 268 RECT aRect = {};
62e1beed 269 GetClientRect ((HWND )myHWindow, &aRect);
ee2be2a8 270 return Standard_Real(aRect.right - aRect.left) / Standard_Real(aRect.bottom - aRect.top);
eaf5c5e0 271}
7fd59977 272
eaf5c5e0 273// =======================================================================
274// function : Position
275// purpose :
276// =======================================================================
277void WNT_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
278 Standard_Integer& theX2, Standard_Integer& theY2) const
279{
62e1beed 280 if (IsVirtual())
281 {
e8e157df 282 theX1 = myXLeft;
283 theX2 = myXRight;
284 theY1 = myYTop;
285 theY2 = myYBottom;
62e1beed 286 return;
287 }
288
e8e157df 289 RECT aRect = {};
eaf5c5e0 290 ::GetClientRect ((HWND )myHWindow, &aRect);
7fd59977 291
eaf5c5e0 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);
7fd59977 298
eaf5c5e0 299 if (myHParentWindow != NULL)
7fd59977 300 {
eaf5c5e0 301 ::ScreenToClient ((HWND )myHParentWindow, &aPntLeft);
302 ::ScreenToClient ((HWND )myHParentWindow, &aPntRight);
7fd59977 303 }
304
eaf5c5e0 305 theX1 = aPntLeft.x;
306 theX2 = aPntRight.x;
307 theY1 = aPntLeft.y;
308 theY2 = aPntRight.y;
309}
7fd59977 310
eaf5c5e0 311// =======================================================================
312// function : Size
313// purpose :
314// =======================================================================
315void WNT_Window::Size (Standard_Integer& theWidth,
316 Standard_Integer& theHeight) const
317{
62e1beed 318 if (IsVirtual())
319 {
e8e157df 320 theWidth = myXRight - myXLeft;
321 theHeight = myYBottom - myYTop;
62e1beed 322 return;
323 }
324
e8e157df 325 RECT aRect = {};
eaf5c5e0 326 ::GetClientRect ((HWND )myHWindow, &aRect);
327 theWidth = aRect.right;
328 theHeight = aRect.bottom;
329}
7fd59977 330
eaf5c5e0 331// =======================================================================
332// function : SetPos
333// purpose :
334// =======================================================================
335void WNT_Window::SetPos (const Standard_Integer theX, const Standard_Integer theY,
336 const Standard_Integer theX1, const Standard_Integer theY1)
337{
e8e157df 338 myXLeft = theX;
339 myYTop = theY;
340 myXRight = theX1;
341 myYBottom = theY1;
eaf5c5e0 342}
1ce0716b 343
49582f9d 344// =======================================================================
345// function : SetTitle
346// purpose :
347// =======================================================================
348void WNT_Window::SetTitle (const TCollection_AsciiString& theTitle)
349{
350 const TCollection_ExtendedString aTitleW (theTitle);
351 SetWindowTextW ((HWND )myHWindow, aTitleW.ToWideString());
352}
353
8693dfd0 354// =======================================================================
355// function : InvalidateContent
356// purpose :
357// =======================================================================
358void WNT_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& )
359{
360 if (myHWindow != NULL)
361 {
362 ::InvalidateRect ((HWND )myHWindow, NULL, TRUE);
363 }
364}
365
49582f9d 366// =======================================================================
367// function : VirtualKeyFromNative
368// purpose :
369// =======================================================================
370Aspect_VKey WNT_Window::VirtualKeyFromNative (Standard_Integer theKey)
371{
372 if (theKey >= Standard_Integer('0')
373 && theKey <= Standard_Integer('9'))
374 {
375 return Aspect_VKey((theKey - Standard_Integer('0')) + Aspect_VKey_0);
376 }
377 if (theKey >= Standard_Integer('A')
378 && theKey <= Standard_Integer('Z'))
379 {
380 // main latin alphabet keys
381 return Aspect_VKey((theKey - Standard_Integer('A')) + Aspect_VKey_A);
382 }
383 if (theKey >= VK_F1
384 && theKey <= VK_F24)
385 {
386 // special keys
387 if (theKey <= VK_F12)
388 {
389 return Aspect_VKey((theKey - VK_F1) + Aspect_VKey_F1);
390 }
391 return Aspect_VKey_UNKNOWN;
392 }
393 if (theKey >= VK_NUMPAD0
394 && theKey <= VK_NUMPAD9)
395 {
396 // numpad keys
397 return Aspect_VKey((theKey - VK_NUMPAD0) + Aspect_VKey_Numpad0);
398 }
399
400 switch (theKey)
401 {
402 case VK_LBUTTON:
403 case VK_RBUTTON:
404 case VK_CANCEL:
405 case VK_MBUTTON:
406 case VK_XBUTTON1:
407 case VK_XBUTTON2:
408 return Aspect_VKey_UNKNOWN;
409 case VK_BACK:
410 return Aspect_VKey_Backspace;
411 case VK_TAB:
412 return Aspect_VKey_Tab;
413 case VK_CLEAR:
414 return Aspect_VKey_UNKNOWN;
415 case VK_RETURN:
416 return Aspect_VKey_Enter;
417 case VK_SHIFT:
418 return Aspect_VKey_Shift;
419 case VK_CONTROL:
420 return Aspect_VKey_Control;
421 case VK_MENU:
422 return Aspect_VKey_Alt; //Aspect_VKey_Menu;
423 case VK_PAUSE:
424 case VK_CAPITAL:
425 return Aspect_VKey_UNKNOWN;
426 case VK_ESCAPE:
427 return Aspect_VKey_Escape;
428 case VK_CONVERT:
429 case VK_NONCONVERT:
430 case VK_ACCEPT:
431 case VK_MODECHANGE:
432 return Aspect_VKey_UNKNOWN;
433 case VK_SPACE:
434 return Aspect_VKey_Space;
435 case VK_PRIOR:
436 return Aspect_VKey_PageUp;
437 case VK_NEXT:
438 return Aspect_VKey_PageDown;
439 case VK_END:
440 return Aspect_VKey_End;
441 case VK_HOME:
442 return Aspect_VKey_Home;
443 case VK_LEFT:
444 return Aspect_VKey_Left;
445 case VK_UP:
446 return Aspect_VKey_Up;
447 case VK_DOWN:
448 return Aspect_VKey_Down;
449 case VK_RIGHT:
450 return Aspect_VKey_Right;
451 case VK_SELECT:
452 case VK_PRINT:
453 case VK_EXECUTE:
454 case VK_SNAPSHOT:
455 return Aspect_VKey_UNKNOWN;
456 case VK_INSERT:
457 return Aspect_VKey_UNKNOWN; // Aspect_VKey_Insert
458 case VK_DELETE:
459 return Aspect_VKey_Delete;
460 case VK_HELP:
461 case VK_LWIN:
462 case VK_RWIN:
463 case VK_APPS:
464 case VK_SLEEP:
465 return Aspect_VKey_UNKNOWN;
466 case VK_MULTIPLY:
467 return Aspect_VKey_NumpadMultiply;
468 case VK_ADD:
469 return Aspect_VKey_NumpadAdd;
470 case VK_SEPARATOR:
471 case VK_DECIMAL:
472 return Aspect_VKey_UNKNOWN;
473 case VK_SUBTRACT:
474 return Aspect_VKey_NumpadSubtract;
475 case VK_DIVIDE:
476 return Aspect_VKey_NumpadDivide;
477 case VK_NUMLOCK:
478 return Aspect_VKey_Numlock;
479 case VK_SCROLL:
480 return Aspect_VKey_Scroll;
481 case VK_LSHIFT:
482 case VK_RSHIFT:
483 case VK_LCONTROL:
484 case VK_RCONTROL:
485 case VK_LMENU:
486 case VK_RMENU:
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;
502 case VK_VOLUME_MUTE:
503 return Aspect_VKey_VolumeMute;
504 case VK_VOLUME_DOWN:
505 return Aspect_VKey_VolumeDown;
506 case VK_VOLUME_UP:
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;
512 case VK_MEDIA_STOP:
513 return Aspect_VKey_MediaStop;
514 case VK_MEDIA_PLAY_PAUSE:
515 return Aspect_VKey_MediaPlayPause;
516 case VK_OEM_1:
517 return Aspect_VKey_Semicolon;
518 case VK_OEM_PLUS:
519 return Aspect_VKey_Plus;
520 case VK_OEM_COMMA:
521 return Aspect_VKey_Comma;
522 case VK_OEM_MINUS:
523 return Aspect_VKey_Minus;
524 case VK_OEM_PERIOD:
525 return Aspect_VKey_Period;
526 case VK_OEM_2:
527 return Aspect_VKey_Slash;
528 case VK_OEM_3:
529 return Aspect_VKey_Tilde;
530 case VK_OEM_4:
531 return Aspect_VKey_BracketLeft;
532 case VK_OEM_5:
533 return Aspect_VKey_Backslash;
534 case VK_OEM_6:
535 return Aspect_VKey_BracketRight;
536 case VK_OEM_7:
537 return Aspect_VKey_Apostrophe;
538 }
539 return Aspect_VKey_UNKNOWN;
540}
541
542// =======================================================================
543// function : MouseKeyFlagsFromEvent
544// purpose :
545// =======================================================================
546Aspect_VKeyFlags WNT_Window::MouseKeyFlagsFromEvent (WPARAM theKeys)
547{
548 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
549 if ((theKeys & MK_CONTROL) != 0)
550 {
551 aFlags |= Aspect_VKeyFlags_CTRL;
552 }
553 if ((theKeys & MK_SHIFT) != 0)
554 {
555 aFlags |= Aspect_VKeyFlags_SHIFT;
556 }
557 if (GetKeyState (VK_MENU) < 0)
558 {
559 aFlags |= Aspect_VKeyFlags_ALT;
560 }
561 return aFlags;
562}
563
564// =======================================================================
565// function : MouseKeyFlagsAsync
566// purpose :
567// =======================================================================
568Aspect_VKeyFlags WNT_Window::MouseKeyFlagsAsync()
569{
570 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
571 if ((GetAsyncKeyState (VK_CONTROL) & 0x8000) != 0)
572 {
573 aFlags |= Aspect_VKeyFlags_CTRL;
574 }
575 if ((GetAsyncKeyState (VK_SHIFT) & 0x8000) != 0)
576 {
577 aFlags |= Aspect_VKeyFlags_SHIFT;
578 }
579 if ((GetAsyncKeyState (VK_MENU) & 0x8000) != 0)
580 {
581 aFlags |= Aspect_VKeyFlags_ALT;
582 }
583 return aFlags;
584}
585
586// =======================================================================
587// function : MouseButtonsFromEvent
588// purpose :
589// =======================================================================
590Aspect_VKeyMouse WNT_Window::MouseButtonsFromEvent (WPARAM theKeys)
591{
592 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
593 if ((theKeys & MK_LBUTTON) != 0)
594 {
595 aButtons |= Aspect_VKeyMouse_LeftButton;
596 }
597 if ((theKeys & MK_MBUTTON) != 0)
598 {
599 aButtons |= Aspect_VKeyMouse_MiddleButton;
600 }
601 if ((theKeys & MK_RBUTTON) != 0)
602 {
603 aButtons |= Aspect_VKeyMouse_RightButton;
604 }
605 return aButtons;
606}
607
608// =======================================================================
609// function : MouseButtonsAsync
610// purpose :
611// =======================================================================
612Aspect_VKeyMouse WNT_Window::MouseButtonsAsync()
613{
614 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
615 const bool isSwapped = GetSystemMetrics (SM_SWAPBUTTON) != 0;
616
617 if ((GetAsyncKeyState (!isSwapped ? VK_LBUTTON : VK_RBUTTON) & 0x8000) != 0)
618 {
619 aButtons |= Aspect_VKeyMouse_LeftButton;
620 }
621 if ((GetAsyncKeyState (VK_MBUTTON) & 0x8000) != 0)
622 {
623 aButtons |= Aspect_VKeyMouse_MiddleButton;
624 }
625 if ((GetAsyncKeyState (!isSwapped ? VK_RBUTTON : VK_LBUTTON) & 0x8000) != 0)
626 {
627 aButtons |= Aspect_VKeyMouse_RightButton;
628 }
629 return aButtons;
630}
631
d6fbb2ab 632// =======================================================================
633// function : RegisterRawInputDevices
634// purpose :
635// =======================================================================
636int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask)
637{
638 if (IsVirtual()
639 || myHWindow == NULL)
640 {
641 return 0;
642 }
643
644 // hidusage.h
645 enum HidUsagePage { THE_HID_USAGE_PAGE_GENERIC = 0x01 }; // HID_USAGE_PAGE_GENERIC
646 enum HidUsage
647 {
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
650 };
651
652 int aNbDevices = 0;
653 RAWINPUTDEVICE aRawInDevList[2];
654 if ((theRawDeviceMask & RawInputMask_Mouse) != 0)
655 {
656 // mouse
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;
662 }
663 if ((theRawDeviceMask & RawInputMask_SpaceMouse) != 0)
664 {
665 // space mouse
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;
671 }
672
673 for (int aTryIter = aNbDevices; aTryIter > 0; --aTryIter)
674 {
675 if (::RegisterRawInputDevices (aRawInDevList, aTryIter, sizeof(aRawInDevList[0])))
676 {
677 return aTryIter;
678 }
679
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");
683 }
684 return 0;
685}
686
e8e157df 687// =======================================================================
688// function : ProcessMessage
689// purpose :
690// =======================================================================
691bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener,
692 MSG& theMsg)
693{
694 switch (theMsg.message)
695 {
696 case WM_CLOSE:
697 {
698 if (theMsg.hwnd == (HWND )myHWindow)
699 {
700 theListener.ProcessClose();
701 return true;
702 }
703 return false;
704 }
705 case WM_ACTIVATE:
706 {
707 if (theMsg.hwnd == (HWND )myHWindow)
708 {
709 theListener.ProcessFocus (LOWORD(theMsg.wParam) == WA_CLICKACTIVE
710 || LOWORD(theMsg.wParam) == WA_ACTIVE);
711 return true;
712 }
713 return false;
714 }
715 case WM_PAINT:
716 {
717 PAINTSTRUCT aPaint;
718 BeginPaint(theMsg.hwnd, &aPaint);
719 EndPaint (theMsg.hwnd, &aPaint);
720 theListener.ProcessExpose();
721 return true;
722 }
723 case WM_SIZE:
724 case WM_MOVE:
725 case WM_MOVING:
726 case WM_SIZING:
727 {
728 theListener.ProcessConfigure (theMsg.message == WM_SIZE);
729 return true;
730 }
731 case WM_KEYUP:
732 case WM_KEYDOWN:
733 {
734 const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )theMsg.wParam);
735 if (aVKey != Aspect_VKey_UNKNOWN)
736 {
737 const double aTimeStamp = theListener.EventTime();
738 if (theMsg.message == WM_KEYDOWN)
739 {
740 theListener.KeyDown (aVKey, aTimeStamp);
741 }
742 else
743 {
744 theListener.KeyUp (aVKey, aTimeStamp);
745 }
746 theListener.ProcessInput();
747 }
748 return true;
749 }
750 case WM_LBUTTONUP:
751 case WM_MBUTTONUP:
752 case WM_RBUTTONUP:
753 case WM_LBUTTONDOWN:
754 case WM_MBUTTONDOWN:
755 case WM_RBUTTONDOWN:
756 {
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)
761 {
762 case WM_LBUTTONUP:
763 case WM_LBUTTONDOWN:
764 aButton = Aspect_VKeyMouse_LeftButton;
765 break;
766 case WM_MBUTTONUP:
767 case WM_MBUTTONDOWN:
768 aButton = Aspect_VKeyMouse_MiddleButton;
769 break;
770 case WM_RBUTTONUP:
771 case WM_RBUTTONDOWN:
772 aButton = Aspect_VKeyMouse_RightButton;
773 break;
774 }
775 if (theMsg.message == WM_LBUTTONDOWN
776 || theMsg.message == WM_MBUTTONDOWN
777 || theMsg.message == WM_RBUTTONDOWN)
778 {
779 SetFocus (theMsg.hwnd);
780 SetCapture(theMsg.hwnd);
781 theListener.PressMouseButton (aPos, aButton, aFlags, false);
782 }
783 else
784 {
785 ReleaseCapture();
786 theListener.ReleaseMouseButton (aPos, aButton, aFlags, false);
787 }
788 theListener.ProcessInput();
789 return true;
790 }
791 case WM_MOUSEWHEEL:
792 {
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))
799 {
800 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
801 }
802
803 if (theMsg.hwnd != (HWND )myHWindow)
804 {
805 return false;
806 }
807
808 theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
809 theListener.ProcessInput();
810 return true;
811 }
812 case WM_MOUSEMOVE:
813 {
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);
817
818 // don't make a slide-show from input events - fetch the actual mouse cursor position
819 CURSORINFO aCursor;
820 aCursor.cbSize = sizeof(aCursor);
821 if (::GetCursorInfo (&aCursor) != FALSE)
822 {
823 POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
824 if (ScreenToClient (theMsg.hwnd, &aCursorPnt))
825 {
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();
830 }
831 }
832
833 if (theMsg.hwnd != (HWND )myHWindow)
834 {
835 // mouse move events come also for inactive windows
836 return false;
837 }
838
839 theListener.UpdateMousePosition (aPos, aButtons, aFlags, false);
840 theListener.ProcessInput();
841 return true;
842 }
843 case WM_INPUT:
844 {
845 UINT aSize = 0;
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)
849 {
850 return true;
851 }
852
853 const RAWINPUT* aRawInput = (RAWINPUT* )(BYTE* )aRawData;
854 if (aRawInput->header.dwType != RIM_TYPEHID)
855 {
856 return true;
857 }
858
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))
865 {
866 return true;
867 }
868
869 WNT_HIDSpaceMouse aSpaceData (aDevInfo.hid.dwProductId, aRawInput->data.hid.bRawData, aRawInput->data.hid.dwSizeHid);
870 if (theListener.Update3dMouse (aSpaceData))
871 {
872 InvalidateContent (Handle(Aspect_DisplayConnection)());
873 }
874 return true;
875 }
876 }
877 return false;
878}
879
1ce0716b 880#endif // _WIN32