vsg: include/vsg/platform/win32/Win32_Window.h Source File

vsg 1.1.8 VulkanSceneGraph library

Loading...
Searching...
No Matches
Win32_Window.h
1#pragma once
2
3/* <editor-fold desc="MIT License">
4
5Copyright(c) 2018 Robert Osfield
6
7Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
13</editor-fold> */
14
15#define VK_USE_PLATFORM_WIN32_KHR
16
17#ifndef NOMINMAX
18# define NOMINMAX
19#endif
20
21#include <vsg/app/Window.h>
22#include <vsg/ui/KeyEvent.h>
23#include <vsg/ui/PointerEvent.h>
24
25#include <windows.h>
26#include <windowsx.h>
27
28#include <vulkan/vulkan_win32.h>
29
30namespace vsgWin32
31{
32 class VSG_DECLSPEC KeyboardMap : public vsg::Object
33 {
34 public:
35 KeyboardMap();
36
37 using VirtualKeyToKeySymbolMap = std::map<uint16_t, vsg::KeySymbol>;
38
39 bool getKeySymbol(WPARAM wParam, LPARAM lParam, vsg::KeySymbol& keySymbol, vsg::KeySymbol& modifiedKeySymbol, vsg::KeyModifier& keyModifier)
40 {
41 uint16_t modifierMask = 0;
42
43 // see https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input#keystroke-message-flags
44 WORD vkCode = LOWORD(wParam); // virtual-key code
45 WORD keyFlags = HIWORD(lParam);
46 WORD scanCode = LOBYTE(keyFlags); // scan code
47 BOOL isExtendedKey = (keyFlags & KF_EXTENDED) == KF_EXTENDED; // extended-key flag, 1 if scancode has 0xE0 prefix
48
49 if (isExtendedKey)
50 scanCode = MAKEWORD(scanCode, 0xE0);
51
52 uint32_t virtualKey = ::MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK_EX, ::GetKeyboardLayout(0));
53 auto itr = _vk2vsg.find(virtualKey);
54
55 if (itr == _vk2vsg.end())
56 {
57 // What ever the code was in lParam should translate to a Virtual Key that we know of in _vk2vsg
58 // If we cannot find it, we simply return.
59 return false;
60 }
61
62 // This is the base-key that was pressed. (i.e., the VSG enum of the physical key pressed).
63 keySymbol = itr->second;
64
65 // Look for any modifiers that may be active.
66 BYTE keyState[256];
67 if (virtualKey == 0 || !::GetKeyboardState(keyState))
68 {
69 // if virtualKey was undefined or we could not get the keyboard state, simply return.
70 return false;
71 }
72
73 // If any of the specific left/right modifier keys are active
74 // add the side-independent vsg modifier to the modifier Mask
75 switch (virtualKey)
76 {
77 case VK_LSHIFT:
78 case VK_RSHIFT:
79 modifierMask |= vsg::KeyModifier::MODKEY_Shift;
80 break;
81
82 case VK_LCONTROL:
83 case VK_RCONTROL:
84 modifierMask |= vsg::KeyModifier::MODKEY_Control;
85 break;
86
87 case VK_LMENU:
88 case VK_RMENU:
89 modifierMask |= vsg::KeyModifier::MODKEY_Alt;
90 break;
91
92 default:
93 virtualKey = static_cast<uint32_t>(wParam);
94 break;
95 }
96
97 // Check if caps lock or numlock is toggled.
98 if (keyState[VK_CAPITAL] & 0x01) modifierMask |= vsg::KeyModifier::MODKEY_CapsLock;
99 if (keyState[VK_NUMLOCK] & 0x01) modifierMask |= vsg::KeyModifier::MODKEY_NumLock;
100
101 // Check if the modifier keys are down (these are non-toggle keys, so the high-order bit is relevant!)
102 // again, vsg only has a side-independent modifier
103 if (keyState[VK_LSHIFT] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Shift;
104 if (keyState[VK_RSHIFT] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Shift;
105 if (keyState[VK_LCONTROL] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Control;
106 if (keyState[VK_RCONTROL] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Control;
107 if (keyState[VK_LMENU] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Alt;
108 if (keyState[VK_RMENU] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Alt;
109
110 // This is the final keyModifier
111 keyModifier = static_cast<vsg::KeyModifier>(modifierMask);
112
113 // The actual keystroke is what we get after the ::ToAscii call
114 char asciiKey[2];
115 int32_t numChars = ::ToAsciiEx(static_cast<UINT>(wParam), scanCode, keyState, reinterpret_cast<WORD*>(asciiKey), 0, ::GetKeyboardLayout(0));
116 if (numChars == 1)
117 {
118 // it is indeed an ascii character. 0-127
119 modifiedKeySymbol = static_cast<vsg::KeySymbol>(asciiKey[0]);
120 }
121 else
122 {
123 // otherwise treat the modifiedKeySymbol as the same as the keySymbol.
124 modifiedKeySymbol = keySymbol;
125 }
126
127 return true;
128 }
129
130 protected:
131 VirtualKeyToKeySymbolMap _vk2vsg;
132 };
133
134 inline vsg::ButtonMask getButtonMask(WPARAM wParam)
135 {
136 auto mask = (wParam & MK_LBUTTON ? vsg::ButtonMask::BUTTON_MASK_1 : 0) | (wParam & MK_MBUTTON ? vsg::ButtonMask::BUTTON_MASK_2 : 0) | (wParam & MK_RBUTTON ? vsg::ButtonMask::BUTTON_MASK_3 : 0) |
137 (wParam & MK_XBUTTON1 ? vsg::ButtonMask::BUTTON_MASK_4 : 0) | (wParam & MK_XBUTTON2 ? vsg::ButtonMask::BUTTON_MASK_5 : 0);
138 return static_cast<vsg::ButtonMask>(mask);
139 }
140
141 inline uint32_t getButtonDownEventDetail(UINT buttonMsg, WORD wParamHi)
142 {
143 switch (buttonMsg)
144 {
145 case WM_LBUTTONDBLCLK:
146 case WM_LBUTTONDOWN: return 1;
147 case WM_MBUTTONDBLCLK:
148 case WM_MBUTTONDOWN: return 2;
149 case WM_RBUTTONDBLCLK:
150 case WM_RBUTTONDOWN: return 3;
151 case WM_XBUTTONDBLCLK:
152 case WM_XBUTTONDOWN:
153 if (wParamHi == XBUTTON1)
154 return 4;
155 else if (wParamHi == XBUTTON2)
156 return 5;
157 else
158 return 0;
159 default:
160 return 0;
161 }
162 }
163
164 inline uint32_t getButtonUpEventDetail(UINT buttonMsg, WORD wParamHi)
165 {
166 switch (buttonMsg)
167 {
168 case WM_LBUTTONUP: return 1;
169 case WM_MBUTTONUP: return 2;
170 case WM_RBUTTONUP: return 3;
171 case WM_XBUTTONUP:
172 if (wParamHi == XBUTTON1)
173 return 4;
174 else if (wParamHi == XBUTTON2)
175 return 5;
176 else
177 return 0;
178 default:
179 return 0;
180 }
181 }
182
184 class VSG_DECLSPEC Win32_Window : public vsg::Inherit<vsg::Window, Win32_Window>
185 {
186 public:
187 Win32_Window(vsg::ref_ptr<vsg::WindowTraits> traits);
188 Win32_Window() = delete;
189 Win32_Window(const Win32_Window&) = delete;
190 Win32_Window operator=(const Win32_Window&) = delete;
191
192 const char* instanceExtensionSurfaceName() const override { return VK_KHR_WIN32_SURFACE_EXTENSION_NAME; }
193
194 bool valid() const override { return _window; }
195
196 bool visible() const override;
197
198 void releaseWindow() override;
199
200 bool pollEvents(vsg::UIEvents& events) override;
201
202 void resize() override;
203
204 operator HWND() const { return _window; }
205
207 virtual bool handleWin32Messages(UINT msg, WPARAM wParam, LPARAM lParam);
208
209 protected:
210 virtual ~Win32_Window();
211
212 void _initSurface() override;
213
214 HWND _window;
215 bool _windowMapped = false;
216
217 vsg::ref_ptr<KeyboardMap> _keyboard;
218 };
219
221 extern VSG_DECLSPEC vsg::Exception getLastErrorAsException(const std::string_view& prefix = {});
222
223} // namespace vsgWin32
224
225EVSG_type_name(vsgWin32::Win32_Window);
vsg::Inherit
Definition Inherit.h:28
vsg::Object
Definition Object.h:60
vsg::ref_ptr
Definition ref_ptr.h:22
vsgWin32::KeyboardMap
Definition Win32_Window.h:33
vsgWin32::Win32_Window
Win32_Window implements Win32 specific window creation, event handling and vulkan Surface setup.
Definition Win32_Window.h:185
vsgWin32::Win32_Window::pollEvents
bool pollEvents(vsg::UIEvents &events) override
get the list of events since the last pollEvents() call by splicing bufferEvents with polled windowin...
vsgWin32::Win32_Window::handleWin32Messages
virtual bool handleWin32Messages(UINT msg, WPARAM wParam, LPARAM lParam)
handle Win32 event messages, return true if handled.
vsgWin32::Win32_Window::releaseWindow
void releaseWindow() override
vsg::Exception
Definition Exception.h:23