Window_win.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. * Copyright 2016 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/gpu/vk/GrVkVulkan.h"
  8. #include "tools/sk_app/win/Window_win.h"
  9. #include <tchar.h>
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include "src/core/SkUtils.h"
  13. #include "tools/ModifierKey.h"
  14. #include "tools/sk_app/WindowContext.h"
  15. #include "tools/sk_app/win/WindowContextFactory_win.h"
  16. #ifdef SK_VULKAN
  17. #include "tools/sk_app/VulkanWindowContext.h"
  18. #endif
  19. namespace sk_app {
  20. static int gWindowX = CW_USEDEFAULT;
  21. static int gWindowY = 0;
  22. static int gWindowWidth = CW_USEDEFAULT;
  23. static int gWindowHeight = 0;
  24. Window* Window::CreateNativeWindow(void* platformData) {
  25. HINSTANCE hInstance = (HINSTANCE)platformData;
  26. Window_win* window = new Window_win();
  27. if (!window->init(hInstance)) {
  28. delete window;
  29. return nullptr;
  30. }
  31. return window;
  32. }
  33. void Window_win::closeWindow() {
  34. RECT r;
  35. if (GetWindowRect(fHWnd, &r)) {
  36. gWindowX = r.left;
  37. gWindowY = r.top;
  38. gWindowWidth = r.right - r.left;
  39. gWindowHeight = r.bottom - r.top;
  40. }
  41. DestroyWindow(fHWnd);
  42. }
  43. Window_win::~Window_win() {
  44. this->closeWindow();
  45. }
  46. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  47. bool Window_win::init(HINSTANCE hInstance) {
  48. fHInstance = hInstance ? hInstance : GetModuleHandle(nullptr);
  49. // The main window class name
  50. static const TCHAR gSZWindowClass[] = _T("SkiaApp");
  51. static WNDCLASSEX wcex;
  52. static bool wcexInit = false;
  53. if (!wcexInit) {
  54. wcex.cbSize = sizeof(WNDCLASSEX);
  55. wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  56. wcex.lpfnWndProc = WndProc;
  57. wcex.cbClsExtra = 0;
  58. wcex.cbWndExtra = 0;
  59. wcex.hInstance = fHInstance;
  60. wcex.hIcon = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
  61. wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
  62. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  63. wcex.lpszMenuName = nullptr;
  64. wcex.lpszClassName = gSZWindowClass;
  65. wcex.hIconSm = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
  66. if (!RegisterClassEx(&wcex)) {
  67. return false;
  68. }
  69. wcexInit = true;
  70. }
  71. /*
  72. if (fullscreen)
  73. {
  74. DEVMODE dmScreenSettings;
  75. // If full screen set the screen to maximum size of the users desktop and 32bit.
  76. memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
  77. dmScreenSettings.dmSize = sizeof(dmScreenSettings);
  78. dmScreenSettings.dmPelsWidth = (unsigned long)width;
  79. dmScreenSettings.dmPelsHeight = (unsigned long)height;
  80. dmScreenSettings.dmBitsPerPel = 32;
  81. dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  82. // Change the display settings to full screen.
  83. ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
  84. // Set the position of the window to the top left corner.
  85. posX = posY = 0;
  86. }
  87. */
  88. // gIsFullscreen = fullscreen;
  89. fHWnd = CreateWindow(gSZWindowClass, nullptr, WS_OVERLAPPEDWINDOW,
  90. gWindowX, gWindowY, gWindowWidth, gWindowHeight,
  91. nullptr, nullptr, fHInstance, nullptr);
  92. if (!fHWnd)
  93. {
  94. return false;
  95. }
  96. SetWindowLongPtr(fHWnd, GWLP_USERDATA, (LONG_PTR)this);
  97. RegisterTouchWindow(fHWnd, 0);
  98. return true;
  99. }
  100. static Window::Key get_key(WPARAM vk) {
  101. static const struct {
  102. WPARAM fVK;
  103. Window::Key fKey;
  104. } gPair[] = {
  105. { VK_BACK, Window::Key::kBack },
  106. { VK_CLEAR, Window::Key::kBack },
  107. { VK_RETURN, Window::Key::kOK },
  108. { VK_UP, Window::Key::kUp },
  109. { VK_DOWN, Window::Key::kDown },
  110. { VK_LEFT, Window::Key::kLeft },
  111. { VK_RIGHT, Window::Key::kRight },
  112. { VK_TAB, Window::Key::kTab },
  113. { VK_PRIOR, Window::Key::kPageUp },
  114. { VK_NEXT, Window::Key::kPageDown },
  115. { VK_HOME, Window::Key::kHome },
  116. { VK_END, Window::Key::kEnd },
  117. { VK_DELETE, Window::Key::kDelete },
  118. { VK_ESCAPE, Window::Key::kEscape },
  119. { VK_SHIFT, Window::Key::kShift },
  120. { VK_CONTROL, Window::Key::kCtrl },
  121. { VK_MENU, Window::Key::kOption },
  122. { 'A', Window::Key::kA },
  123. { 'C', Window::Key::kC },
  124. { 'V', Window::Key::kV },
  125. { 'X', Window::Key::kX },
  126. { 'Y', Window::Key::kY },
  127. { 'Z', Window::Key::kZ },
  128. };
  129. for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
  130. if (gPair[i].fVK == vk) {
  131. return gPair[i].fKey;
  132. }
  133. }
  134. return Window::Key::kNONE;
  135. }
  136. static ModifierKey get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
  137. ModifierKey modifiers = ModifierKey::kNone;
  138. switch (message) {
  139. case WM_UNICHAR:
  140. case WM_CHAR:
  141. if (0 == (lParam & (1 << 30))) {
  142. modifiers |= ModifierKey::kFirstPress;
  143. }
  144. if (lParam & (1 << 29)) {
  145. modifiers |= ModifierKey::kOption;
  146. }
  147. break;
  148. case WM_KEYDOWN:
  149. case WM_SYSKEYDOWN:
  150. if (0 == (lParam & (1 << 30))) {
  151. modifiers |= ModifierKey::kFirstPress;
  152. }
  153. if (lParam & (1 << 29)) {
  154. modifiers |= ModifierKey::kOption;
  155. }
  156. break;
  157. case WM_KEYUP:
  158. case WM_SYSKEYUP:
  159. if (lParam & (1 << 29)) {
  160. modifiers |= ModifierKey::kOption;
  161. }
  162. break;
  163. case WM_LBUTTONDOWN:
  164. case WM_LBUTTONUP:
  165. case WM_MOUSEMOVE:
  166. case WM_MOUSEWHEEL:
  167. if (wParam & MK_CONTROL) {
  168. modifiers |= ModifierKey::kControl;
  169. }
  170. if (wParam & MK_SHIFT) {
  171. modifiers |= ModifierKey::kShift;
  172. }
  173. break;
  174. }
  175. return modifiers;
  176. }
  177. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  178. {
  179. PAINTSTRUCT ps;
  180. HDC hdc;
  181. Window_win* window = (Window_win*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  182. bool eventHandled = false;
  183. switch (message) {
  184. case WM_PAINT:
  185. hdc = BeginPaint(hWnd, &ps);
  186. window->onPaint();
  187. EndPaint(hWnd, &ps);
  188. eventHandled = true;
  189. break;
  190. case WM_CLOSE:
  191. PostQuitMessage(0);
  192. eventHandled = true;
  193. break;
  194. case WM_ACTIVATE:
  195. // disable/enable rendering here, depending on wParam != WA_INACTIVE
  196. break;
  197. case WM_SIZE:
  198. window->onResize(LOWORD(lParam), HIWORD(lParam));
  199. eventHandled = true;
  200. break;
  201. case WM_UNICHAR:
  202. eventHandled = window->onChar((SkUnichar)wParam,
  203. get_modifiers(message, wParam, lParam));
  204. break;
  205. case WM_CHAR: {
  206. const uint16_t* c = reinterpret_cast<uint16_t*>(&wParam);
  207. eventHandled = window->onChar(SkUTF16_NextUnichar(&c),
  208. get_modifiers(message, wParam, lParam));
  209. } break;
  210. case WM_KEYDOWN:
  211. case WM_SYSKEYDOWN:
  212. eventHandled = window->onKey(get_key(wParam), InputState::kDown,
  213. get_modifiers(message, wParam, lParam));
  214. break;
  215. case WM_KEYUP:
  216. case WM_SYSKEYUP:
  217. eventHandled = window->onKey(get_key(wParam), InputState::kUp,
  218. get_modifiers(message, wParam, lParam));
  219. break;
  220. case WM_LBUTTONDOWN:
  221. case WM_LBUTTONUP: {
  222. int xPos = GET_X_LPARAM(lParam);
  223. int yPos = GET_Y_LPARAM(lParam);
  224. //if (!gIsFullscreen)
  225. //{
  226. // RECT rc = { 0, 0, 640, 480 };
  227. // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
  228. // xPos -= rc.left;
  229. // yPos -= rc.top;
  230. //}
  231. InputState istate = ((wParam & MK_LBUTTON) != 0) ? InputState::kDown
  232. : InputState::kUp;
  233. eventHandled = window->onMouse(xPos, yPos, istate,
  234. get_modifiers(message, wParam, lParam));
  235. } break;
  236. case WM_MOUSEMOVE: {
  237. int xPos = GET_X_LPARAM(lParam);
  238. int yPos = GET_Y_LPARAM(lParam);
  239. //if (!gIsFullscreen)
  240. //{
  241. // RECT rc = { 0, 0, 640, 480 };
  242. // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
  243. // xPos -= rc.left;
  244. // yPos -= rc.top;
  245. //}
  246. eventHandled = window->onMouse(xPos, yPos, InputState::kMove,
  247. get_modifiers(message, wParam, lParam));
  248. } break;
  249. case WM_MOUSEWHEEL:
  250. eventHandled = window->onMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f,
  251. get_modifiers(message, wParam, lParam));
  252. break;
  253. case WM_TOUCH: {
  254. uint16_t numInputs = LOWORD(wParam);
  255. std::unique_ptr<TOUCHINPUT[]> inputs(new TOUCHINPUT[numInputs]);
  256. if (GetTouchInputInfo((HTOUCHINPUT)lParam, numInputs, inputs.get(),
  257. sizeof(TOUCHINPUT))) {
  258. POINT topLeft = {0, 0};
  259. ClientToScreen(hWnd, &topLeft);
  260. for (uint16_t i = 0; i < numInputs; ++i) {
  261. TOUCHINPUT ti = inputs[i];
  262. InputState state;
  263. if (ti.dwFlags & TOUCHEVENTF_DOWN) {
  264. state = InputState::kDown;
  265. } else if (ti.dwFlags & TOUCHEVENTF_MOVE) {
  266. state = InputState::kMove;
  267. } else if (ti.dwFlags & TOUCHEVENTF_UP) {
  268. state = InputState::kUp;
  269. } else {
  270. continue;
  271. }
  272. // TOUCHINPUT coordinates are in 100ths of pixels
  273. // Adjust for that, and make them window relative
  274. LONG tx = (ti.x / 100) - topLeft.x;
  275. LONG ty = (ti.y / 100) - topLeft.y;
  276. eventHandled = window->onTouch(ti.dwID, state, tx, ty) || eventHandled;
  277. }
  278. }
  279. } break;
  280. default:
  281. return DefWindowProc(hWnd, message, wParam, lParam);
  282. }
  283. return eventHandled ? 0 : 1;
  284. }
  285. void Window_win::setTitle(const char* title) {
  286. SetWindowTextA(fHWnd, title);
  287. }
  288. void Window_win::show() {
  289. ShowWindow(fHWnd, SW_SHOW);
  290. }
  291. bool Window_win::attach(BackendType attachType) {
  292. fBackend = attachType;
  293. switch (attachType) {
  294. case kNativeGL_BackendType:
  295. fWindowContext = window_context_factory::NewGLForWin(fHWnd, fRequestedDisplayParams);
  296. break;
  297. #if SK_ANGLE
  298. case kANGLE_BackendType:
  299. fWindowContext = window_context_factory::NewANGLEForWin(fHWnd, fRequestedDisplayParams);
  300. break;
  301. #endif
  302. case kRaster_BackendType:
  303. fWindowContext = window_context_factory::NewRasterForWin(fHWnd,
  304. fRequestedDisplayParams);
  305. break;
  306. #ifdef SK_VULKAN
  307. case kVulkan_BackendType:
  308. fWindowContext = window_context_factory::NewVulkanForWin(fHWnd,
  309. fRequestedDisplayParams);
  310. break;
  311. #endif
  312. }
  313. this->onBackendCreated();
  314. return (SkToBool(fWindowContext));
  315. }
  316. void Window_win::onInval() {
  317. InvalidateRect(fHWnd, nullptr, false);
  318. }
  319. void Window_win::setRequestedDisplayParams(const DisplayParams& params, bool allowReattach) {
  320. // GL on Windows doesn't let us change MSAA after the window is created
  321. if (params.fMSAASampleCount != this->getRequestedDisplayParams().fMSAASampleCount
  322. && allowReattach) {
  323. // Need to change these early, so attach() creates the window context correctly
  324. fRequestedDisplayParams = params;
  325. delete fWindowContext;
  326. this->closeWindow();
  327. this->init(fHInstance);
  328. this->attach(fBackend);
  329. }
  330. INHERITED::setRequestedDisplayParams(params, allowReattach);
  331. }
  332. } // namespace sk_app