Minimal clipboard handling #95
|
@ -333,7 +333,10 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
|
|||
OC_UI_STYLE_LAYOUT_SPACING);
|
||||
oc_ui_container("buttons", 0)
|
||||
{
|
||||
oc_ui_button("Button A");
|
||||
if(oc_ui_button("Break the law").clicked)
|
||||
{
|
||||
oc_clipboard_set_string((oc_str8)OC_STR8_LIT("Check out my cool website"));
|
||||
}
|
||||
oc_ui_button("Button B");
|
||||
oc_ui_button("Button C");
|
||||
oc_ui_button("Button D");
|
||||
|
|
|
@ -133,7 +133,6 @@ def bindgen(apiName, spec, **kwargs):
|
|||
s += '\t\tOC_ASSERT((char*)__retPtr + sizeof(' + retTypeCName + ') <= ((char*)_mem + m3_GetMemorySize(runtime)), "return pointer is out of bounds");\n'
|
||||
s += '\t}\n'
|
||||
|
||||
|
||||
for argIndex, arg in enumerate(decl['args']):
|
||||
|
||||
argName = arg['name']
|
||||
|
|
|
@ -58,6 +58,7 @@ typedef enum
|
|||
OC_EVENT_MOUSE_WHEEL,
|
||||
OC_EVENT_MOUSE_ENTER,
|
||||
OC_EVENT_MOUSE_LEAVE,
|
||||
OC_EVENT_CLIPBOARD_PASTE,
|
||||
OC_EVENT_WINDOW_RESIZE,
|
||||
OC_EVENT_WINDOW_MOVE,
|
||||
OC_EVENT_WINDOW_FOCUS,
|
||||
|
@ -479,6 +480,8 @@ void oc_window_set_size(oc_vec2 size);
|
|||
void ORCA_IMPORT(oc_request_quit)(void);
|
||||
oc_key_code ORCA_IMPORT(oc_scancode_to_keycode)(oc_scan_code scanCode);
|
||||
|
||||
void oc_clipboard_set_string(oc_str8 string);
|
||||
|
||||
#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1243,6 +1243,7 @@ void oc_clipboard_set_string(oc_str8 string)
|
|||
|
||||
NSString* nsString = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
|
||||
NSPasteboard* pb = [NSPasteboard generalPasteboard];
|
||||
[pb clearContents];
|
||||
[pb writeObjects:[[NSArray alloc] initWithObjects:nsString, nil]];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "orca.h"
|
||||
|
||||
#include "runtime.h"
|
||||
#include "runtime_clipboard.c"
|
||||
#include "runtime_io.c"
|
||||
#include "runtime_memory.c"
|
||||
|
||||
|
@ -117,6 +118,16 @@ void oc_bridge_window_set_size(oc_vec2 size)
|
|||
oc_window_set_content_size(__orcaApp.window, size);
|
||||
}
|
||||
|
||||
oc_wasm_str8 oc_bridge_clipboard_get_string(oc_wasm_addr wasmArena)
|
||||
{
|
||||
return oc_runtime_clipboard_get_string(&__orcaApp.clipboard, wasmArena);
|
||||
}
|
||||
|
||||
void oc_bridge_clipboard_set_string(oc_wasm_str8 value)
|
||||
{
|
||||
oc_runtime_clipboard_set_string(&__orcaApp.clipboard, value);
|
||||
}
|
||||
|
||||
void oc_bridge_log(oc_log_level level,
|
||||
int fileLen,
|
||||
char* file,
|
||||
|
@ -553,7 +564,6 @@ i32 orca_runloop(void* user)
|
|||
oc_event* event = 0;
|
||||
while((event = oc_next_event(oc_scratch())) != 0)
|
||||
{
|
||||
|
||||
if(app->debugOverlay.show)
|
||||
{
|
||||
oc_ui_process_event(event);
|
||||
|
@ -561,19 +571,41 @@ i32 orca_runloop(void* user)
|
|||
|
||||
if(exports[OC_EXPORT_RAW_EVENT])
|
||||
{
|
||||
#ifndef M3_BIG_ENDIAN
|
||||
oc_event* eventPtr = (oc_event*)oc_wasm_address_to_ptr(app->env.rawEventOffset, sizeof(oc_event));
|
||||
memcpy(eventPtr, event, sizeof(*event));
|
||||
|
||||
const void* args[1] = { &app->env.rawEventOffset };
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_RAW_EVENT], 1, args);
|
||||
if(res)
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
oc_event* clipboardEvent = oc_runtime_clipboard_process_event_begin(&__orcaApp.clipboard, scratch.arena, event);
|
||||
oc_event* events[2];
|
||||
u64 eventsCount;
|
||||
if(clipboardEvent != 0)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
|
||||
events[0] = clipboardEvent;
|
||||
events[1] = event;
|
||||
eventsCount = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
events[0] = event;
|
||||
eventsCount = 1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < eventsCount; i++)
|
||||
{
|
||||
#ifndef M3_BIG_ENDIAN
|
||||
oc_event* eventPtr = (oc_event*)oc_wasm_address_to_ptr(app->env.rawEventOffset, sizeof(oc_event));
|
||||
memcpy(eventPtr, events[i], sizeof(*events[i]));
|
||||
|
||||
const void* args[1] = { &app->env.rawEventOffset };
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_RAW_EVENT], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
#else
|
||||
oc_log_error("oc_on_raw_event() is not supported on big endian platforms");
|
||||
oc_log_error("oc_on_raw_event() is not supported on big endian platforms");
|
||||
#endif
|
||||
}
|
||||
|
||||
oc_runtime_clipboard_process_event_end(&__orcaApp.clipboard);
|
||||
oc_scratch_end(scratch);
|
||||
}
|
||||
|
||||
switch(event->type)
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#define __RUNTIME_H_
|
||||
|
||||
#include "platform/platform_io_internal.h"
|
||||
#include "runtime_memory.h"
|
||||
#include "runtime_clipboard.h"
|
||||
|
||||
#include "m3_compile.h"
|
||||
#include "m3_env.h"
|
||||
|
@ -121,6 +123,7 @@ typedef struct oc_runtime
|
|||
|
||||
oc_wasm_env env;
|
||||
|
||||
oc_runtime_clipboard clipboard;
|
||||
} oc_runtime;
|
||||
|
||||
oc_runtime* oc_runtime_get(void);
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* Orca
|
||||
* Copyright 2023 Martin Fouilleul and the Orca project contributors
|
||||
* See LICENSE.txt for licensing information
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "runtime_clipboard.h"
|
||||
|
||||
#if OC_PLATFORM_WINDOWS || OC_PLATFORM_MACOS
|
||||
|
||||
oc_wasm_str8 oc_runtime_clipboard_get_string(oc_runtime_clipboard* clipboard, oc_wasm_addr wasmArena)
|
||||
{
|
||||
oc_wasm_str8 result = { 0 };
|
||||
if(clipboard->isGetAllowed)
|
||||
{
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
oc_str8 value = oc_clipboard_get_string(scratch.arena);
|
||||
oc_wasm_addr valueAddr = oc_wasm_arena_push(wasmArena, value.len);
|
||||
char* valuePtr = (char*)oc_wasm_address_to_ptr(valueAddr, value.len);
|
||||
memcpy(valuePtr, value.ptr, value.len);
|
||||
oc_scratch_end(scratch);
|
||||
result = (oc_wasm_str8){ .ptr = valueAddr,
|
||||
.len = value.len };
|
||||
}
|
||||
else
|
||||
{
|
||||
oc_log_warning("Clipboard contents can only be get from within the paste event handler\n");
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static f64 OC_CLIPBOARD_SET_TIMEOUT = 1;
|
||||
|
||||
void oc_runtime_clipboard_set_string(oc_runtime_clipboard* clipboard, oc_wasm_str8 value)
|
||||
{
|
||||
f64 time = oc_clock_time(OC_CLOCK_MONOTONIC);
|
||||
if(time < clipboard->setAllowedUntil)
|
||||
{
|
||||
oc_str8 nativeValue = oc_wasm_str8_to_native(value);
|
||||
oc_clipboard_set_string(nativeValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
oc_log_warning("Clipboard contents can only be set within %f second(s) of a paste shortcut press\n", OC_CLIPBOARD_SET_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
oc_event* oc_runtime_clipboard_process_event_begin(oc_runtime_clipboard* clipboard, oc_arena* arena, oc_event* origEvent)
|
||||
{
|
||||
oc_event* resultEvent = 0;
|
||||
if(origEvent->type == OC_EVENT_KEYBOARD_KEY)
|
||||
{
|
||||
bool isPressedOrRepeated = origEvent->key.action == OC_KEY_PRESS || origEvent->key.action == OC_KEY_REPEAT;
|
||||
oc_keymod_flags rawMods = origEvent->key.mods & ~OC_KEYMOD_MAIN_MODIFIER;
|
||||
#if OC_PLATFORM_WINDOWS
|
||||
bool cutOrCopied = isPressedOrRepeated
|
||||
&& ((origEvent->key.keyCode == OC_KEY_X && rawMods == OC_KEYMOD_CTRL)
|
||||
|| (origEvent->key.keyCode == OC_KEY_DELETE && rawMods == OC_KEYMOD_SHIFT)
|
||||
|| (origEvent->key.keyCode == OC_KEY_C && rawMods == OC_KEYMOD_CTRL)
|
||||
|| (origEvent->key.keyCode == OC_KEY_INSERT && rawMods == OC_KEYMOD_CTRL));
|
||||
bool pasted = isPressedOrRepeated
|
||||
&& ((origEvent->key.keyCode == OC_KEY_V && rawMods == OC_KEYMOD_CTRL)
|
||||
|| (origEvent->key.keyCode == OC_KEY_INSERT && rawMods == OC_KEYMOD_SHIFT));
|
||||
#elif OC_PLATFORM_MACOS
|
||||
bool cutOrCopied = isPressedOrRepeated
|
||||
&& ((origEvent->key.keyCode == OC_KEY_X && rawMods == OC_KEYMOD_CMD)
|
||||
|| (origEvent->key.keyCode == OC_KEY_C && rawMods == OC_KEYMOD_CMD));
|
||||
bool pasted = isPressedOrRepeated
|
||||
&& origEvent->key.keyCode == OC_KEY_V && rawMods == OC_KEYMOD_CMD;
|
||||
#endif
|
||||
if(cutOrCopied)
|
||||
{
|
||||
clipboard->setAllowedUntil = oc_clock_time(OC_CLOCK_MONOTONIC) + OC_CLIPBOARD_SET_TIMEOUT;
|
||||
}
|
||||
|
||||
if(pasted)
|
||||
{
|
||||
clipboard->isGetAllowed = true;
|
||||
resultEvent = oc_arena_push_type(arena, oc_event);
|
||||
*resultEvent = (oc_event){ .window = origEvent->window,
|
||||
.type = OC_EVENT_CLIPBOARD_PASTE };
|
||||
}
|
||||
}
|
||||
return (resultEvent);
|
||||
}
|
||||
|
||||
void oc_runtime_clipboard_process_event_end(oc_runtime_clipboard* clipboard)
|
||||
{
|
||||
clipboard->isGetAllowed = false;
|
||||
}
|
||||
|
||||
#else
|
||||
#error Default clipboard handling is not supported on this platform"
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* Orca
|
||||
* Copyright 2023 Martin Fouilleul and the Orca project contributors
|
||||
* See LICENSE.txt for licensing information
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef __RUNTIME_CLIPBOARD_H_
|
||||
#define __RUNTIME_CLIPBOARD_H_
|
||||
|
||||
#include "runtime_memory.h"
|
||||
|
||||
typedef struct oc_runtime_clipboard
|
||||
{
|
||||
bool isGetAllowed;
|
||||
f64 setAllowedUntil;
|
||||
} oc_runtime_clipboard;
|
||||
|
||||
#if OC_PLATFORM_WINDOWS || OC_PLATFORM_MACOS
|
||||
|
||||
oc_wasm_str8 oc_runtime_clipboard_get_string(oc_runtime_clipboard* clipboard, oc_wasm_addr wasmArena);
|
||||
void oc_runtime_clipboard_set_string(oc_runtime_clipboard* clipboard, oc_wasm_str8 value);
|
||||
oc_event* oc_runtime_clipboard_process_event_begin(oc_runtime_clipboard* clipboard, oc_arena* arena, oc_event* origEvent);
|
||||
void oc_runtime_clipboard_process_event_end(oc_runtime_clipboard* clipboard);
|
||||
|
||||
#else
|
||||
#error Default clipboard handling is not supported on this platform"
|
||||
#endif
|
||||
|
||||
#endif //__RUNTIME_CLIPBOARD_H_
|
|
@ -134,7 +134,8 @@ oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(oc_wasm_add
|
|||
|
||||
oc_list_for(&nativeResult.selection, elt, oc_file_open_with_dialog_elt, listElt)
|
||||
{
|
||||
oc_wasm_file_open_with_dialog_elt* wasmElt = oc_wasm_arena_push(wasmArena, sizeof(oc_wasm_file_open_with_dialog_elt));
|
||||
oc_wasm_addr wasmEltAddr = oc_wasm_arena_push(wasmArena, sizeof(oc_wasm_file_open_with_dialog_elt));
|
||||
oc_wasm_file_open_with_dialog_elt* wasmElt = oc_wasm_address_to_ptr(wasmEltAddr, sizeof(oc_wasm_file_open_with_dialog_elt));
|
||||
wasmElt->file = elt->file;
|
||||
|
||||
oc_wasm_list_push_back(&result.selection, &wasmElt->listElt);
|
||||
|
|
|
@ -127,7 +127,7 @@ void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt)
|
|||
// Wasm arenas helpers
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size)
|
||||
oc_wasm_addr oc_wasm_arena_push(oc_wasm_addr arena, u64 size)
|
||||
{
|
||||
oc_wasm_env* env = oc_runtime_get_env();
|
||||
|
||||
|
@ -146,6 +146,6 @@ void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size)
|
|||
{
|
||||
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
|
||||
}
|
||||
void* ptr = oc_wasm_address_to_ptr(retValues[0], size);
|
||||
return (ptr);
|
||||
|
||||
return (retValues[0]);
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
#ifndef __RUNTIME_MEMORY_H_
|
||||
#define __RUNTIME_MEMORY_H_
|
||||
|
||||
#include "runtime.h"
|
||||
|
||||
typedef u32 oc_wasm_addr;
|
||||
typedef u32 oc_wasm_size;
|
||||
|
||||
|
@ -96,6 +94,6 @@ typedef struct oc_wasm_str8_list
|
|||
// Wasm arenas helpers
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size);
|
||||
oc_wasm_addr oc_wasm_arena_push(oc_wasm_addr arena, u64 size);
|
||||
|
||||
#endif //__RUNTIME_MEMORY_H_
|
||||
|
|
|
@ -63,6 +63,12 @@ static void oc_update_key_mods(oc_input_state* state, oc_keymod_flags mods)
|
|||
state->keyboard.mods = mods;
|
||||
}
|
||||
|
||||
static void oc_update_clipboard_paste(oc_input_state* state, oc_arena* arena)
|
||||
{
|
||||
state->clipboard.lastUpdate = state->frameCounter;
|
||||
state->clipboard.pastedText = oc_clipboard_get_string(arena);
|
||||
}
|
||||
|
||||
static void oc_update_mouse_move(oc_input_state* state, f32 x, f32 y, f32 deltaX, f32 deltaY)
|
||||
{
|
||||
u64 frameCounter = state->frameCounter;
|
||||
|
@ -134,7 +140,7 @@ void oc_input_next_frame(oc_input_state* state)
|
|||
state->frameCounter++;
|
||||
}
|
||||
|
||||
void oc_input_process_event(oc_input_state* state, oc_event* event)
|
||||
void oc_input_process_event(oc_input_state* state, oc_arena* arena, oc_event* event)
|
||||
{
|
||||
switch(event->type)
|
||||
{
|
||||
|
@ -154,6 +160,10 @@ void oc_input_process_event(oc_input_state* state, oc_event* event)
|
|||
oc_update_key_mods(state, event->key.mods);
|
||||
break;
|
||||
|
||||
case OC_EVENT_CLIPBOARD_PASTE:
|
||||
oc_update_clipboard_paste(state, arena);
|
||||
break;
|
||||
|
||||
case OC_EVENT_MOUSE_MOVE:
|
||||
oc_update_mouse_move(state, event->mouse.x, event->mouse.y, event->mouse.deltaX, event->mouse.deltaY);
|
||||
break;
|
||||
|
@ -413,3 +423,18 @@ oc_str8 oc_input_text_utf8(oc_input_state* input, oc_arena* arena)
|
|||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
bool oc_clipboard_pasted(oc_input_state* input)
|
||||
{
|
||||
return input->clipboard.lastUpdate == input->frameCounter;
|
||||
}
|
||||
|
||||
oc_str8 oc_clipboard_pasted_text(oc_input_state* input)
|
||||
{
|
||||
oc_str8 res = { 0 };
|
||||
if(input->clipboard.lastUpdate == input->frameCounter)
|
||||
{
|
||||
res = input->clipboard.pastedText;
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
|
|
@ -67,15 +67,22 @@ typedef struct oc_text_state
|
|||
oc_str32 codePoints;
|
||||
} oc_text_state;
|
||||
|
||||
typedef struct oc_clipboard_state
|
||||
{
|
||||
u64 lastUpdate;
|
||||
oc_str8 pastedText;
|
||||
} oc_clipboard_state;
|
||||
|
||||
typedef struct oc_input_state
|
||||
{
|
||||
u64 frameCounter;
|
||||
oc_keyboard_state keyboard;
|
||||
oc_mouse_state mouse;
|
||||
oc_text_state text;
|
||||
oc_clipboard_state clipboard;
|
||||
} oc_input_state;
|
||||
|
||||
ORCA_API void oc_input_process_event(oc_input_state* state, oc_event* event);
|
||||
ORCA_API void oc_input_process_event(oc_input_state* state, oc_arena* arena, oc_event* event);
|
||||
ORCA_API void oc_input_next_frame(oc_input_state* state);
|
||||
|
||||
ORCA_API bool oc_key_down(oc_input_state* state, oc_key_code key);
|
||||
|
@ -101,6 +108,9 @@ ORCA_API oc_vec2 oc_mouse_wheel(oc_input_state* state);
|
|||
ORCA_API oc_str32 oc_input_text_utf32(oc_input_state* state, oc_arena* arena);
|
||||
ORCA_API oc_str8 oc_input_text_utf8(oc_input_state* state, oc_arena* arena);
|
||||
|
||||
ORCA_API bool oc_clipboard_pasted(oc_input_state* state);
|
||||
ORCA_API oc_str8 oc_clipboard_pasted_text(oc_input_state* state);
|
||||
|
||||
ORCA_API oc_keymod_flags oc_key_mods(oc_input_state* state);
|
||||
|
||||
#endif //__INPUT_STATE_H_
|
||||
|
|
35
src/ui/ui.c
35
src/ui/ui.c
|
@ -7,6 +7,7 @@
|
|||
**************************************************************************/
|
||||
#include "ui.h"
|
||||
#include "math.h"
|
||||
#include "app/app.h"
|
||||
#include "platform/platform.h"
|
||||
#include "platform/platform_clock.h"
|
||||
#include "platform/platform_debug.h"
|
||||
|
@ -329,7 +330,7 @@ void oc_ui_style_box_after(oc_ui_box* box, oc_ui_pattern pattern, oc_ui_style* s
|
|||
void oc_ui_process_event(oc_event* event)
|
||||
{
|
||||
oc_ui_context* ui = oc_ui_get_context();
|
||||
oc_input_process_event(&ui->input, event);
|
||||
oc_input_process_event(&ui->input, &ui->frameArena, event);
|
||||
}
|
||||
|
||||
oc_vec2 oc_ui_mouse_position(void)
|
||||
|
@ -590,6 +591,8 @@ oc_ui_sig oc_ui_box_sig(oc_ui_box* box)
|
|||
|
||||
sig.dragging = box->dragging;
|
||||
}
|
||||
|
||||
sig.pasted = oc_clipboard_pasted(input);
|
||||
}
|
||||
return (sig);
|
||||
}
|
||||
|
@ -1438,8 +1441,6 @@ void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask
|
|||
{
|
||||
oc_ui_context* ui = oc_ui_get_context();
|
||||
|
||||
oc_arena_clear(&ui->frameArena);
|
||||
|
||||
ui->frameCounter++;
|
||||
f64 time = oc_clock_time(OC_CLOCK_MONOTONIC);
|
||||
ui->lastFrameDuration = time - ui->frameTime;
|
||||
|
@ -1515,6 +1516,7 @@ void oc_ui_end_frame(void)
|
|||
}
|
||||
}
|
||||
|
||||
oc_arena_clear(&ui->frameArena);
|
||||
oc_input_next_frame(&ui->input);
|
||||
}
|
||||
|
||||
|
@ -2699,7 +2701,6 @@ oc_str32 oc_ui_edit_delete_selection(oc_ui_context* ui, oc_str32 codepoints)
|
|||
|
||||
void oc_ui_edit_copy_selection_to_clipboard(oc_ui_context* ui, oc_str32 codepoints)
|
||||
{
|
||||
#if !OC_PLATFORM_ORCA
|
||||
if(ui->editCursor == ui->editMark)
|
||||
{
|
||||
return;
|
||||
|
@ -2709,15 +2710,13 @@ void oc_ui_edit_copy_selection_to_clipboard(oc_ui_context* ui, oc_str32 codepoin
|
|||
oc_str32 selection = oc_str32_slice(codepoints, start, end);
|
||||
oc_str8 string = oc_utf8_push_from_codepoints(&ui->frameArena, selection);
|
||||
|
||||
oc_clipboard_clear();
|
||||
oc_clipboard_set_string(string);
|
||||
#endif
|
||||
}
|
||||
|
||||
oc_str32 oc_ui_edit_replace_selection_with_clipboard(oc_ui_context* ui, oc_str32 codepoints)
|
||||
{
|
||||
#if OC_PLATFORM_ORCA
|
||||
oc_str32 result = { 0 };
|
||||
oc_str32 result = codepoints;
|
||||
#else
|
||||
oc_str8 string = oc_clipboard_get_string(&ui->frameArena);
|
||||
oc_str32 input = oc_utf8_push_to_codepoints(&ui->frameArena, string);
|
||||
|
@ -3095,17 +3094,32 @@ const oc_ui_edit_command OC_UI_EDIT_COMMANDS_WINDOWS[] = {
|
|||
.mods = OC_KEYMOD_CTRL,
|
||||
.operation = OC_UI_EDIT_CUT,
|
||||
.move = OC_UI_EDIT_MOVE_NONE },
|
||||
{
|
||||
.key = OC_KEY_DELETE,
|
||||
.mods = OC_KEYMOD_SHIFT,
|
||||
.operation = OC_UI_EDIT_CUT,
|
||||
.move = OC_UI_EDIT_MOVE_NONE },
|
||||
//NOTE(martin): copy
|
||||
{
|
||||
.key = OC_KEY_C,
|
||||
.mods = OC_KEYMOD_CTRL,
|
||||
.operation = OC_UI_EDIT_COPY,
|
||||
.move = OC_UI_EDIT_MOVE_NONE },
|
||||
{
|
||||
.key = OC_KEY_INSERT,
|
||||
.mods = OC_KEYMOD_CTRL,
|
||||
.operation = OC_UI_EDIT_COPY,
|
||||
.move = OC_UI_EDIT_MOVE_NONE },
|
||||
//NOTE(martin): paste
|
||||
{
|
||||
.key = OC_KEY_V,
|
||||
.mods = OC_KEYMOD_CTRL,
|
||||
.operation = OC_UI_EDIT_PASTE,
|
||||
.move = OC_UI_EDIT_MOVE_NONE },
|
||||
{
|
||||
.key = OC_KEY_INSERT,
|
||||
.mods = OC_KEYMOD_SHIFT,
|
||||
.operation = OC_UI_EDIT_PASTE,
|
||||
.move = OC_UI_EDIT_MOVE_NONE }
|
||||
};
|
||||
|
||||
|
@ -3696,6 +3710,13 @@ oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8
|
|||
}
|
||||
}
|
||||
|
||||
if(sig.pasted)
|
||||
{
|
||||
oc_str8 pastedText = oc_clipboard_pasted_text(&ui->input);
|
||||
oc_str32 input = oc_utf8_push_to_codepoints(&ui->frameArena, pastedText);
|
||||
codepoints = oc_ui_edit_replace_selection_with_codepoints(ui, codepoints, input);
|
||||
}
|
||||
|
||||
//NOTE(martin): check changed/accepted
|
||||
if(oldCodepoints.ptr != codepoints.ptr)
|
||||
{
|
||||
|
|
|
@ -456,6 +456,8 @@ typedef struct oc_ui_sig
|
|||
bool dragging;
|
||||
bool hovering;
|
||||
|
||||
bool pasted;
|
||||
|
||||
} oc_ui_sig;
|
||||
|
||||
typedef void (*oc_ui_box_draw_proc)(oc_ui_box* box, void* data);
|
||||
|
@ -620,6 +622,8 @@ typedef struct oc_ui_context
|
|||
oc_ui_edit_move editSelectionMode;
|
||||
i32 editWordSelectionInitialCursor;
|
||||
i32 editWordSelectionInitialMark;
|
||||
|
||||
bool clipboardRegistered;
|
||||
|
||||
oc_ui_theme* theme;
|
||||
} oc_ui_context;
|
||||
|
|
|
@ -106,5 +106,23 @@
|
|||
{ "name": "scanCode",
|
||||
"type": {"name": "oc_scan_code", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "oc_clipboard_get_string",
|
||||
"cname": "oc_bridge_clipboard_get_string",
|
||||
"ret": { "name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"},
|
||||
"args": [
|
||||
{"name": "arena",
|
||||
"type": {"name": "oc_arena*", "cname": "i32", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "oc_clipboard_set_string",
|
||||
"cname": "oc_bridge_clipboard_set_string",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [
|
||||
{ "name": "value",
|
||||
"type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue