From 9accf4c66667fbf5495095ecb40ba95aebca12ba Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Thu, 9 Mar 2023 17:38:41 +0100 Subject: [PATCH 1/4] [ui, win32] - change coord system of gl canvas to match ui - change mouse coordinate system to match ui - fix mouse delta --- examples/ui_style_test/main.c | 2 +- src/glsl_shaders.h | 6 +- src/glsl_shaders/blit_vertex.glsl | 4 +- src/ui.c | 15 ++--- src/ui.h | 99 +++++++++++++++---------------- src/wgl_surface.c | 4 +- src/win32_app.c | 58 +++++++++++++++--- 7 files changed, 115 insertions(+), 73 deletions(-) diff --git a/examples/ui_style_test/main.c b/examples/ui_style_test/main.c index 743408e..2149f7a 100644 --- a/examples/ui_style_test/main.c +++ b/examples/ui_style_test/main.c @@ -450,7 +450,7 @@ int main() ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 300}, .size.height = {UI_SIZE_TEXT}}, UI_STYLE_SIZE); - static str8 text = {}; + static str8 text = {0}; ui_text_box_result res = ui_text_box("textbox", mem_scratch(), text); if(res.changed) { diff --git a/src/glsl_shaders.h b/src/glsl_shaders.h index f61d119..6745a33 100644 --- a/src/glsl_shaders.h +++ b/src/glsl_shaders.h @@ -2,7 +2,7 @@ * * file: glsl_shaders.h * note: string literals auto-generated by embed_text.py -* date: 03/032023 +* date: 09/032023 * **********************************************************************/ #ifndef __GLSL_SHADERS_H__ @@ -35,11 +35,13 @@ const char* glsl_blit_vertex = "\n" "void main()\n" "{\n" +" /* generate (0, 0) (1, 0) (1, 1) (1, 1) (0, 1) (0, 0)*/\n" +"\n" " float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u);\n" " float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u);\n" "\n" " gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);\n" -" uv = vec2(x, y);\n" +" uv = vec2(x, 1-y);\n" "}\n"; //NOTE: string imported from src\glsl_shaders\blit_fragment.glsl diff --git a/src/glsl_shaders/blit_vertex.glsl b/src/glsl_shaders/blit_vertex.glsl index 063dc03..a88b757 100644 --- a/src/glsl_shaders/blit_vertex.glsl +++ b/src/glsl_shaders/blit_vertex.glsl @@ -5,9 +5,11 @@ out vec2 uv; void main() { + /* generate (0, 0) (1, 0) (1, 1) (1, 1) (0, 1) (0, 0)*/ + float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u); float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u); gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f); - uv = vec2(x, y); + uv = vec2(x, 1-y); } diff --git a/src/ui.c b/src/ui.c index a22e87e..b07a68b 100644 --- a/src/ui.c +++ b/src/ui.c @@ -6,6 +6,7 @@ * @revision: * *****************************************************************/ +#include"platform.h" #include"memory.h" #include"hash.h" #include"platform_clock.h" @@ -33,7 +34,7 @@ static ui_style UI_STYLE_DEFAULTS = // context //----------------------------------------------------------------------------- -const u32 UI_MAX_INPUT_CHAR_PER_FRAME = 64; +enum { UI_MAX_INPUT_CHAR_PER_FRAME = 64 }; typedef struct ui_input_text { @@ -60,7 +61,7 @@ typedef struct ui_tag_elt ui_tag tag; } ui_tag_elt; -const u64 UI_BOX_MAP_BUCKET_COUNT = 1024; +enum { UI_BOX_MAP_BUCKET_COUNT = 1024 }; typedef struct ui_context { @@ -94,8 +95,8 @@ typedef struct ui_context } ui_context; -__thread ui_context __uiThreadContext = {0}; -__thread ui_context* __uiCurrentContext = 0; +mp_thread_local ui_context __uiThreadContext = {0}; +mp_thread_local ui_context* __uiCurrentContext = 0; ui_context* ui_get_context(void) { @@ -240,7 +241,7 @@ ui_key ui_key_make_str8(str8 string) seed = parent->key.hash; } - ui_key key = {}; + ui_key key = {0}; key.hash = mp_hash_aes_string_seed(string, seed); return(key); } @@ -1909,7 +1910,7 @@ ui_sig ui_menu_button(const char* name) |UI_STYLE_LAYOUT_MARGIN_X |UI_STYLE_BG_COLOR); - ui_pattern pattern = {}; + ui_pattern pattern = {0}; ui_pattern_push(&ui->frameArena, &pattern, (ui_selector){.kind = UI_SEL_STATUS, .status = UI_HOVER}); ui_style style = {.bgColor = {0, 0, 1, 1}}; @@ -1937,7 +1938,7 @@ str32 ui_edit_replace_selection_with_codepoints(ui_context* ui, str32 codepoints str32 before = str32_slice(codepoints, 0, start); str32 after = str32_slice(codepoints, end, codepoints.len); - str32_list list = {}; + str32_list list = {0}; str32_list_push(&ui->frameArena, &list, before); str32_list_push(&ui->frameArena, &list, input); str32_list_push(&ui->frameArena, &list, after); diff --git a/src/ui.h b/src/ui.h index fda363a..6434676 100644 --- a/src/ui.h +++ b/src/ui.h @@ -327,24 +327,24 @@ typedef struct ui_context ui_context; //------------------------------------------------------------------------------------- // UI context initialization and frame cycle //------------------------------------------------------------------------------------- -void ui_init(void); -ui_context* ui_get_context(void); -void ui_set_context(ui_context* context); +MP_API void ui_init(void); +MP_API ui_context* ui_get_context(void); +MP_API void ui_set_context(ui_context* context); -void ui_begin_frame(ui_style* defaultStyle, ui_style_mask mask); -void ui_end_frame(void); -void ui_draw(void); +MP_API void ui_begin_frame(ui_style* defaultStyle, ui_style_mask mask); +MP_API void ui_end_frame(void); +MP_API void ui_draw(void); #define ui_frame(s, m) defer_loop(ui_begin_frame((s), (m)), ui_end_frame()) //------------------------------------------------------------------------------------- // Box keys //------------------------------------------------------------------------------------- -ui_key ui_key_make_str8(str8 string); -ui_key ui_key_make_path(str8_list path); +MP_API ui_key ui_key_make_str8(str8 string); +MP_API ui_key ui_key_make_path(str8_list path); -ui_box* ui_box_lookup_key(ui_key key); -ui_box* ui_box_lookup_str8(str8 string); +MP_API ui_box* ui_box_lookup_key(ui_key key); +MP_API ui_box* ui_box_lookup_str8(str8 string); // C-string helper #define ui_key_make(s) ui_key_make_str8(STR8(s)) @@ -353,17 +353,17 @@ ui_box* ui_box_lookup_str8(str8 string); //------------------------------------------------------------------------------------- // Box hierarchy building //------------------------------------------------------------------------------------- -ui_box* ui_box_make_str8(str8 string, ui_flags flags); -ui_box* ui_box_begin_str8(str8 string, ui_flags flags); +MP_API ui_box* ui_box_make_str8(str8 string, ui_flags flags); +MP_API ui_box* ui_box_begin_str8(str8 string, ui_flags flags); -ui_box* ui_box_end(void); +MP_API ui_box* ui_box_end(void); #define ui_container(name, flags) defer_loop(ui_box_begin(name, flags), ui_box_end()) -void ui_box_push(ui_box* box); -void ui_box_pop(void); -ui_box* ui_box_top(void); +MP_API void ui_box_push(ui_box* box); +MP_API void ui_box_pop(void); +MP_API ui_box* ui_box_top(void); -void ui_box_set_render_proc(ui_box* box, ui_box_render_proc proc, void* data); +MP_API void ui_box_set_render_proc(ui_box* box, ui_box_render_proc proc, void* data); // C-string helpers #define ui_box_lookup(s) ui_box_lookup_str8(STR8(s)) @@ -373,24 +373,24 @@ void ui_box_set_render_proc(ui_box* box, ui_box_render_proc proc, void* data); //------------------------------------------------------------------------------------- // Box status and signals //------------------------------------------------------------------------------------- -bool ui_box_closed(ui_box* box); -void ui_box_set_closed(ui_box* box, bool closed); +MP_API bool ui_box_closed(ui_box* box); +MP_API void ui_box_set_closed(ui_box* box, bool closed); -bool ui_box_active(ui_box* box); -void ui_box_activate(ui_box* box); -void ui_box_deactivate(ui_box* box); +MP_API bool ui_box_active(ui_box* box); +MP_API void ui_box_activate(ui_box* box); +MP_API void ui_box_deactivate(ui_box* box); -bool ui_box_hot(ui_box* box); -void ui_box_set_hot(ui_box* box, bool hot); +MP_API bool ui_box_hot(ui_box* box); +MP_API void ui_box_set_hot(ui_box* box, bool hot); -ui_sig ui_box_sig(ui_box* box); +MP_API ui_sig ui_box_sig(ui_box* box); //------------------------------------------------------------------------------------- // Tagging //------------------------------------------------------------------------------------- -ui_tag ui_tag_make_str8(str8 string); -void ui_tag_box_str8(ui_box* box, str8 string); -void ui_tag_next_str8(str8 string); +MP_API ui_tag ui_tag_make_str8(str8 string); +MP_API void ui_tag_box_str8(ui_box* box, str8 string); +MP_API void ui_tag_next_str8(str8 string); // C-string helpers #define ui_tag_make(s) ui_tag_make_str8(STR8(s)) @@ -403,15 +403,15 @@ void ui_tag_next_str8(str8 string); //NOTE: styling API //WARN: You can use a pattern in multiple rules, but be aware that a pattern is references an underlying list of selectors, // hence pushing to a pattern also modifies rules in which the pattern was previously used! -void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask); +MP_API void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask); -void ui_pattern_push(mem_arena* arena, ui_pattern* pattern, ui_selector selector); -ui_pattern ui_pattern_all(void); -ui_pattern ui_pattern_owner(void); +MP_API void ui_pattern_push(mem_arena* arena, ui_pattern* pattern, ui_selector selector); +MP_API ui_pattern ui_pattern_all(void); +MP_API ui_pattern ui_pattern_owner(void); -void ui_style_next(ui_style* style, ui_style_mask mask); -void ui_style_match_before(ui_pattern pattern, ui_style* style, ui_style_mask mask); -void ui_style_match_after(ui_pattern pattern, ui_style* style, ui_style_mask mask); +MP_API void ui_style_next(ui_style* style, ui_style_mask mask); +MP_API void ui_style_match_before(ui_pattern pattern, ui_style* style, ui_style_mask mask); +MP_API void ui_style_match_after(ui_pattern pattern, ui_style* style, ui_style_mask mask); //------------------------------------------------------------------------- // Basic widget helpers @@ -426,30 +426,27 @@ enum { UI_STYLE_TAG_MENU }; -ui_sig ui_label(const char* label); +MP_API ui_sig ui_label(const char* label); +MP_API ui_sig ui_button(const char* label); +MP_API ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue); -ui_sig ui_button(const char* label); - -ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue); -ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue); - -void ui_panel_begin(const char* name, ui_flags flags); -void ui_panel_end(void); +MP_API void ui_panel_begin(const char* name, ui_flags flags); +MP_API void ui_panel_end(void); #define ui_panel(s, f) defer_loop(ui_panel_begin(s, f), ui_panel_end()) -ui_sig ui_tooltip_begin(const char* name); -void ui_tooltip_end(void); +MP_API ui_sig ui_tooltip_begin(const char* name); +MP_API void ui_tooltip_end(void); #define ui_tooltip(name) defer_loop(ui_tooltip_begin(name), ui_tooltip_end()) -void ui_menu_bar_begin(const char* label); -void ui_menu_bar_end(void); +MP_API void ui_menu_bar_begin(const char* label); +MP_API void ui_menu_bar_end(void); #define ui_menu_bar(name) defer_loop(ui_menu_bar_begin(name), ui_menu_bar_end()) -void ui_menu_begin(const char* label); -void ui_menu_end(void); +MP_API void ui_menu_begin(const char* label); +MP_API void ui_menu_end(void); #define ui_menu(name) defer_loop(ui_menu_begin(name), ui_menu_end()) -ui_sig ui_menu_button(const char* name); +MP_API ui_sig ui_menu_button(const char* name); typedef struct ui_text_box_result { @@ -459,7 +456,7 @@ typedef struct ui_text_box_result }ui_text_box_result; -ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text); +MP_API ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text); #ifdef __cplusplus } // extern "C" diff --git a/src/wgl_surface.c b/src/wgl_surface.c index 43a82d7..e21019b 100644 --- a/src/wgl_surface.c +++ b/src/wgl_surface.c @@ -176,7 +176,7 @@ void* mg_wgl_get_proc(const char* name) mg_surface_data* mg_wgl_surface_create_for_window(mp_window window) { - mg_surface* surface = 0; + mg_wgl_surface* surface = 0; mp_window_data* windowData = mp_window_ptr_from_handle(window); if(windowData) @@ -184,7 +184,7 @@ mg_surface_data* mg_wgl_surface_create_for_window(mp_window window) wgl_init(); //NOTE: fill surface data and load api - mg_wgl_surface* surface = malloc_type(mg_wgl_surface); + surface = malloc_type(mg_wgl_surface); if(surface) { mg_surface_init_for_window((mg_surface_data*)surface, windowData); diff --git a/src/win32_app.c b/src/win32_app.c index 206dc17..91e5f07 100644 --- a/src/win32_app.c +++ b/src/win32_app.c @@ -177,9 +177,9 @@ static mp_key_code mp_convert_win32_key(int code) return(__mpApp.keyCodes[code]); } -static mp_key_mods mp_get_mod_keys() +static mp_keymod_flags mp_get_mod_keys() { - mp_key_mods mods = 0; + mp_keymod_flags mods = 0; if(GetKeyState(VK_SHIFT) & 0x8000) { mods |= MP_KEYMOD_SHIFT; @@ -218,7 +218,7 @@ static void process_mouse_event(mp_window_data* window, mp_key_action action, mp } } - mp_update_key_state(&__mpApp.inputState.mouse.buttons[button], action == MP_KEY_PRESS); + mp_update_key_state(&__mpApp.inputState.mouse.buttons[button], action); //TODO click/double click mp_event event = {0}; @@ -236,7 +236,7 @@ static void process_wheel_event(mp_window_data* window, f32 x, f32 y) mp_event event = {0}; event.window = mp_window_handle_from_ptr(window); event.type = MP_EVENT_MOUSE_WHEEL; - event.move.deltaX = -x/30.0f; + event.move.deltaX = x/30.0f; event.move.deltaY = y/30.0f; event.move.mods = mp_get_mod_keys(); @@ -385,7 +385,7 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam) event.window = mp_window_handle_from_ptr(mpWindow); event.type = MP_EVENT_MOUSE_MOVE; event.move.x = LOWORD(lParam) / scaling; - event.move.y = (rect.bottom - HIWORD(lParam)) / scaling; + event.move.y = HIWORD(lParam) / scaling; if(__mpApp.inputState.mouse.posValid) { @@ -414,8 +414,8 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam) .move.y = event.move.y}; mp_queue_event(&enter); } - __mpApp.inputState.mouse.pos.x = event.move.x; - __mpApp.inputState.mouse.pos.y = event.move.y; + + mp_update_mouse_move(event.move.x, event.move.y, event.move.deltaX, event.move.deltaY); mp_queue_event(&event); } break; @@ -515,13 +515,14 @@ void mp_request_quit() void mp_pump_events(f64 timeout) { + __mpApp.inputState.frameCounter++; + MSG message; while(PeekMessage(&message, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&message); DispatchMessage(&message); } - __mpApp.inputState.frameCounter++; } //-------------------------------------------------------------------- @@ -777,6 +778,33 @@ mp_rect mp_window_get_content_rect(mp_window window) return(rect); } +//-------------------------------------------------------------------------------- +// clipboard functions +//-------------------------------------------------------------------------------- + +MP_API void mp_clipboard_clear(void) +{ + //TODO +} + +MP_API void mp_clipboard_set_string(str8 string) +{ + //TODO +} + +MP_API str8 mp_clipboard_get_string(mem_arena* arena) +{ + //TODO + return((str8){0}); +} + +MP_API str8 mp_clipboard_copy_string(str8 backing) +{ + //TODO + return((str8){0}); +} + + //-------------------------------------------------------------------------------- // win32 surfaces //-------------------------------------------------------------------------------- @@ -869,6 +897,18 @@ void mg_surface_cleanup(mg_surface_data* surface) DestroyWindow(surface->layer.hWnd); } +LRESULT LayerWinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam) +{ + if(message == WM_NCHITTEST) + { + return(HTTRANSPARENT); + } + else + { + return(DefWindowProc(windowHandle, message, wParam, lParam)); + } +} + void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window) { surface->contentsScaling = mg_win32_surface_contents_scaling; @@ -880,7 +920,7 @@ void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window //NOTE(martin): create a child window for the surface WNDCLASS layerWindowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, - .lpfnWndProc = DefWindowProc, + .lpfnWndProc = LayerWinProc, .hInstance = GetModuleHandleW(NULL), .lpszClassName = "layer_window_class", .hCursor = LoadCursor(0, IDC_ARROW)}; From cae8666561feb55c83a6af1a469a807e9f38b51a Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Thu, 9 Mar 2023 18:03:27 +0100 Subject: [PATCH 2/4] [ui, win32] Fixed char input and modifier keys --- src/mp_app.c | 5 +++++ src/osx_app.m | 5 ----- src/win32_app.c | 10 ++++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/mp_app.c b/src/mp_app.c index cb9c4cd..a721b39 100644 --- a/src/mp_app.c +++ b/src/mp_app.c @@ -172,6 +172,11 @@ static void mp_update_key_state(mp_key_state* key, mp_key_action action) } } +static void mp_update_key_mods(mp_keymod_flags mods) +{ + __mpApp.inputState.keyboard.mods = mods; +} + static void mp_update_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY) { u64 frameCounter = __mpApp.inputState.frameCounter; diff --git a/src/osx_app.m b/src/osx_app.m index 8f49982..68bd9c5 100644 --- a/src/osx_app.m +++ b/src/osx_app.m @@ -369,11 +369,6 @@ void mp_install_keyboard_layout_listener() object:nil]; } -static void mp_update_key_mods(mp_keymod_flags mods) -{ - __mpApp.inputState.keyboard.mods = mods; -} - //--------------------------------------------------------------- // Application and app delegate //--------------------------------------------------------------- diff --git a/src/win32_app.c b/src/win32_app.c index 91e5f07..9e74efb 100644 --- a/src/win32_app.c +++ b/src/win32_app.c @@ -455,6 +455,9 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam) event.key.code = mp_convert_win32_key(HIWORD(lParam) & 0x1ff); event.key.mods = mp_get_mod_keys(); mp_queue_event(&event); + + mp_update_key_mods(event.key.mods); + mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], event.key.action); } break; case WM_KEYUP: @@ -467,6 +470,10 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam) event.key.code = mp_convert_win32_key(HIWORD(lParam) & 0x1ff); event.key.mods = mp_get_mod_keys(); mp_queue_event(&event); + + mp_update_key_mods(event.key.mods); + mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], event.key.action); + } break; case WM_CHAR: @@ -478,6 +485,9 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam) str8 seq = utf8_encode(event.character.sequence, event.character.codepoint); event.character.seqLen = seq.len; mp_queue_event(&event); + + mp_update_text(event.character.codepoint); + } break; case WM_DROPFILES: From 359e08b0a860974fe8514c7c5f9603891926e7ff Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Thu, 9 Mar 2023 18:09:04 +0100 Subject: [PATCH 3/4] [ui] set text box cursor to the same color as text --- src/ui.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui.c b/src/ui.c index b07a68b..621b0fd 100644 --- a/src/ui.c +++ b/src/ui.c @@ -2321,8 +2321,8 @@ void ui_text_box_render(ui_box* box, void* data) { f32 caretX = box->rect.x + textMargin - beforeBox.w + beforeSelectBox.w; f32 caretY = textTop; - mg_set_color_rgba(0, 0, 0, 1); - mg_rectangle_fill(caretX, caretY, 2, lineHeight); + mg_set_color(style->color); + mg_rectangle_fill(caretX, caretY, 1, lineHeight); } mg_set_font(style->font); mg_set_font_size(style->fontSize); From 137a75540bb74e73c735538c211e547081ea8c65 Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Thu, 9 Mar 2023 19:44:55 +0100 Subject: [PATCH 4/4] [win32] implemented string clipboard functions --- src/ui.c | 14 +++++++--- src/win32_app.c | 72 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/src/ui.c b/src/ui.c index 621b0fd..94365d9 100644 --- a/src/ui.c +++ b/src/ui.c @@ -2005,6 +2005,12 @@ typedef struct ui_edit_command } ui_edit_command; +#if OS_WIN64 + #define OS_COPY_PASTE_MOD MP_KEYMOD_CTRL +#elif OS_MACOS + #define OS_COPY_PAST_MOD MP_KEYMOD_CMD +#endif + const ui_edit_command UI_EDIT_COMMANDS[] = { //NOTE(martin): move one left { @@ -2097,7 +2103,7 @@ const ui_edit_command UI_EDIT_COMMANDS[] = { //NOTE(martin): select all { .key = MP_KEY_Q, - .mods = MP_KEYMOD_CMD, + .mods = OS_COPY_PASTE_MOD, .operation = UI_EDIT_SELECT_ALL, .move = UI_EDIT_MOVE_NONE }, @@ -2118,21 +2124,21 @@ const ui_edit_command UI_EDIT_COMMANDS[] = { //NOTE(martin): cut { .key = MP_KEY_X, - .mods = MP_KEYMOD_CMD, + .mods = OS_COPY_PASTE_MOD, .operation = UI_EDIT_CUT, .move = UI_EDIT_MOVE_NONE }, //NOTE(martin): copy { .key = MP_KEY_C, - .mods = MP_KEYMOD_CMD, + .mods = OS_COPY_PASTE_MOD, .operation = UI_EDIT_COPY, .move = UI_EDIT_MOVE_NONE }, //NOTE(martin): paste { .key = MP_KEY_V, - .mods = MP_KEYMOD_CMD, + .mods = OS_COPY_PASTE_MOD, .operation = UI_EDIT_PASTE, .move = UI_EDIT_MOVE_NONE } diff --git a/src/win32_app.c b/src/win32_app.c index 9e74efb..e19ade4 100644 --- a/src/win32_app.c +++ b/src/win32_app.c @@ -478,16 +478,18 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam) case WM_CHAR: { - mp_event event = {0}; - event.window = mp_window_handle_from_ptr(mpWindow); - event.type = MP_EVENT_KEYBOARD_CHAR; - event.character.codepoint = (utf32)wParam; - str8 seq = utf8_encode(event.character.sequence, event.character.codepoint); - event.character.seqLen = seq.len; - mp_queue_event(&event); - - mp_update_text(event.character.codepoint); + if((u32)wParam >= 32) + { + mp_event event = {0}; + event.window = mp_window_handle_from_ptr(mpWindow); + event.type = MP_EVENT_KEYBOARD_CHAR; + event.character.codepoint = (utf32)wParam; + str8 seq = utf8_encode(event.character.sequence, event.character.codepoint); + event.character.seqLen = seq.len; + mp_queue_event(&event); + mp_update_text(event.character.codepoint); + } } break; case WM_DROPFILES: @@ -794,18 +796,62 @@ mp_rect mp_window_get_content_rect(mp_window window) MP_API void mp_clipboard_clear(void) { - //TODO + if(OpenClipboard(NULL)) + { + EmptyClipboard(); + CloseClipboard(); + } } MP_API void mp_clipboard_set_string(str8 string) { - //TODO + if(OpenClipboard(NULL)) + { + EmptyClipboard(); + + int wideCount = MultiByteToWideChar(CP_UTF8, 0, string.ptr, string.len, 0, 0); + HANDLE handle = GlobalAlloc(GMEM_MOVEABLE, (wideCount+1)*sizeof(wchar_t)); + if(handle) + { + char* memory = GlobalLock(handle); + if(memory) + { + MultiByteToWideChar(CP_UTF8, 0, string.ptr, string.len, (wchar_t*)memory, wideCount); + ((wchar_t*)memory)[wideCount] = '\0'; + + GlobalUnlock(handle); + SetClipboardData(CF_UNICODETEXT, handle); + } + } + CloseClipboard(); + } } MP_API str8 mp_clipboard_get_string(mem_arena* arena) { - //TODO - return((str8){0}); + str8 string = {0}; + + if(OpenClipboard(NULL)) + { + HANDLE handle = GetClipboardData(CF_UNICODETEXT); + if(handle) + { + char* memory = GlobalLock(handle); + if(memory) + { + u64 size = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)memory, -1, 0, 0, 0, 0); + if(size) + { + string.ptr = mem_arena_alloc(arena, size); + string.len = size - 1; + WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)memory, -1, string.ptr, size, 0, 0); + GlobalUnlock(handle); + } + } + } + CloseClipboard(); + } + return(string); } MP_API str8 mp_clipboard_copy_string(str8 backing)