Keyboard handling is 100%

master
Allen Webster 2019-10-10 13:15:47 -07:00
parent aa565395e2
commit 27e3efdd01
13 changed files with 156 additions and 42 deletions

50
4ed.cpp
View File

@ -159,6 +159,7 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){
}
Command_Map *map = mapping_get_or_make_map(&new_mapping, mapid);
map_set_parent(&new_mapping, map, mapid_global);
if (unit->map_begin.replace){
map->real_beginning = unit;
}
@ -197,7 +198,12 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){
case unit_inherit:
{
if (map_ptr != 0){
map_set_parent(&new_mapping, map_ptr, unit->map_inherit.mapid);
if (unit->map_inherit.mapid == mapid_nomap){
map_null_parent(map_ptr);
}
else{
map_set_parent(&new_mapping, map_ptr, unit->map_inherit.mapid);
}
}
}break;
@ -581,14 +587,17 @@ force_abort_coroutine(Models *models, View *view){
init_query_set(&view->query_set);
}
internal void
internal b32
launch_command_via_event(Models *models, View *view, Input_Event *event){
block_copy_struct(&models->event, event);
b32 result = false;
Command_Map_ID map = view_get_map(view);
Command_Binding cmd_bind = map_get_binding_recursive(&models->mapping, map, event);
if (cmd_bind.custom != 0){
result = true;
block_copy_struct(&models->event, event);
Assert(models->command_coroutine == 0);
Coroutine *command_coroutine = coroutine_create(&models->coroutines, command_caller);
models->command_coroutine = command_coroutine;
@ -597,13 +606,19 @@ launch_command_via_event(Models *models, View *view, Input_Event *event){
cmd_in.models = models;
cmd_in.bind = cmd_bind;
models->event_unhandled = false;
models->command_coroutine = app_coroutine_run(models, Co_Command, models->command_coroutine, &cmd_in, models->command_coroutine_flags);
if (models->event_unhandled){
result = false;
}
models->prev_command = cmd_bind;
if (match_core_code(event, CoreCode_Animate)){
models->animate_next_frame = true;
}
}
return(result);
}
internal void
@ -964,8 +979,14 @@ App_Step_Sig(app_step){
for (Input_Event_Node *node = input_list.first;
node != 0;
node = node->next){
b32 event_was_handled = false;
Input_Event *event = &node->event;
if (event->kind == InputEventKind_TextInsert &&
event->text.blocked){
continue;
}
Panel *active_panel = layout_get_active_panel(layout);
View *view = active_panel->view;
Assert(view != 0);
@ -995,6 +1016,7 @@ App_Step_Sig(app_step){
{
models->state = APP_STATE_RESIZING;
models->resizing_intermediate_panel = divider_panel;
event_was_handled = true;
}break;
case EventConsume_ClickChangeView:
@ -1019,6 +1041,8 @@ App_Step_Sig(app_step){
// NOTE(allen): run activate command
launch_command_via_core_event(models, view, CoreCode_ClickActivateView);
event_was_handled = true;
}break;
case EventConsume_CustomCommand:
@ -1033,6 +1057,8 @@ App_Step_Sig(app_step){
Event_Property event_flags = get_event_properties(event);
if ((get_flags & event_flags) != 0){
event_was_handled = true;
Command_Map_ID map = view_get_map(view);
Command_Binding cmd_bind = map_get_binding_recursive(&models->mapping, map, event);
@ -1040,7 +1066,12 @@ App_Step_Sig(app_step){
user_in.event = *event;
user_in.command = cmd_bind.custom;
user_in.abort = ((abort_flags & event_flags) != 0);
models->event_unhandled = false;
models->command_coroutine = app_coroutine_run(models, Co_Command, command_coroutine, &user_in, models->command_coroutine_flags);
if (models->event_unhandled){
event_was_handled = false;
}
if (!HasFlag(event_flags, EventProperty_Animate)){
models->animate_next_frame = true;
@ -1052,7 +1083,9 @@ App_Step_Sig(app_step){
}
}
else{
launch_command_via_event(models, view, event);
if (launch_command_via_event(models, view, event)){
event_was_handled = true;
}
}
}break;
}
@ -1079,6 +1112,15 @@ App_Step_Sig(app_step){
}
}break;
}
if (event_was_handled && event->kind == InputEventKind_KeyStroke){
for (Input_Event *dependent_text = event->key.first_dependent_text;
dependent_text != 0;
dependent_text = dependent_text->text.next_text){
Assert(dependent_text->kind == InputEventKind_TextInsert);
dependent_text->text.blocked = true;
}
}
}
// NOTE(allen): send panel size update

View File

@ -2107,6 +2107,12 @@ set_command_input(Application_Links *app, Input_Event *event)
models->event = *event;
}
api(custom) function void
leave_command_input_unhandled(Application_Links *app){
Models *models = (Models*)app->cmd_context;
models->event_unhandled = true;
}
api(custom) function Mouse_State
get_mouse_state(Application_Links *app)
{

View File

@ -124,9 +124,10 @@ struct Models{
// Event Context
Application_Step_Input *input;
Input_Event event;
b8 event_unhandled;
b8 in_render_mode;
Render_Target *target;
b32 in_render_mode;
};
////////////////////////////////

View File

@ -104,7 +104,6 @@ mapping_release(Thread_Context *tctx, Mapping *mapping){
}
}
#if 0
internal Command_Map*
mapping_begin_new_map(Mapping *mapping){
Command_Map *map = mapping__alloc_map(mapping);
@ -115,7 +114,6 @@ mapping_begin_new_map(Mapping *mapping){
table_insert(&mapping->id_to_map, map->id, (u64)PtrAsInt(map));
return(map);
}
#endif
internal Command_Map*
mapping_get_map(Mapping *mapping, Command_Map_ID id){
@ -233,6 +231,11 @@ map_set_parent(Command_Map *map, Command_Map *parent){
}
}
internal void
map_null_parent(Command_Map *map){
map->parent = 0;
}
internal void
map_set_binding_text_input(Command_Map *map, Custom_Command_Function *custom){
if (map != 0){
@ -284,6 +287,12 @@ map_set_parent(Mapping *mapping, Command_Map *map, Command_Map_ID parent_id){
map_set_parent(map, parent);
}
internal void
map_null_parent(Mapping *mapping, Command_Map_ID map_id){
Command_Map *map = mapping_get_map(mapping, map_id);
map_null_parent(map);
}
internal void
map_set_binding_text_input(Mapping *mapping, Command_Map_ID map_id, Custom_Command_Function *custom){
Command_Map *map = mapping_get_map(mapping, map_id);

View File

@ -18,10 +18,6 @@ internal b32
is_modified(Input_Event *event){
b8 *mods = 0;
switch (event->kind){
case InputEventKind_TextInsert:
{
mods = event->text.modifiers.modifiers;
}break;
case InputEventKind_KeyStroke:
{
mods = event->key.modifiers.modifiers;
@ -140,6 +136,14 @@ get_event_properties(Input_Event *event){
return(flags);
}
internal Input_Event*
push_input_event(Arena *arena, Input_List *list){
Input_Event_Node *node = push_array_zero(arena, Input_Event_Node, 1);
sll_queue_push(list->first, list->last, node);
list->count += 1;
return(&node->event);
}
internal Input_Event*
push_input_event(Arena *arena, Input_List *list, Input_Event *event){
Input_Event_Node *node = push_array(arena, Input_Event_Node, 1);

View File

@ -46,11 +46,17 @@ struct Input_Event{
union{
struct{
String_Const_u8 string;
Key_Modifiers modifiers;
// used internally
Input_Event *next_text;
b32 blocked;
} text;
struct{
Key_Code code;
Key_Modifiers modifiers;
// used internally
Input_Event *first_dependent_text;
} key;
struct{
Mouse_Code code;

View File

@ -571,6 +571,9 @@ CUSTOM_DOC("If the buffer in the active view is writable, inserts a character, o
lock_jump_buffer(app, buffer);
}
}
else{
leave_command_input_unhandled(app);
}
}
CUSTOM_COMMAND_SIG(if_read_only_goto_position_same_panel)
@ -585,6 +588,9 @@ CUSTOM_DOC("If the buffer in the active view is writable, inserts a character, o
lock_jump_buffer(app, buffer);
}
}
else{
leave_command_input_unhandled(app);
}
}
//

View File

@ -413,7 +413,7 @@ static Command_Metadata fcoder_metacmd_table[227] = {
{ PROC_LINKS(goto_first_jump, 0), "goto_first_jump", 15, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer.", 95, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 523 },
{ PROC_LINKS(goto_first_jump_same_panel_sticky, 0), "goto_first_jump_same_panel_sticky", 33, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was.", 153, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 540 },
{ PROC_LINKS(if_read_only_goto_position, 0), "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 562 },
{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 576 },
{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 579 },
{ PROC_LINKS(view_jump_list_with_lister, 0), "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 102 },
{ PROC_LINKS(log_graph__escape, 0), "log_graph__escape", 17, "Ends the log grapher", 20, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 906 },
{ PROC_LINKS(log_graph__scroll_wheel, 0), "log_graph__scroll_wheel", 23, "Scrolls the log graph", 21, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 915 },

View File

@ -119,6 +119,7 @@ vtable->managed_object_load_data = managed_object_load_data;
vtable->get_user_input = get_user_input;
vtable->get_command_input = get_command_input;
vtable->set_command_input = set_command_input;
vtable->leave_command_input_unhandled = leave_command_input_unhandled;
vtable->get_mouse_state = get_mouse_state;
vtable->get_active_query_bars = get_active_query_bars;
vtable->start_query_bar = start_query_bar;
@ -293,6 +294,7 @@ managed_object_load_data = vtable->managed_object_load_data;
get_user_input = vtable->get_user_input;
get_command_input = vtable->get_command_input;
set_command_input = vtable->set_command_input;
leave_command_input_unhandled = vtable->leave_command_input_unhandled;
get_mouse_state = vtable->get_mouse_state;
get_active_query_bars = vtable->get_active_query_bars;
start_query_bar = vtable->start_query_bar;

View File

@ -117,6 +117,7 @@
#define custom_get_user_input_sig() User_Input custom_get_user_input(Application_Links* app, Event_Property get_properties, Event_Property abort_properties)
#define custom_get_command_input_sig() User_Input custom_get_command_input(Application_Links* app)
#define custom_set_command_input_sig() void custom_set_command_input(Application_Links* app, Input_Event* event)
#define custom_leave_command_input_unhandled_sig() void custom_leave_command_input_unhandled(Application_Links* app)
#define custom_get_mouse_state_sig() Mouse_State custom_get_mouse_state(Application_Links* app)
#define custom_get_active_query_bars_sig() b32 custom_get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out)
#define custom_start_query_bar_sig() b32 custom_start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags)
@ -287,6 +288,7 @@ typedef b32 custom_managed_object_load_data_type(Application_Links* app, Managed
typedef User_Input custom_get_user_input_type(Application_Links* app, Event_Property get_properties, Event_Property abort_properties);
typedef User_Input custom_get_command_input_type(Application_Links* app);
typedef void custom_set_command_input_type(Application_Links* app, Input_Event* event);
typedef void custom_leave_command_input_unhandled_type(Application_Links* app);
typedef Mouse_State custom_get_mouse_state_type(Application_Links* app);
typedef b32 custom_get_active_query_bars_type(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out);
typedef b32 custom_start_query_bar_type(Application_Links* app, Query_Bar* bar, u32 flags);
@ -458,6 +460,7 @@ custom_managed_object_load_data_type *managed_object_load_data;
custom_get_user_input_type *get_user_input;
custom_get_command_input_type *get_command_input;
custom_set_command_input_type *set_command_input;
custom_leave_command_input_unhandled_type *leave_command_input_unhandled;
custom_get_mouse_state_type *get_mouse_state;
custom_get_active_query_bars_type *get_active_query_bars;
custom_start_query_bar_type *start_query_bar;
@ -630,6 +633,7 @@ internal b32 managed_object_load_data(Application_Links* app, Managed_Object obj
internal User_Input get_user_input(Application_Links* app, Event_Property get_properties, Event_Property abort_properties);
internal User_Input get_command_input(Application_Links* app);
internal void set_command_input(Application_Links* app, Input_Event* event);
internal void leave_command_input_unhandled(Application_Links* app);
internal Mouse_State get_mouse_state(Application_Links* app);
internal b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out);
internal b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags);
@ -802,6 +806,7 @@ global custom_managed_object_load_data_type *managed_object_load_data = 0;
global custom_get_user_input_type *get_user_input = 0;
global custom_get_command_input_type *get_command_input = 0;
global custom_set_command_input_type *set_command_input = 0;
global custom_leave_command_input_unhandled_type *leave_command_input_unhandled = 0;
global custom_get_mouse_state_type *get_mouse_state = 0;
global custom_get_active_query_bars_type *get_active_query_bars = 0;
global custom_start_query_bar_type *start_query_bar = 0;

View File

@ -117,6 +117,7 @@ api(custom) function b32 managed_object_load_data(Application_Links* app, Manage
api(custom) function User_Input get_user_input(Application_Links* app, Event_Property get_properties, Event_Property abort_properties);
api(custom) function User_Input get_command_input(Application_Links* app);
api(custom) function void set_command_input(Application_Links* app, Input_Event* event);
api(custom) function void leave_command_input_unhandled(Application_Links* app);
api(custom) function Mouse_State get_mouse_state(Application_Links* app);
api(custom) function b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out);
api(custom) function b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags);

View File

@ -22,7 +22,6 @@ void fill_keys_default(Bind_Helper *context){
bind(context, KeyCode_X, MDFR_ALT, command_lister);
bind(context, KeyCode_X, MDFR_ALT|MDFR_SHIFT, project_command_lister);
bind(context, KeyCode_I, MDFR_CTRL|MDFR_SHIFT, list_all_functions_all_buffers_lister);
bind(context, KeyCode_F4, MDFR_ALT, exit_4coder);
bind(context, KeyCode_F1, MDFR_NONE, project_fkey_command);
bind(context, KeyCode_F2, MDFR_NONE, project_fkey_command);
bind(context, KeyCode_F3, MDFR_NONE, project_fkey_command);
@ -39,6 +38,7 @@ void fill_keys_default(Bind_Helper *context){
bind(context, KeyCode_F14, MDFR_NONE, project_fkey_command);
bind(context, KeyCode_F15, MDFR_NONE, project_fkey_command);
bind(context, KeyCode_F16, MDFR_NONE, project_fkey_command);
bind(context, KeyCode_F4, MDFR_ALT, exit_4coder);
//bind(context, KeyCodeExt_MouseWheel, MDFR_NONE, mouse_wheel_scroll);
//bind(context, KeyCodeExt_MouseWheel, MDFR_CTRL, mouse_wheel_change_face_size);
end_map(context);
@ -120,7 +120,6 @@ void fill_keys_default(Bind_Helper *context){
bind(context, KeyCode_Return, MDFR_NONE, if_read_only_goto_position);
bind(context, KeyCode_Return, MDFR_SHIFT, if_read_only_goto_position_same_panel);
bind(context, KeyCode_Period, MDFR_CTRL|MDFR_SHIFT, view_jump_list_with_lister);
bind(context, KeyCode_Space, MDFR_SHIFT, write_space);
end_map(context);
begin_map(context, default_code_map);
inherit_map(context, mapid_file);

View File

@ -146,6 +146,8 @@ struct Win32_Vars{
Thread_Context *tctx;
Arena *frame_arena;
Input_Event *active_key_stroke;
Input_Event *active_text_input;
Win32_Input_Chunk input_chunk;
b8 lctrl_lalt_is_altgr;
b8 got_useful_event;
@ -999,42 +1001,69 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
Key_Code key = keycode_lookup_table[(u8)wParam];
if (key != 0){
Key_Modifiers modifiers = system_get_keyboard_modifiers();
Input_Event event = {};
event.kind = InputEventKind_KeyStroke;
event.key.code = key;
block_copy_struct(&event.key.modifiers, &modifiers);
push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list, &event);
Input_Event *event = push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list);
event->kind = InputEventKind_KeyStroke;
event->key.code = key;
block_copy_struct(&event->key.modifiers, &modifiers);
win32vars.active_key_stroke = event;
win32vars.got_useful_event = true;
}
}
else{
win32vars.active_key_stroke = 0;
win32vars.active_text_input = 0;
win32vars.got_useful_event = true;
}
}break;
case WM_CHAR: case WM_SYSCHAR: case WM_UNICHAR:
case WM_CHAR:
{
u16 character = (u16)wParam;
if (character == '\r'){
character = '\n';
u16 c = wParam & bitmask_16;
if (c == '\r'){
c = '\n';
}
else if (character == '\t'){
// Do nothing
if (c > 127 || (' ' <= c && c <= '~') || c == '\t' || c == '\n'){
String_Const_u16 str_16 = SCu16(&c, 1);
String_Const_u8 str_8 = string_u8_from_string_u16(win32vars.frame_arena, str_16).string;
Input_Event *event = push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list);
event->kind = InputEventKind_TextInsert;
event->text.string = str_8;
event->text.next_text = 0;
event->text.blocked = false;
if (win32vars.active_text_input != 0){
win32vars.active_text_input->text.next_text = event;
}
else if (win32vars.active_key_stroke != 0){
win32vars.active_key_stroke->key.first_dependent_text = event;
}
win32vars.active_text_input = event;
win32vars.got_useful_event = true;
}
else if (character < 32 || character == 127){
break;
}break;
case WM_UNICHAR:
{
if (wParam == UNICODE_NOCHAR){
result = true;
}
else{
u32 c = (u32)wParam;
if (c == '\r'){
c= '\n';
}
if (c > 127 || (' ' <= c && c <= '~') || c == '\t' || c == '\n'){
String_Const_u32 str_32 = SCu32(&c, 1);
String_Const_u8 str_8 = string_u8_from_string_u32(win32vars.frame_arena, str_32).string;
Input_Event event = {};
event.kind = InputEventKind_TextInsert;
event.text.string = str_8;
push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list, &event);
win32vars.got_useful_event = true;
}
}
String_Const_u16 str_16 = SCu16(&character, 1);
String_Const_u8 str_8 = string_u8_from_string_u16(win32vars.frame_arena, str_16).string;
Key_Modifiers modifiers = system_get_keyboard_modifiers();
Input_Event event = {};
event.kind = InputEventKind_TextInsert;
event.text.string = str_8;
block_copy_struct(&event.text.modifiers, &modifiers);
push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list, &event);
win32vars.got_useful_event = true;
}break;
case WM_MOUSEMOVE:
@ -1096,6 +1125,8 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
win32vars.input_chunk.pers.control_keys[i] = false;
}
block_zero_struct(&win32vars.input_chunk.pers.controls);
win32vars.active_key_stroke = 0;
win32vars.active_text_input = 0;
}break;
case WM_SIZE:
@ -1659,6 +1690,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
for (;keep_running;){
linalloc_clear(win32vars.frame_arena);
block_zero_struct(&win32vars.input_chunk.trans);
win32vars.active_key_stroke = 0;
win32vars.active_text_input = 0;
// TODO(allen): Find a good way to wait on a pipe
// without interfering with the reading process.
@ -1694,8 +1727,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
}
if (treat_normally){
TranslateMessage(&msg);
DispatchMessage(&msg);
TranslateMessage(&msg);
}
else{
Control_Keys *controls = &win32vars.input_chunk.pers.controls;