win32drv.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. /**
  2. * @file win32drv.c
  3. *
  4. */
  5. /*********************
  6. * INCLUDES
  7. *********************/
  8. #include "win32drv.h"
  9. #if USE_WIN32DRV
  10. #include <windowsx.h>
  11. #include <stdbool.h>
  12. #include <stdint.h>
  13. /*********************
  14. * DEFINES
  15. *********************/
  16. #define WINDOW_EX_STYLE \
  17. WS_EX_CLIENTEDGE
  18. #define WINDOW_STYLE \
  19. (WS_OVERLAPPEDWINDOW & ~(WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME))
  20. #ifndef WIN32DRV_MONITOR_ZOOM
  21. #define WIN32DRV_MONITOR_ZOOM 1
  22. #endif
  23. #ifndef USER_DEFAULT_SCREEN_DPI
  24. #define USER_DEFAULT_SCREEN_DPI 96
  25. #endif
  26. /**********************
  27. * TYPEDEFS
  28. **********************/
  29. /**********************
  30. * STATIC PROTOTYPES
  31. **********************/
  32. /**
  33. * @brief Creates a B8G8R8A8 frame buffer.
  34. * @param WindowHandle A handle to the window for the creation of the frame
  35. * buffer. If this value is NULL, the entire screen will be
  36. * referenced.
  37. * @param Width The width of the frame buffer.
  38. * @param Height The height of the frame buffer.
  39. * @param PixelBuffer The raw pixel buffer of the frame buffer you created.
  40. * @param PixelBufferSize The size of the frame buffer you created.
  41. * @return If the function succeeds, the return value is a handle to the device
  42. * context (DC) for the frame buffer. If the function fails, the return
  43. * value is NULL, and PixelBuffer parameter is NULL.
  44. */
  45. static HDC lv_win32_create_frame_buffer(
  46. _In_opt_ HWND WindowHandle,
  47. _In_ LONG Width,
  48. _In_ LONG Height,
  49. _Out_ UINT32** PixelBuffer,
  50. _Out_ SIZE_T* PixelBufferSize);
  51. /**
  52. * @brief Enables WM_DPICHANGED message for child window for the associated
  53. * window.
  54. * @param WindowHandle The window you want to enable WM_DPICHANGED message for
  55. * child window.
  56. * @return If the function succeeds, the return value is non-zero. If the
  57. * function fails, the return value is zero.
  58. * @remarks You need to use this function in Windows 10 Threshold 1 or Windows
  59. * 10 Threshold 2.
  60. */
  61. static BOOL lv_win32_enable_child_window_dpi_message(
  62. _In_ HWND WindowHandle);
  63. /**
  64. * @brief Registers a window as being touch-capable.
  65. * @param hWnd The handle of the window being registered.
  66. * @param ulFlags A set of bit flags that specify optional modifications.
  67. * @return If the function succeeds, the return value is nonzero. If the
  68. * function fails, the return value is zero.
  69. * @remark For more information, see RegisterTouchWindow.
  70. */
  71. static BOOL lv_win32_register_touch_window(
  72. HWND hWnd,
  73. ULONG ulFlags);
  74. /**
  75. * @brief Retrieves detailed information about touch inputs associated with a
  76. * particular touch input handle.
  77. * @param hTouchInput The touch input handle received in the LPARAM of a touch
  78. * message.
  79. * @param cInputs The number of structures in the pInputs array.
  80. * @param pInputs A pointer to an array of TOUCHINPUT structures to receive
  81. * information about the touch points associated with the
  82. * specified touch input handle.
  83. * @param cbSize The size, in bytes, of a single TOUCHINPUT structure.
  84. * @return If the function succeeds, the return value is nonzero. If the
  85. * function fails, the return value is zero.
  86. * @remark For more information, see GetTouchInputInfo.
  87. */
  88. static BOOL lv_win32_get_touch_input_info(
  89. HTOUCHINPUT hTouchInput,
  90. UINT cInputs,
  91. PTOUCHINPUT pInputs,
  92. int cbSize);
  93. /**
  94. * @brief Closes a touch input handle, frees process memory associated with it,
  95. and invalidates the handle.
  96. * @param hTouchInput The touch input handle received in the LPARAM of a touch
  97. * message.
  98. * @return If the function succeeds, the return value is nonzero. If the
  99. * function fails, the return value is zero.
  100. * @remark For more information, see CloseTouchInputHandle.
  101. */
  102. static BOOL lv_win32_close_touch_input_handle(
  103. HTOUCHINPUT hTouchInput);
  104. /**
  105. * @brief Returns the dots per inch (dpi) value for the associated window.
  106. * @param WindowHandle The window you want to get information about.
  107. * @return The DPI for the window.
  108. */
  109. static UINT lv_win32_get_dpi_for_window(
  110. _In_ HWND WindowHandle);
  111. static void lv_win32_display_driver_flush_callback(
  112. lv_disp_drv_t* disp_drv,
  113. const lv_area_t* area,
  114. lv_color_t* color_p);
  115. static void lv_win32_display_driver_rounder_callback(
  116. lv_disp_drv_t* disp_drv,
  117. lv_area_t* area);
  118. static void lv_win32_pointer_driver_read_callback(
  119. lv_indev_drv_t* indev_drv,
  120. lv_indev_data_t* data);
  121. static void lv_win32_keypad_driver_read_callback(
  122. lv_indev_drv_t* indev_drv,
  123. lv_indev_data_t* data);
  124. static void lv_win32_encoder_driver_read_callback(
  125. lv_indev_drv_t* indev_drv,
  126. lv_indev_data_t* data);
  127. static LRESULT CALLBACK lv_win32_window_message_callback(
  128. HWND hWnd,
  129. UINT uMsg,
  130. WPARAM wParam,
  131. LPARAM lParam);
  132. static void lv_win32_message_handler(
  133. lv_timer_t* param);
  134. /**********************
  135. * GLOBAL VARIABLES
  136. **********************/
  137. EXTERN_C bool lv_win32_quit_signal = false;
  138. EXTERN_C lv_indev_t* lv_win32_pointer_device_object = NULL;
  139. EXTERN_C lv_indev_t* lv_win32_keypad_device_object = NULL;
  140. EXTERN_C lv_indev_t* lv_win32_encoder_device_object = NULL;
  141. /**********************
  142. * STATIC VARIABLES
  143. **********************/
  144. static HINSTANCE g_instance_handle = NULL;
  145. static HWND g_window_handle = NULL;
  146. static HDC g_buffer_dc_handle = NULL;
  147. static UINT32* g_pixel_buffer = NULL;
  148. static SIZE_T g_pixel_buffer_size = 0;
  149. static lv_disp_t* g_display = NULL;
  150. static bool volatile g_mouse_pressed = false;
  151. static LPARAM volatile g_mouse_value = 0;
  152. static bool volatile g_mousewheel_pressed = false;
  153. static int16_t volatile g_mousewheel_value = 0;
  154. static bool volatile g_keyboard_pressed = false;
  155. static WPARAM volatile g_keyboard_value = 0;
  156. static int volatile g_dpi_value = USER_DEFAULT_SCREEN_DPI;
  157. /**********************
  158. * MACROS
  159. **********************/
  160. /**********************
  161. * GLOBAL FUNCTIONS
  162. **********************/
  163. EXTERN_C void lv_win32_add_all_input_devices_to_group(
  164. lv_group_t* group)
  165. {
  166. if (!group)
  167. {
  168. LV_LOG_WARN(
  169. "The group object is NULL. Get the default group object instead.");
  170. group = lv_group_get_default();
  171. if (!group)
  172. {
  173. LV_LOG_WARN(
  174. "The default group object is NULL. Create a new group object "
  175. "and set it to default instead.");
  176. group = lv_group_create();
  177. if (group)
  178. {
  179. lv_group_set_default(group);
  180. }
  181. }
  182. }
  183. LV_ASSERT_MSG(group, "Cannot obtain an available group object.");
  184. lv_indev_set_group(lv_win32_pointer_device_object, group);
  185. lv_indev_set_group(lv_win32_keypad_device_object, group);
  186. lv_indev_set_group(lv_win32_encoder_device_object, group);
  187. }
  188. EXTERN_C bool lv_win32_init(
  189. HINSTANCE instance_handle,
  190. int show_window_mode,
  191. lv_coord_t hor_res,
  192. lv_coord_t ver_res,
  193. HICON icon_handle)
  194. {
  195. WNDCLASSEXW WindowClass;
  196. WindowClass.cbSize = sizeof(WNDCLASSEX);
  197. WindowClass.style = 0;
  198. WindowClass.lpfnWndProc = lv_win32_window_message_callback;
  199. WindowClass.cbClsExtra = 0;
  200. WindowClass.cbWndExtra = 0;
  201. WindowClass.hInstance = instance_handle;
  202. WindowClass.hIcon = icon_handle;
  203. WindowClass.hCursor = LoadCursorW(NULL, IDC_ARROW);
  204. WindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  205. WindowClass.lpszMenuName = NULL;
  206. WindowClass.lpszClassName = L"lv_sim_visual_studio";
  207. WindowClass.hIconSm = icon_handle;
  208. if (!RegisterClassExW(&WindowClass))
  209. {
  210. return false;
  211. }
  212. g_instance_handle = instance_handle;
  213. g_window_handle = CreateWindowExW(
  214. WINDOW_EX_STYLE,
  215. WindowClass.lpszClassName,
  216. L"LVGL Simulator for Windows Desktop",
  217. WINDOW_STYLE,
  218. CW_USEDEFAULT,
  219. 0,
  220. CW_USEDEFAULT,
  221. 0,
  222. NULL,
  223. NULL,
  224. instance_handle,
  225. NULL);
  226. if (!g_window_handle)
  227. {
  228. return false;
  229. }
  230. g_dpi_value = lv_win32_get_dpi_for_window(g_window_handle);
  231. RECT WindowSize;
  232. WindowSize.left = 0;
  233. WindowSize.right = MulDiv(
  234. hor_res * WIN32DRV_MONITOR_ZOOM,
  235. g_dpi_value,
  236. USER_DEFAULT_SCREEN_DPI);
  237. WindowSize.top = 0;
  238. WindowSize.bottom = MulDiv(
  239. ver_res * WIN32DRV_MONITOR_ZOOM,
  240. g_dpi_value,
  241. USER_DEFAULT_SCREEN_DPI);
  242. AdjustWindowRectEx(
  243. &WindowSize,
  244. WINDOW_STYLE,
  245. FALSE,
  246. WINDOW_EX_STYLE);
  247. OffsetRect(
  248. &WindowSize,
  249. -WindowSize.left,
  250. -WindowSize.top);
  251. SetWindowPos(
  252. g_window_handle,
  253. NULL,
  254. 0,
  255. 0,
  256. WindowSize.right,
  257. WindowSize.bottom,
  258. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
  259. lv_win32_register_touch_window(g_window_handle, 0);
  260. lv_timer_create(lv_win32_message_handler, 0, NULL);
  261. lv_win32_enable_child_window_dpi_message(g_window_handle);
  262. HDC hNewBufferDC = lv_win32_create_frame_buffer(
  263. g_window_handle,
  264. hor_res,
  265. ver_res,
  266. &g_pixel_buffer,
  267. &g_pixel_buffer_size);
  268. DeleteDC(g_buffer_dc_handle);
  269. g_buffer_dc_handle = hNewBufferDC;
  270. static lv_disp_draw_buf_t display_buffer;
  271. lv_disp_draw_buf_init(
  272. &display_buffer,
  273. (lv_color_t*)malloc(hor_res * ver_res * sizeof(lv_color_t)),
  274. NULL,
  275. hor_res * ver_res);
  276. static lv_disp_drv_t display_driver;
  277. lv_disp_drv_init(&display_driver);
  278. display_driver.hor_res = hor_res;
  279. display_driver.ver_res = ver_res;
  280. display_driver.flush_cb = lv_win32_display_driver_flush_callback;
  281. display_driver.draw_buf = &display_buffer;
  282. display_driver.rounder_cb = lv_win32_display_driver_rounder_callback;
  283. g_display = lv_disp_drv_register(&display_driver);
  284. static lv_indev_drv_t pointer_driver;
  285. lv_indev_drv_init(&pointer_driver);
  286. pointer_driver.type = LV_INDEV_TYPE_POINTER;
  287. pointer_driver.read_cb = lv_win32_pointer_driver_read_callback;
  288. lv_win32_pointer_device_object = lv_indev_drv_register(&pointer_driver);
  289. static lv_indev_drv_t keypad_driver;
  290. lv_indev_drv_init(&keypad_driver);
  291. keypad_driver.type = LV_INDEV_TYPE_KEYPAD;
  292. keypad_driver.read_cb = lv_win32_keypad_driver_read_callback;
  293. lv_win32_keypad_device_object = lv_indev_drv_register(&keypad_driver);
  294. static lv_indev_drv_t encoder_driver;
  295. lv_indev_drv_init(&encoder_driver);
  296. encoder_driver.type = LV_INDEV_TYPE_ENCODER;
  297. encoder_driver.read_cb = lv_win32_encoder_driver_read_callback;
  298. lv_win32_encoder_device_object = lv_indev_drv_register(&encoder_driver);
  299. ShowWindow(g_window_handle, show_window_mode);
  300. UpdateWindow(g_window_handle);
  301. return true;
  302. }
  303. /**********************
  304. * STATIC FUNCTIONS
  305. **********************/
  306. static HDC lv_win32_create_frame_buffer(
  307. HWND WindowHandle,
  308. LONG Width,
  309. LONG Height,
  310. UINT32** PixelBuffer,
  311. SIZE_T* PixelBufferSize)
  312. {
  313. HDC hFrameBufferDC = NULL;
  314. if (PixelBuffer && PixelBufferSize)
  315. {
  316. HDC hWindowDC = GetDC(WindowHandle);
  317. if (hWindowDC)
  318. {
  319. hFrameBufferDC = CreateCompatibleDC(hWindowDC);
  320. ReleaseDC(WindowHandle, hWindowDC);
  321. }
  322. if (hFrameBufferDC)
  323. {
  324. #if LV_COLOR_DEPTH == 32
  325. BITMAPINFO BitmapInfo = { 0 };
  326. #elif LV_COLOR_DEPTH == 16
  327. typedef struct _BITMAPINFO_16BPP {
  328. BITMAPINFOHEADER bmiHeader;
  329. DWORD bmiColorMask[3];
  330. } BITMAPINFO_16BPP, *PBITMAPINFO_16BPP;
  331. BITMAPINFO_16BPP BitmapInfo = { 0 };
  332. #elif LV_COLOR_DEPTH == 8
  333. typedef struct _BITMAPINFO_8BPP {
  334. BITMAPINFOHEADER bmiHeader;
  335. RGBQUAD bmiColors[256];
  336. } BITMAPINFO_8BPP, *PBITMAPINFO_8BPP;
  337. BITMAPINFO_8BPP BitmapInfo = { 0 };
  338. #elif LV_COLOR_DEPTH == 1
  339. typedef struct _BITMAPINFO_1BPP {
  340. BITMAPINFOHEADER bmiHeader;
  341. RGBQUAD bmiColors[2];
  342. } BITMAPINFO_1BPP, *PBITMAPINFO_1BPP;
  343. BITMAPINFO_1BPP BitmapInfo = { 0 };
  344. #else
  345. BITMAPINFO BitmapInfo = { 0 };
  346. #endif
  347. BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  348. BitmapInfo.bmiHeader.biWidth = Width;
  349. BitmapInfo.bmiHeader.biHeight = -Height;
  350. BitmapInfo.bmiHeader.biPlanes = 1;
  351. #if LV_COLOR_DEPTH == 32
  352. BitmapInfo.bmiHeader.biBitCount = 32;
  353. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  354. #elif LV_COLOR_DEPTH == 16
  355. BitmapInfo.bmiHeader.biBitCount = 16;
  356. BitmapInfo.bmiHeader.biCompression = BI_BITFIELDS;
  357. BitmapInfo.bmiColorMask[0] = 0xF800;
  358. BitmapInfo.bmiColorMask[1] = 0x07E0;
  359. BitmapInfo.bmiColorMask[2] = 0x001F;
  360. #elif LV_COLOR_DEPTH == 8
  361. BitmapInfo.bmiHeader.biBitCount = 8;
  362. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  363. for (size_t i = 0; i < 256; ++i)
  364. {
  365. lv_color8_t color;
  366. color.full = i;
  367. BitmapInfo.bmiColors[i].rgbRed = LV_COLOR_GET_R(color) * 36;
  368. BitmapInfo.bmiColors[i].rgbGreen = LV_COLOR_GET_G(color) * 36;
  369. BitmapInfo.bmiColors[i].rgbBlue = LV_COLOR_GET_B(color) * 85;
  370. BitmapInfo.bmiColors[i].rgbReserved = 0xFF;
  371. }
  372. #elif LV_COLOR_DEPTH == 1
  373. BitmapInfo.bmiHeader.biBitCount = 8;
  374. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  375. BitmapInfo.bmiHeader.biClrUsed = 2;
  376. BitmapInfo.bmiHeader.biClrImportant = 2;
  377. BitmapInfo.bmiColors[0].rgbRed = 0x00;
  378. BitmapInfo.bmiColors[0].rgbGreen = 0x00;
  379. BitmapInfo.bmiColors[0].rgbBlue = 0x00;
  380. BitmapInfo.bmiColors[0].rgbReserved = 0xFF;
  381. BitmapInfo.bmiColors[1].rgbRed = 0xFF;
  382. BitmapInfo.bmiColors[1].rgbGreen = 0xFF;
  383. BitmapInfo.bmiColors[1].rgbBlue = 0xFF;
  384. BitmapInfo.bmiColors[1].rgbReserved = 0xFF;
  385. #else
  386. BitmapInfo.bmiHeader.biBitCount = 32;
  387. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  388. #endif
  389. HBITMAP hBitmap = CreateDIBSection(
  390. hFrameBufferDC,
  391. (PBITMAPINFO)(&BitmapInfo),
  392. DIB_RGB_COLORS,
  393. (void**)PixelBuffer,
  394. NULL,
  395. 0);
  396. if (hBitmap)
  397. {
  398. #if LV_COLOR_DEPTH == 32
  399. *PixelBufferSize = Width * Height * sizeof(UINT32);
  400. #elif LV_COLOR_DEPTH == 16
  401. *PixelBufferSize = Width * Height * sizeof(UINT16);
  402. #elif LV_COLOR_DEPTH == 8
  403. *PixelBufferSize = Width * Height * sizeof(UINT8);
  404. #elif LV_COLOR_DEPTH == 1
  405. *PixelBufferSize = Width * Height * sizeof(UINT8);
  406. #else
  407. *PixelBufferSize = Width * Height * sizeof(UINT32);
  408. #endif
  409. DeleteObject(SelectObject(hFrameBufferDC, hBitmap));
  410. DeleteObject(hBitmap);
  411. }
  412. else
  413. {
  414. DeleteDC(hFrameBufferDC);
  415. hFrameBufferDC = NULL;
  416. }
  417. }
  418. }
  419. return hFrameBufferDC;
  420. }
  421. static BOOL lv_win32_enable_child_window_dpi_message(
  422. HWND WindowHandle)
  423. {
  424. // This hack is only for Windows 10 TH1/TH2 only.
  425. // We don't need this hack if the Per Monitor Aware V2 is existed.
  426. OSVERSIONINFOEXW OSVersionInfoEx = { 0 };
  427. OSVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
  428. OSVersionInfoEx.dwMajorVersion = 10;
  429. OSVersionInfoEx.dwMinorVersion = 0;
  430. OSVersionInfoEx.dwBuildNumber = 14393;
  431. if (!VerifyVersionInfoW(
  432. &OSVersionInfoEx,
  433. VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER,
  434. VerSetConditionMask(
  435. VerSetConditionMask(
  436. VerSetConditionMask(
  437. 0,
  438. VER_MAJORVERSION,
  439. VER_GREATER_EQUAL),
  440. VER_MINORVERSION,
  441. VER_GREATER_EQUAL),
  442. VER_BUILDNUMBER,
  443. VER_LESS)))
  444. {
  445. return FALSE;
  446. }
  447. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  448. if (!ModuleHandle)
  449. {
  450. return FALSE;
  451. }
  452. typedef BOOL(WINAPI* FunctionType)(HWND, BOOL);
  453. FunctionType pFunction = (FunctionType)(
  454. GetProcAddress(ModuleHandle, "EnableChildWindowDpiMessage"));
  455. if (!pFunction)
  456. {
  457. return FALSE;
  458. }
  459. return pFunction(WindowHandle, TRUE);
  460. }
  461. static BOOL lv_win32_register_touch_window(
  462. HWND hWnd,
  463. ULONG ulFlags)
  464. {
  465. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  466. if (!ModuleHandle)
  467. {
  468. return FALSE;
  469. }
  470. typedef BOOL(WINAPI* FunctionType)(HWND, ULONG);
  471. FunctionType pFunction = (FunctionType)(
  472. GetProcAddress(ModuleHandle, "RegisterTouchWindow"));
  473. if (!pFunction)
  474. {
  475. return FALSE;
  476. }
  477. return pFunction(hWnd, ulFlags);
  478. }
  479. static BOOL lv_win32_get_touch_input_info(
  480. HTOUCHINPUT hTouchInput,
  481. UINT cInputs,
  482. PTOUCHINPUT pInputs,
  483. int cbSize)
  484. {
  485. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  486. if (!ModuleHandle)
  487. {
  488. return FALSE;
  489. }
  490. typedef BOOL(WINAPI* FunctionType)(HTOUCHINPUT, UINT, PTOUCHINPUT, int);
  491. FunctionType pFunction = (FunctionType)(
  492. GetProcAddress(ModuleHandle, "GetTouchInputInfo"));
  493. if (!pFunction)
  494. {
  495. return FALSE;
  496. }
  497. return pFunction(hTouchInput, cInputs, pInputs, cbSize);
  498. }
  499. static BOOL lv_win32_close_touch_input_handle(
  500. HTOUCHINPUT hTouchInput)
  501. {
  502. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  503. if (!ModuleHandle)
  504. {
  505. return FALSE;
  506. }
  507. typedef BOOL(WINAPI* FunctionType)(HTOUCHINPUT);
  508. FunctionType pFunction = (FunctionType)(
  509. GetProcAddress(ModuleHandle, "CloseTouchInputHandle"));
  510. if (!pFunction)
  511. {
  512. return FALSE;
  513. }
  514. return pFunction(hTouchInput);
  515. }
  516. static UINT lv_win32_get_dpi_for_window(
  517. _In_ HWND WindowHandle)
  518. {
  519. UINT Result = (UINT)(-1);
  520. HMODULE ModuleHandle = LoadLibraryW(L"SHCore.dll");
  521. if (ModuleHandle)
  522. {
  523. typedef enum MONITOR_DPI_TYPE_PRIVATE {
  524. MDT_EFFECTIVE_DPI = 0,
  525. MDT_ANGULAR_DPI = 1,
  526. MDT_RAW_DPI = 2,
  527. MDT_DEFAULT = MDT_EFFECTIVE_DPI
  528. } MONITOR_DPI_TYPE_PRIVATE;
  529. typedef HRESULT(WINAPI* FunctionType)(
  530. HMONITOR, MONITOR_DPI_TYPE_PRIVATE, UINT*, UINT*);
  531. FunctionType pFunction = (FunctionType)(
  532. GetProcAddress(ModuleHandle, "GetDpiForMonitor"));
  533. if (pFunction)
  534. {
  535. HMONITOR MonitorHandle = MonitorFromWindow(
  536. WindowHandle,
  537. MONITOR_DEFAULTTONEAREST);
  538. UINT dpiX = 0;
  539. UINT dpiY = 0;
  540. if (SUCCEEDED(pFunction(
  541. MonitorHandle,
  542. MDT_EFFECTIVE_DPI,
  543. &dpiX,
  544. &dpiY)))
  545. {
  546. Result = dpiX;
  547. }
  548. }
  549. FreeLibrary(ModuleHandle);
  550. }
  551. if (Result == (UINT)(-1))
  552. {
  553. HDC hWindowDC = GetDC(WindowHandle);
  554. if (hWindowDC)
  555. {
  556. Result = GetDeviceCaps(hWindowDC, LOGPIXELSX);
  557. ReleaseDC(WindowHandle, hWindowDC);
  558. }
  559. }
  560. if (Result == (UINT)(-1))
  561. {
  562. Result = USER_DEFAULT_SCREEN_DPI;
  563. }
  564. return Result;
  565. }
  566. static void lv_win32_display_driver_flush_callback(
  567. lv_disp_drv_t* disp_drv,
  568. const lv_area_t* area,
  569. lv_color_t* color_p)
  570. {
  571. #if (LV_COLOR_DEPTH == 32) || \
  572. (LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0) || \
  573. (LV_COLOR_DEPTH == 8) || \
  574. (LV_COLOR_DEPTH == 1)
  575. UNREFERENCED_PARAMETER(area);
  576. memcpy(g_pixel_buffer, color_p, g_pixel_buffer_size);
  577. #elif (LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP != 0)
  578. SIZE_T count = g_pixel_buffer_size / sizeof(UINT16);
  579. PUINT16 source = (PUINT16)color_p;
  580. PUINT16 destination = (PUINT16)g_pixel_buffer;
  581. for (SIZE_T i = 0; i < count; ++i)
  582. {
  583. UINT16 current = *source;
  584. *destination = (LOBYTE(current) << 8) | HIBYTE(current);
  585. ++source;
  586. ++destination;
  587. }
  588. #else
  589. for (int y = area->y1; y <= area->y2; ++y)
  590. {
  591. for (int x = area->x1; x <= area->x2; ++x)
  592. {
  593. g_pixel_buffer[y * disp_drv->hor_res + x] = lv_color_to32(*color_p);
  594. color_p++;
  595. }
  596. }
  597. #endif
  598. HDC hWindowDC = GetDC(g_window_handle);
  599. if (hWindowDC)
  600. {
  601. int PreviousMode = SetStretchBltMode(
  602. hWindowDC,
  603. HALFTONE);
  604. StretchBlt(
  605. hWindowDC,
  606. 0,
  607. 0,
  608. MulDiv(
  609. disp_drv->hor_res * WIN32DRV_MONITOR_ZOOM,
  610. g_dpi_value,
  611. USER_DEFAULT_SCREEN_DPI),
  612. MulDiv(
  613. disp_drv->ver_res * WIN32DRV_MONITOR_ZOOM,
  614. g_dpi_value,
  615. USER_DEFAULT_SCREEN_DPI),
  616. g_buffer_dc_handle,
  617. 0,
  618. 0,
  619. disp_drv->hor_res,
  620. disp_drv->ver_res,
  621. SRCCOPY);
  622. SetStretchBltMode(
  623. hWindowDC,
  624. PreviousMode);
  625. ReleaseDC(g_window_handle, hWindowDC);
  626. }
  627. lv_disp_flush_ready(disp_drv);
  628. }
  629. static void lv_win32_display_driver_rounder_callback(
  630. lv_disp_drv_t* disp_drv,
  631. lv_area_t* area)
  632. {
  633. area->x1 = 0;
  634. area->x2 = disp_drv->hor_res - 1;
  635. area->y1 = 0;
  636. area->y2 = disp_drv->ver_res - 1;
  637. }
  638. static void lv_win32_pointer_driver_read_callback(
  639. lv_indev_drv_t* indev_drv,
  640. lv_indev_data_t* data)
  641. {
  642. UNREFERENCED_PARAMETER(indev_drv);
  643. data->state = (lv_indev_state_t)(
  644. g_mouse_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
  645. data->point.x = MulDiv(
  646. GET_X_LPARAM(g_mouse_value),
  647. USER_DEFAULT_SCREEN_DPI,
  648. WIN32DRV_MONITOR_ZOOM * g_dpi_value);
  649. data->point.y = MulDiv(
  650. GET_Y_LPARAM(g_mouse_value),
  651. USER_DEFAULT_SCREEN_DPI,
  652. WIN32DRV_MONITOR_ZOOM * g_dpi_value);
  653. if (data->point.x < 0)
  654. {
  655. data->point.x = 0;
  656. }
  657. if (data->point.x > g_display->driver->hor_res - 1)
  658. {
  659. data->point.x = g_display->driver->hor_res - 1;
  660. }
  661. if (data->point.y < 0)
  662. {
  663. data->point.y = 0;
  664. }
  665. if (data->point.y > g_display->driver->ver_res - 1)
  666. {
  667. data->point.y = g_display->driver->ver_res - 1;
  668. }
  669. }
  670. static void lv_win32_keypad_driver_read_callback(
  671. lv_indev_drv_t* indev_drv,
  672. lv_indev_data_t* data)
  673. {
  674. UNREFERENCED_PARAMETER(indev_drv);
  675. data->state = (lv_indev_state_t)(
  676. g_keyboard_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
  677. WPARAM KeyboardValue = g_keyboard_value;
  678. switch (KeyboardValue)
  679. {
  680. case VK_UP:
  681. data->key = LV_KEY_UP;
  682. break;
  683. case VK_DOWN:
  684. data->key = LV_KEY_DOWN;
  685. break;
  686. case VK_LEFT:
  687. data->key = LV_KEY_LEFT;
  688. break;
  689. case VK_RIGHT:
  690. data->key = LV_KEY_RIGHT;
  691. break;
  692. case VK_ESCAPE:
  693. data->key = LV_KEY_ESC;
  694. break;
  695. case VK_DELETE:
  696. data->key = LV_KEY_DEL;
  697. break;
  698. case VK_BACK:
  699. data->key = LV_KEY_BACKSPACE;
  700. break;
  701. case VK_RETURN:
  702. data->key = LV_KEY_ENTER;
  703. break;
  704. case VK_NEXT:
  705. data->key = LV_KEY_NEXT;
  706. break;
  707. case VK_PRIOR:
  708. data->key = LV_KEY_PREV;
  709. break;
  710. case VK_HOME:
  711. data->key = LV_KEY_HOME;
  712. break;
  713. case VK_END:
  714. data->key = LV_KEY_END;
  715. break;
  716. default:
  717. if (KeyboardValue >= 'A' && KeyboardValue <= 'Z')
  718. {
  719. KeyboardValue += 0x20;
  720. }
  721. data->key = (uint32_t)KeyboardValue;
  722. break;
  723. }
  724. }
  725. static void lv_win32_encoder_driver_read_callback(
  726. lv_indev_drv_t* indev_drv,
  727. lv_indev_data_t* data)
  728. {
  729. UNREFERENCED_PARAMETER(indev_drv);
  730. data->state = (lv_indev_state_t)(
  731. g_mousewheel_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
  732. data->enc_diff = g_mousewheel_value;
  733. g_mousewheel_value = 0;
  734. }
  735. static LRESULT CALLBACK lv_win32_window_message_callback(
  736. HWND hWnd,
  737. UINT uMsg,
  738. WPARAM wParam,
  739. LPARAM lParam)
  740. {
  741. switch (uMsg)
  742. {
  743. case WM_MOUSEMOVE:
  744. case WM_LBUTTONDOWN:
  745. case WM_LBUTTONUP:
  746. case WM_MBUTTONDOWN:
  747. case WM_MBUTTONUP:
  748. {
  749. g_mouse_value = lParam;
  750. if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
  751. {
  752. g_mouse_pressed = (uMsg == WM_LBUTTONDOWN);
  753. }
  754. else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
  755. {
  756. g_mousewheel_pressed = (uMsg == WM_MBUTTONDOWN);
  757. }
  758. return 0;
  759. }
  760. case WM_KEYDOWN:
  761. case WM_KEYUP:
  762. {
  763. g_keyboard_pressed = (uMsg == WM_KEYDOWN);
  764. g_keyboard_value = wParam;
  765. break;
  766. }
  767. case WM_MOUSEWHEEL:
  768. {
  769. g_mousewheel_value = -(GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA);
  770. break;
  771. }
  772. case WM_TOUCH:
  773. {
  774. UINT cInputs = LOWORD(wParam);
  775. HTOUCHINPUT hTouchInput = (HTOUCHINPUT)(lParam);
  776. PTOUCHINPUT pInputs = malloc(cInputs * sizeof(TOUCHINPUT));
  777. if (pInputs)
  778. {
  779. if (lv_win32_get_touch_input_info(
  780. hTouchInput,
  781. cInputs,
  782. pInputs,
  783. sizeof(TOUCHINPUT)))
  784. {
  785. for (UINT i = 0; i < cInputs; ++i)
  786. {
  787. POINT Point;
  788. Point.x = TOUCH_COORD_TO_PIXEL(pInputs[i].x);
  789. Point.y = TOUCH_COORD_TO_PIXEL(pInputs[i].y);
  790. if (!ScreenToClient(hWnd, &Point))
  791. {
  792. continue;
  793. }
  794. uint16_t x = (uint16_t)(Point.x & 0xffff);
  795. uint16_t y = (uint16_t)(Point.y & 0xffff);
  796. DWORD MousePressedMask =
  797. TOUCHEVENTF_MOVE | TOUCHEVENTF_DOWN;
  798. g_mouse_value = (y << 16) | x;
  799. g_mouse_pressed = (pInputs[i].dwFlags & MousePressedMask);
  800. }
  801. }
  802. free(pInputs);
  803. }
  804. lv_win32_close_touch_input_handle(hTouchInput);
  805. break;
  806. }
  807. case WM_DPICHANGED:
  808. {
  809. g_dpi_value = HIWORD(wParam);
  810. LPRECT SuggestedRect = (LPRECT)lParam;
  811. SetWindowPos(
  812. hWnd,
  813. NULL,
  814. SuggestedRect->left,
  815. SuggestedRect->top,
  816. SuggestedRect->right,
  817. SuggestedRect->bottom,
  818. SWP_NOZORDER | SWP_NOACTIVATE);
  819. RECT ClientRect;
  820. GetClientRect(hWnd, &ClientRect);
  821. int WindowWidth = MulDiv(
  822. g_display->driver->hor_res * WIN32DRV_MONITOR_ZOOM,
  823. g_dpi_value,
  824. USER_DEFAULT_SCREEN_DPI);
  825. int WindowHeight = MulDiv(
  826. g_display->driver->ver_res * WIN32DRV_MONITOR_ZOOM,
  827. g_dpi_value,
  828. USER_DEFAULT_SCREEN_DPI);
  829. SetWindowPos(
  830. hWnd,
  831. NULL,
  832. SuggestedRect->left,
  833. SuggestedRect->top,
  834. SuggestedRect->right + (WindowWidth - ClientRect.right),
  835. SuggestedRect->bottom + (WindowHeight - ClientRect.bottom),
  836. SWP_NOZORDER | SWP_NOACTIVATE);
  837. break;
  838. }
  839. case WM_DESTROY:
  840. PostQuitMessage(0);
  841. break;
  842. default:
  843. return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  844. }
  845. return 0;
  846. }
  847. static void lv_win32_message_handler(
  848. lv_timer_t* param)
  849. {
  850. UNREFERENCED_PARAMETER(param);
  851. MSG Message;
  852. BOOL Result = PeekMessageW(&Message, NULL, 0, 0, TRUE);
  853. if (Result != 0 && Result != -1)
  854. {
  855. TranslateMessage(&Message);
  856. DispatchMessageW(&Message);
  857. if (Message.message == WM_QUIT)
  858. {
  859. lv_win32_quit_signal = true;
  860. }
  861. }
  862. }
  863. #endif /*USE_WIN32DRV*/