Closed MouriNaruto closed 1 year ago
Very nice! In the arch/drivers branch it works like this:
lv_disp_t * disp = lv_sdl_window_create(w, h);
lv_indev_t * mouse = lv_sdl_mouse_create();
lv_indev_set_disp(mouse, disp);
lv_indev_t * mousewheel = lv_sdl_mousewheel_create();
lv_indev_set_disp(mousewheel, disp);
lv_indev_t * keyboard = lv_sdl_keyboard_create();
lv_indev_set_disp(keyboard, disp);
I think it fits well into your current API.
Let me now if I can merge it.
@kisvegabor
I think it's OK to merge with the new driver model to the arch/drivers branch. If you don't mind waiting for one or two weeks, I want to contribute the implementation with the new driver model to the arch/drivers branch directly because I think my implementation can be optimized with the new driver model, or you can merge them at first and I commit for some improvements via the further PRs if needed.
Note1: I have read the implementation of the new driver model and I think I can try something about unifying the implementations from windows simulator and windows port.
Note2: I don't know how to test with the new driver model.
I also hope this PR can be merged because it can enable current users using the multiple display support.
Kenji Mouri
@kisvegabor
If you want to merge this driver to new driver model by yourself directly. I hope the driver name should be win32
.
Kenji Mouri
Here is the screenshot for 16 displays with different LVGL demos.
@kisvegabor @wrgallo
Fix #255 and #256.
The implementation have almost been rewritten and provide some new APIs. But it still keeps the compatibility with the old usage.
Here is the snippet of the new usage.
#include <Windows.h> #include "resource.h" #if _MSC_VER >= 1200 // Disable compilation warnings. #pragma warning(push) // nonstandard extension used : bit field types other than int #pragma warning(disable:4214) // 'conversion' conversion from 'type1' to 'type2', possible loss of data #pragma warning(disable:4244) #endif #include "lvgl/lvgl.h" #include "lvgl/examples/lv_examples.h" #include "lvgl/demos/lv_demos.h" #include "lv_drivers/win32drv/win32drv.h" #if _MSC_VER >= 1200 // Restore compilation warnings. #pragma warning(pop) #endif #include <stdio.h> #include <process.h> HANDLE g_window_mutex = NULL; bool g_initialization_status = false; #define LVGL_SIMULATOR_MAXIMUM_DISPLAYS 16 static HWND g_display_window_handles[LVGL_SIMULATOR_MAXIMUM_DISPLAYS]; unsigned int __stdcall lv_win32_window_thread_entrypoint( void* raw_parameter) { size_t display_id = *(size_t*)(raw_parameter); HINSTANCE instance_handle = GetModuleHandleW(NULL); HICON icon_handle = LoadIconW(GetModuleHandleW(NULL), MAKEINTRESOURCE(IDI_LVGL)); lv_coord_t hor_res = 800; lv_coord_t ver_res = 450; wchar_t WindowTitle[256]; memset(WindowTitle, 0, sizeof(WindowTitle)); _snwprintf( WindowTitle, 256, L"LVGL Simulator for Windows Desktop (Display %d)", display_id); g_display_window_handles[display_id] = CreateWindowExW( WS_EX_CLIENTEDGE, LVGL_SIMULATOR_WINDOW_CLASS, WindowTitle, WS_OVERLAPPEDWINDOW & ~(WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME), CW_USEDEFAULT, 0, hor_res, ver_res, NULL, NULL, instance_handle, NULL); if (!g_display_window_handles[display_id]) { return 0; } SendMessageW( g_display_window_handles[display_id], WM_SETICON, TRUE, (LPARAM)icon_handle); SendMessageW( g_display_window_handles[display_id], WM_SETICON, FALSE, (LPARAM)icon_handle); ShowWindow(g_display_window_handles[display_id], SW_SHOW); UpdateWindow(g_display_window_handles[display_id]); g_initialization_status = true; SetEvent(g_window_mutex); MSG message; while (GetMessageW(&message, NULL, 0, 0)) { TranslateMessage(&message); DispatchMessageW(&message); } lv_win32_quit_signal = true; return 0; } bool dual_display_mode_initialization() { if (!lv_win32_init_window_class()) { return false; } for (size_t i = 0; i < LVGL_SIMULATOR_MAXIMUM_DISPLAYS; ++i) { g_initialization_status = false; g_window_mutex = CreateEventExW(NULL, NULL, 0, EVENT_ALL_ACCESS); _beginthreadex( NULL, 0, lv_win32_window_thread_entrypoint, &i, 0, NULL); WaitForSingleObjectEx(g_window_mutex, INFINITE, FALSE); CloseHandle(g_window_mutex); if (!g_initialization_status) { return false; } } lv_win32_window_context_t* context = (lv_win32_window_context_t*)( lv_win32_get_window_context(g_display_window_handles[0])); if (context) { lv_win32_pointer_device_object = context->mouse_device_object; lv_win32_keypad_device_object = context->keyboard_device_object; lv_win32_encoder_device_object = context->mousewheel_device_object; } lv_win32_add_all_input_devices_to_group(NULL); return true; } int main() { lv_init(); if (!dual_display_mode_initialization()) { return -1; } else { for (size_t i = 0; i < LVGL_SIMULATOR_MAXIMUM_DISPLAYS; ++i) { lv_win32_window_context_t* context = (lv_win32_window_context_t*)( lv_win32_get_window_context(g_display_window_handles[i])); if (context) { lv_disp_set_default(context->display_device_object); switch (i) { case 0: lv_demo_widgets(); break; case 1: lv_demo_benchmark(); break; case 2: lv_example_style_1(); break; case 3: lv_example_get_started_1(); break; case 4: lv_example_anim_1(); break; case 5: lv_example_style_2(); break; case 6: lv_example_get_started_2(); break; case 7: lv_example_anim_2(); break; case 8: lv_example_style_3(); break; case 9: lv_example_get_started_3(); break; case 10: lv_example_anim_3(); break; case 11: lv_example_style_4(); break; case 12: lv_example_style_5(); break; case 13: lv_example_style_6(); break; case 14: lv_example_imgfont_1(); break; case 15: lv_example_style_7(); break; default: break; } } } } while (!lv_win32_quit_signal) { lv_task_handler(); Sleep(1); } return 0; }
Kenji Mouri
It would be necessary to create other lv_win32_window_thread_entrypoint
implementation on the main
to be able to use multiple display and change the window title?
I know my suggested implementation had a lot of room for improvement, but the option to use a simple function to create and setup the display window would be really useful, if the older function would be kept for compatibility we could create a new one.
/**
* @brief Create a display on WIN32
* @param[in] hor_res Horizontal Resolution
* @param[in] ver_res Vertical Resolution
* @param[in] screen_title Title of the windows screen or NULL to use default
* @param[in] icon_handle Icon for the windows screen
* @return pointer to the new display or NULL if failed
*/
EXTERN_C lv_disp_t* lv_win32_create_disp(
lv_coord_t hor_res,
lv_coord_t ver_res,
const wchar_t* screen_title,
HICON icon_handle );
@wrgallo-navitas
It would be necessary to create other lv_win32_window_thread_entrypoint implementation on the main to be able to use multiple display and change the window title?
Of course, it's not necessary. But I use that example because I want to show flexibility. You can make all windows and LVGL scheduler in the main thread. I use multithread for making offload tasks from the main thread to improve the performance.
I know my https://github.com/lvgl/lv_drivers/pull/257 had a lot of room for improvement, but the option to use a simple function to create and setup the display window would be really useful, if the older function would be kept for compatibility we could create a new one.
I will follow your suggestion to provide a simple function to create a display instance.
Kenji Mouri
@wrgallo-navitas
I have add a new API to simplify them.
@kisvegabor
Ping for progress.
Kenji Mouri
Great work, just a question:
Why not always use GetModuleHandleW(NULL)
for instance_handle
and SW_SHOW
for show_window_mode
?
EXTERN_C HWND lv_win32_create_display_window(
const wchar_t* window_title,
lv_coord_t hor_res,
lv_coord_t ver_res,
HINSTANCE instance_handle, // Always use GetModuleHandleW(NULL) ?
HICON icon_handle,
int show_window_mode // why not fix with SW_SHOW ?
);
@wrgallo-navitas
I have add a new API to simplify them.
@kisvegabor
Ping for progress.
Kenji Mouri
@wrgallo-navitas
I have considered more. (For example, somebody doesn't want to show some simulator display windows for doing something headless so providing show_window_mode is useful. Or they want to use win32drv instance in a dll so providing instance_handle is useful for them to manage the resources.)
Kenji Mouri
Sorry, somehow I missed your previous comment. I merge it now.
We are updating the MicroPython binding for arch/drivers
. So I hope it will be merged soon too. Until that feel free to send PRs to arch/drivers
. It'd be great to see how it work with various platforms and concepts.
@MouriNaruto I have just tested the commit and had troubles making it work.
This works:
int main()
{
lv_init();
HICON icoLvgl = LoadIconW(GetModuleHandleW(NULL), MAKEINTRESOURCE(IDI_LVGL));
lv_win32_init(GetModuleHandleW(NULL), SW_SHOW, 800, 480, icoLvgl);
lv_demo_widgets();
while (!lv_win32_quit_signal) {
lv_task_handler();
Sleep(1);
}
return 0;
}
But this does not:
int main()
{
lv_init();
HICON icoLvgl = LoadIconW(GetModuleHandleW(NULL), MAKEINTRESOURCE(IDI_LVGL));
// lv_win32_init_window_class(); // Removing this comment, still does not make it work!
lv_win32_create_display_window(L"My title", 800, 480, GetModuleHandleW(NULL), icoLvgl, SW_SHOW);
lv_demo_widgets();
while (!lv_win32_quit_signal) {
lv_task_handler();
Sleep(1);
}
return 0;
}
Since it is not intuitive, could you please guide me on how to use lv_win32_create_display_window
?
Here is the screenshot for 16 displays with different LVGL demos.
@kisvegabor @wrgallo
Fix #255 and #256.
The implementation have almost been rewritten and provide some new APIs. But it still keeps the compatibility with the old usage.
Here is the snippet of the new usage.
Kenji Mouri