Finished primary rewrite of input system

This commit is contained in:
Allen Webster 2018-11-19 20:18:57 -08:00
parent a34372191b
commit c82d38d4a7
6 changed files with 351 additions and 595 deletions

View File

@ -346,14 +346,16 @@ backspace_utf8(String *str){
static bool32 static bool32
query_user_general(Application_Links *app, Query_Bar *bar, bool32 force_number){ query_user_general(Application_Links *app, Query_Bar *bar, bool32 force_number){
bool32 success = true;
// NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to. // NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to.
// start a query bar, but it will be unusual behavior from the point of view of the // start a query bar, but it will be unusual behavior from the point of view of the
// user, if this command starts intercepting input even though no prompt is shown. // user, if this command starts intercepting input even though no prompt is shown.
// This will only happen if you have a lot of bars open already or if the current view // This will only happen if you have a lot of bars open already or if the current view
// doesn't support query bars. // doesn't support query bars.
if (start_query_bar(app, bar, 0) == 0) return 0; if (start_query_bar(app, bar, 0) == 0){
return(false);
}
bool32 success = true;
for (;;){ for (;;){
// NOTE(allen|a3.4.4): This call will block until the user does one of the input // NOTE(allen|a3.4.4): This call will block until the user does one of the input
@ -398,7 +400,7 @@ query_user_general(Application_Links *app, Query_Bar *bar, bool32 force_number){
backspace_utf8(&bar->string); backspace_utf8(&bar->string);
} }
else if (good_character){ else if (good_character){
append_ss(&bar->string, make_string(character, length)); append(&bar->string, make_string(character, length));
} }
} }
} }

857
4ed.cpp
View File

@ -14,84 +14,6 @@
#define DEFAULT_DISPLAY_WIDTH 672 #define DEFAULT_DISPLAY_WIDTH 672
#define DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH 550 #define DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH 550
internal Available_Input
init_available_input(Key_Input_Data *keys, Mouse_State *mouse){
Available_Input result = {0};
result.keys = keys;
result.mouse = mouse;
return(result);
}
internal Key_Input_Data
direct_get_key_data(Available_Input *available){
Key_Input_Data result = *available->keys;
return(result);
}
internal Mouse_State
direct_get_mouse_state(Available_Input *available){
Mouse_State result = *available->mouse;
return(result);
}
internal Key_Input_Data
get_key_data(Available_Input *available){
Key_Input_Data result = {0};
if (!available->records[Input_AnyKey].consumed){
result = *available->keys;
}
else if (!available->records[Input_Esc].consumed){
i32 count = available->keys->count;
for (i32 i = 0; i < count; ++i){
Key_Event_Data key = available->keys->keys[i];
if (key.keycode == key_esc){
result.count = 1;
result.keys[0] = key;
break;
}
}
}
return(result);
}
internal Mouse_State
get_mouse_state(Available_Input *available){
Mouse_State mouse = *available->mouse;
if (available->records[Input_MouseLeftButton].consumed){
mouse.l = 0;
mouse.press_l = 0;
mouse.release_l = 0;
}
if (available->records[Input_MouseRightButton].consumed){
mouse.r = 0;
mouse.press_r = 0;
mouse.release_r = 0;
}
if (available->records[Input_MouseWheel].consumed){
mouse.wheel = 0;
}
return(mouse);
}
internal void
consume_input(Available_Input *available, i32 input_type, char *consumer){
Consumption_Record *record = &available->records[input_type];
record->consumed = 1;
if (consumer){
String str = make_fixed_width_string(record->consumer);
copy_sc(&str, consumer);
terminate_with_null(&str);
}
else{
record->consumer[0] = 0;
}
}
inline App_Coroutine_State inline App_Coroutine_State
get_state(Application_Links *app){ get_state(Application_Links *app){
App_Coroutine_State state = {0}; App_Coroutine_State state = {0};
@ -960,20 +882,54 @@ app_setup_memory(System_Functions *system, Application_Memory *memory){
return(vars); return(vars);
} }
internal u32
get_event_flags(Key_Code keycode){
u32 event_flags = 0;
if (keycode == key_esc){
event_flags |= EventOnEsc;
event_flags |= EventOnAnyKey;
}
else if (keycode == key_mouse_left){
// TODO(allen):
}
else if (keycode == key_mouse_right){
// TODO(allen):
}
else if (keycode == key_mouse_left_release){
// TODO(allen):
}
else if (keycode == key_mouse_right_release){
// TODO(allen):
}
else if (keycode == key_mouse_wheel){
// TODO(allen):
}
else if (keycode == key_mouse_move){
// TODO(allen):
}
else if (keycode == key_animate){
// TODO(allen):
}
else if (keycode == key_view_activate){
// TODO(allen):
}
else{
event_flags |= EventOnAnyKey;
}
return(event_flags);
}
App_Read_Command_Line_Sig(app_read_command_line){ App_Read_Command_Line_Sig(app_read_command_line){
i32 out_size = 0; i32 out_size = 0;
App_Vars *vars = app_setup_memory(system, memory); App_Vars *vars = app_setup_memory(system, memory);
App_Settings *settings = &vars->models.settings; App_Settings *settings = &vars->models.settings;
memset(settings, 0, sizeof(*settings)); memset(settings, 0, sizeof(*settings));
plat_settings->font_size = 16; plat_settings->font_size = 16;
if (argc > 1){ if (argc > 1){
init_command_line_settings(&vars->models.settings, plat_settings, argc, argv); init_command_line_settings(&vars->models.settings, plat_settings, argc, argv);
} }
*files = vars->models.settings.init_files; *files = vars->models.settings.init_files;
*file_count = &vars->models.settings.init_files_count; *file_count = &vars->models.settings.init_files_count;
return(out_size); return(out_size);
} }
@ -1146,7 +1102,7 @@ App_Step_Sig(app_step){
// NOTE(allen): OS clipboard event handling // NOTE(allen): OS clipboard event handling
String clipboard = input->clipboard; String clipboard = input->clipboard;
if (clipboard.str){ if (clipboard.str != 0){
String *dest = working_set_next_clipboard_string(&models->mem.heap, &models->working_set, clipboard.size); String *dest = working_set_next_clipboard_string(&models->mem.heap, &models->working_set, clipboard.size);
dest->size = eol_convert_in(dest->str, clipboard.str, clipboard.size); dest->size = eol_convert_in(dest->str, clipboard.str, clipboard.size);
} }
@ -1298,502 +1254,347 @@ App_Step_Sig(app_step){
end_temp_memory(temp); end_temp_memory(temp);
} }
#if 0 // NOTE(allen): init event context
models->input = input;
// NOTE(allen): input filter and simulated events
if (models->input_filter != 0){
models->input_filter(&input->mouse);
}
Key_Event_Data mouse_event = {0};
if (input->mouse.press_l){
mouse_event.keycode = key_mouse_left;
input->keys.keys[input->keys.count++] = mouse_event;
}
else if (input->mouse.release_l){
mouse_event.keycode = key_mouse_left_release;
input->keys.keys[input->keys.count++] = mouse_event;
}
if (input->mouse.press_r){
mouse_event.keycode = key_mouse_right;
input->keys.keys[input->keys.count++] = mouse_event;
}
else if (input->mouse.release_r){
mouse_event.keycode = key_mouse_right_release;
input->keys.keys[input->keys.count++] = mouse_event;
}
if (input->mouse.wheel != 0){
mouse_event.keycode = key_mouse_wheel;
input->keys.keys[input->keys.count++] = mouse_event;
}
if (input->mouse.x != models->prev_x || input->mouse.y != models->prev_y){
b32 was_in_window = hit_check(models->prev_x, models->prev_y, i32R(0, 0, prev_width, prev_height));
b32 is_in_window = hit_check(input->mouse.x, input->mouse.y, i32R(0, 0, current_width, current_height));
if (is_in_window || was_in_window){
mouse_event.keycode = key_mouse_move;
input->keys.keys[input->keys.count++] = mouse_event;
}
}
if (models->animated_last_frame){
mouse_event.keycode = key_animate;
input->keys.keys[input->keys.count++] = mouse_event;
}
// NOTE(allen): mouse hover status
Panel *mouse_panel = 0; Panel *mouse_panel = 0;
b32 mouse_in_edit_area = false; b32 mouse_in_edit_area = false;
b32 mouse_in_margin_area = false; b32 mouse_in_margin_area = false;
b32 mouse_on_divider = false; b32 mouse_on_divider = false;
b32 mouse_divider_vertical = false; b32 mouse_divider_vertical = false;
#endif i32 mouse_divider_id = 0;
i32 mouse_divider_side = 0;
#if 1
////
////
//// BEGIN INPUT PROCESSING
////
////
// NOTE(allen): prepare input information
b32 has_keyboard_event = (input->keys.count > 0);
{
if (models->input_filter != 0){
models->input_filter(&input->mouse);
}
Key_Event_Data mouse_event = {0};
if (input->mouse.press_l){
mouse_event.keycode = key_mouse_left;
input->keys.keys[input->keys.count++] = mouse_event;
}
else if (input->mouse.release_l){
mouse_event.keycode = key_mouse_left_release;
input->keys.keys[input->keys.count++] = mouse_event;
}
if (input->mouse.press_r){
mouse_event.keycode = key_mouse_right;
input->keys.keys[input->keys.count++] = mouse_event;
}
else if (input->mouse.release_r){
mouse_event.keycode = key_mouse_right_release;
input->keys.keys[input->keys.count++] = mouse_event;
}
if (input->mouse.wheel != 0){
mouse_event.keycode = key_mouse_wheel;
input->keys.keys[input->keys.count++] = mouse_event;
}
if (input->mouse.x != models->prev_x || input->mouse.y != models->prev_y){
b32 was_in_window = hit_check(models->prev_x, models->prev_y, i32R(0, 0, prev_width, prev_height));
b32 is_in_window = hit_check(input->mouse.x, input->mouse.y, i32R(0, 0, current_width, current_height));
if (is_in_window || (was_in_window != is_in_window)){
mouse_event.keycode = key_mouse_move;
input->keys.keys[input->keys.count++] = mouse_event;
}
}
if (models->animated_last_frame){
mouse_event.keycode = key_animate;
input->keys.keys[input->keys.count++] = mouse_event;
}
}
// NOTE(allen): detect mouse hover status
i32 mx = input->mouse.x; i32 mx = input->mouse.x;
i32 my = input->mouse.y; i32 my = input->mouse.y;
b32 mouse_in_edit_area = false;
b32 mouse_in_margin_area = false;
Panel *mouse_panel = 0;
for (Panel *panel = models->layout.used_sentinel.next; for (Panel *panel = models->layout.used_sentinel.next;
panel != &models->layout.used_sentinel; panel != &models->layout.used_sentinel;
panel = panel->next){ panel = panel->next){
if (hit_check(mx, my, panel->inner)){ if (hit_check(mx, my, panel->inner)){
mouse_panel = panel; mouse_panel = panel;
mouse_in_edit_area = true; mouse_in_edit_area = true;
break;
} }
else if (hit_check(mx, my, panel->full)){ else if (hit_check(mx, my, panel->full)){
mouse_panel = panel; mouse_panel = panel;
mouse_in_margin_area = true; mouse_in_margin_area = true;
if (mx >= panel->inner.x0 && mx < panel->inner.x1){
if (my > panel->inner.y0){
mouse_divider_side = -1;
}
else{
mouse_divider_side = 1;
}
}
else{
mouse_divider_vertical = true;
if (mx > panel->inner.x0){
mouse_divider_side = -1;
}
else{
mouse_divider_side = 1;
}
}
if (models->layout.panel_count > 1){
mouse_divider_id = panel->parent;
i32 which_child = panel->which_child;
for (;;){
Divider_And_ID div = layout_get_divider(&models->layout, mouse_divider_id);
if (which_child == mouse_divider_side && div.divider->v_divider == mouse_divider_vertical){
mouse_on_divider = true;
break;
}
if (mouse_divider_id == models->layout.root){
break;
}
mouse_divider_id = div.divider->parent;
which_child = div.divider->which_child;
}
}
else{
mouse_on_divider = false;
mouse_divider_id = 0;
}
}
if (mouse_panel != 0){
break; break;
} }
} }
b32 mouse_on_divider = false; // NOTE(allen): consume event stream
b32 mouse_divider_vertical = false; Key_Event_Data *key_ptr = input->keys.keys;
i32 mouse_divider_id = 0; Key_Event_Data *key_end = key_ptr + input->keys.count;
i32 mouse_divider_side = 0; for (;key_ptr < key_end; key_ptr += 1){
if (mouse_in_margin_area){
Panel *panel = mouse_panel;
if (mx >= panel->inner.x0 && mx < panel->inner.x1){
mouse_divider_vertical = false;
if (my > panel->inner.y0){
mouse_divider_side = -1;
}
else{
mouse_divider_side = 1;
}
}
else{
mouse_divider_vertical = true;
if (mx > panel->inner.x0){
mouse_divider_side = -1;
}
else{
mouse_divider_side = 1;
}
}
if (models->layout.panel_count > 1){
mouse_divider_id = panel->parent;
i32 which_child = panel->which_child;
for (;;){
Divider_And_ID div =layout_get_divider(&models->layout, mouse_divider_id);
if (which_child == mouse_divider_side &&
div.divider->v_divider == mouse_divider_vertical){
mouse_on_divider = true;
break;
}
if (mouse_divider_id == models->layout.root){
break;
}
else{
mouse_divider_id = div.divider->parent;
which_child = div.divider->which_child;
}
}
}
else{
mouse_on_divider = 0;
mouse_divider_id = 0;
}
}
// NOTE(allen): prepare to start executing commands
vars->available_input = init_available_input(&input->keys, &input->mouse);
// NOTE(allen): Keyboard and Mouse input to command coroutine.
if (models->command_coroutine != 0){
Coroutine_Head *command_coroutine = models->command_coroutine;
u32 get_flags = models->command_coroutine_flags[0];
u32 abort_flags = models->command_coroutine_flags[1];
get_flags |= abort_flags;
Panel *active_panel = &models->layout.panels[models->layout.active_panel]; Panel *active_panel = &models->layout.panels[models->layout.active_panel];
View *view = active_panel->view; View *view = active_panel->view;
Assert(view != 0);
models->key = *key_ptr;
Partition *part = &models->mem.part; // NOTE(allen): execute a command or resize panels
Temp_Memory temp = begin_temp_memory(part); switch (vars->state){
case APP_STATE_EDIT:
{
Key_Code keycode = key_ptr->keycode;
// HACK(allen): This can be simplified a lot more. enum{
Coroutine_Event *events = push_array(part, Coroutine_Event, 32); EventConsume_None,
u32 event_count = 0; EventConsume_BeginResize,
EventConsume_ClickChangeView,
Key_Input_Data key_data = get_key_data(&vars->available_input); EventConsume_Command,
};
if ((get_flags & EventOnAnyKey) || (get_flags & EventOnEsc)){ i32 event_consume_mode = EventConsume_Command;
for (i32 key_i = 0; key_i < key_data.count; ++key_i){ if (keycode == key_mouse_left && input->mouse.press_l && mouse_on_divider){
Key_Code keycode = key_data.keys[key_i].keycode; event_consume_mode = EventConsume_BeginResize;
if (keycode != key_animate && keycode != key_mouse_move){
Coroutine_Event *new_event = &events[event_count++];
new_event->type = Event_Keyboard;
new_event->key_i = key_i;
} }
} else if (keycode == key_mouse_left && input->mouse.press_l && mouse_panel != 0 && mouse_panel != active_panel){
} event_consume_mode = EventConsume_ClickChangeView;
if (models->command_coroutine != 0 && (get_flags & EventOnMouse)){
Coroutine_Event *new_event = &events[event_count++];
new_event->type = Event_Mouse;
}
Coroutine_Event *event = events;
for (u32 event_i = 0; event_i < event_count; ++event_i, ++event){
b32 pass_in = false;
User_Input user_in = {0};
switch (event->type){
case Event_Keyboard:
{
Key_Event_Data key = key_data.keys[event->key_i];
models->key = key;
i32 map = mapid_global;
if (view != 0){
map = view_get_map(view);
}
Command_Binding cmd_bind = map_extract_recursive(&models->mapping, map, key);
user_in.type = UserInputKey;
user_in.key = key;
user_in.command.command = cmd_bind.custom;
if ((abort_flags & EventOnEsc) && key.keycode == key_esc){
user_in.abort = true;
}
else if (abort_flags & EventOnAnyKey){
user_in.abort = true;
}
if (get_flags & EventOnAnyKey){
pass_in = true;
consume_input(&vars->available_input, Input_AnyKey, "command coroutine");
}
if (key.keycode == key_esc){
if (get_flags & EventOnEsc){
pass_in = true;
}
consume_input(&vars->available_input, Input_Esc, "command coroutine");
}
}break;
case Event_Mouse:
{
user_in.type = UserInputMouse;
user_in.mouse = input->mouse;
if (abort_flags & EventOnMouseMove){
user_in.abort = true;
}
if (get_flags & EventOnMouseMove){
pass_in = true;
consume_input(&vars->available_input, Input_MouseMove, "command coroutine");
}
if (input->mouse.press_l || input->mouse.release_l || input->mouse.l){
if (abort_flags & EventOnLeftButton){
user_in.abort = true;
}
if (get_flags & EventOnLeftButton){
pass_in = true;
consume_input(&vars->available_input, Input_MouseLeftButton, "command coroutine");
}
}
if (input->mouse.press_r || input->mouse.release_r || input->mouse.r){
if (abort_flags & EventOnRightButton){
user_in.abort = true;
}
if (get_flags & EventOnRightButton){
pass_in = true;
consume_input(&vars->available_input, Input_MouseRightButton, "command coroutine");
}
}
if (input->mouse.wheel != 0){
if (abort_flags & EventOnWheel){
user_in.abort = true;
}
if (get_flags & EventOnWheel){
pass_in = true;
consume_input(&vars->available_input, Input_MouseWheel, "command coroutine");
}
}
}break;
}
if (pass_in){
models->command_coroutine = app_resume_coroutine(system, &models->app_links, Co_Command, command_coroutine, &user_in, models->command_coroutine_flags);
app_result.animating = true;
if (view != 0 && models->command_coroutine == 0){
init_query_set(&view->transient.query_set);
} }
if (models->command_coroutine == 0){
break;
}
}
}
end_temp_memory(temp); switch (event_consume_mode){
} case EventConsume_BeginResize:
{
vars->state = APP_STATE_RESIZING;
Divider_And_ID div = layout_get_divider(&models->layout, mouse_divider_id);
vars->resizing.divider = div.divider;
// NOTE(allen): command execution f32 min = 0;
{ f32 max = 0;
Key_Input_Data key_data = get_key_data(&vars->available_input); if (mouse_divider_vertical){
b32 hit_something = 0; max = (f32)models->layout.full_width;
b32 hit_esc = 0;
for (i32 key_i = 0; key_i < key_data.count; ++key_i){
if (models->command_coroutine != 0){
break;
}
switch (vars->state){
case APP_STATE_EDIT:
{
Key_Event_Data key = key_data.keys[key_i];
models->key = key;
Panel *active_panel = &models->layout.panels[models->layout.active_panel];
View *view = active_panel->view;
Assert(view != 0);
i32 map = view_get_map(view);
Command_Binding cmd_bind = map_extract_recursive(&models->mapping, map, key);
if (cmd_bind.function != 0){
if (key.keycode == key_esc){
hit_esc = true;
} }
else{ else{
hit_something = true; max = (f32)models->layout.full_height;
}
f32 mid = layout_get_position(&models->layout, mouse_divider_id);
i32 divider_id = div.id;
do{
Divider_And_ID other_div = layout_get_divider(&models->layout, divider_id);
b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical);
f32 pos = layout_get_position(&models->layout, divider_id);
if (divider_match && pos > mid && pos < max){
max = pos;
}
else if (divider_match && pos < mid && pos > min){
min = pos;
}
divider_id = other_div.divider->parent;
}while(divider_id != -1);
Temp_Memory temp = begin_temp_memory(&models->mem.part);
i32 *divider_stack = push_array(&models->mem.part, i32, models->layout.panel_count);
i32 top = 0;
divider_stack[top++] = div.id;
for (;top > 0;){
--top;
Divider_And_ID other_div = layout_get_divider(&models->layout, divider_stack[top]);
b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical);
f32 pos = layout_get_position(&models->layout, divider_stack[top]);
if (divider_match && pos > mid && pos < max){
max = pos;
}
else if (divider_match && pos < mid && pos > min){
min = pos;
}
if (other_div.divider->child1 != -1){
divider_stack[top++] = other_div.divider->child1;
}
if (other_div.divider->child2 != -1){
divider_stack[top++] = other_div.divider->child2;
}
}
end_temp_memory(temp);
}break;
case EventConsume_ClickChangeView:
{
if (models->command_coroutine != 0){
User_Input user_in = {0};
user_in.abort = true;
for (u32 j = 0; j < 10 && models->command_coroutine != 0; ++j){
models->command_coroutine = app_resume_coroutine(system, &models->app_links, Co_Command, models->command_coroutine, &user_in, models->command_coroutine_flags);
}
if (models->command_coroutine != 0){
// TODO(allen): post grave warning
models->command_coroutine = 0;
}
init_query_set(&view->transient.query_set);
} }
Assert(models->command_coroutine == 0); models->layout.active_panel = (i32)(mouse_panel - models->layout.panels);
Coroutine_Head *command_coroutine = system->create_coroutine(command_caller); app_result.animating = true;
models->command_coroutine = command_coroutine;
Command_In cmd_in; {
cmd_in.models = models; Key_Event_Data key = {};
cmd_in.bind = cmd_bind; key.keycode = key_view_activate;
models->key = key;
models->command_coroutine = app_launch_coroutine(system, &models->app_links, Co_Command, models->command_coroutine, &cmd_in, models->command_coroutine_flags); i32 map = view_get_map(view);
Command_Binding cmd_bind = map_extract_recursive(&models->mapping, map, key);
models->prev_command = cmd_bind; if (cmd_bind.function != 0){
Assert(models->command_coroutine == 0);
Coroutine_Head *command_coroutine = system->create_coroutine(command_caller);
models->command_coroutine = command_coroutine;
if (key.keycode != key_animate){ Command_In cmd_in;
app_result.animating = true; cmd_in.models = models;
cmd_in.bind = cmd_bind;
models->command_coroutine = app_launch_coroutine(system, &models->app_links, Co_Command, models->command_coroutine, &cmd_in, models->command_coroutine_flags);
models->prev_command = cmd_bind;
app_result.animating = true;
}
} }
} }break;
}break;
case APP_STATE_RESIZING: case EventConsume_Command:
{ {
if (has_keyboard_event){
vars->state = APP_STATE_EDIT;
}
}break;
}
}
if (hit_something){ if (models->command_coroutine != 0){
consume_input(&vars->available_input, Input_AnyKey, "command dispatcher"); Coroutine_Head *command_coroutine = models->command_coroutine;
} u32 abort_flags = models->command_coroutine_flags[1];
if (hit_esc){ u32 get_flags = models->command_coroutine_flags[0] | abort_flags;
consume_input(&vars->available_input, Input_Esc, "command dispatcher");
}
}
// NOTE(allen): panel resizing Partition *part = &models->mem.part;
switch (vars->state){ Temp_Memory temp = begin_temp_memory(part);
case APP_STATE_EDIT:
{
if (input->mouse.press_l && mouse_on_divider){
vars->state = APP_STATE_RESIZING;
Divider_And_ID div = layout_get_divider(&models->layout, mouse_divider_id);
vars->resizing.divider = div.divider;
f32 min = 0; u32 event_flags = get_event_flags(key_ptr->keycode);
f32 max = 0; if ((get_flags & event_flags) != 0){
{ i32 map = view_get_map(view);
f32 mid = layout_get_position(&models->layout, mouse_divider_id); Command_Binding cmd_bind = map_extract_recursive(&models->mapping, map, *key_ptr);
if (mouse_divider_vertical){
max = (f32)models->layout.full_width; User_Input user_in = {};
user_in.type = UserInputKey;
user_in.key = *key_ptr;
user_in.command.command = cmd_bind.custom;
user_in.abort = ((abort_flags & event_flags) != 0);
models->command_coroutine = app_resume_coroutine(system, &models->app_links, Co_Command, command_coroutine, &user_in, models->command_coroutine_flags);
app_result.animating = true;
if (models->command_coroutine == 0){
init_query_set(&view->transient.query_set);
}
}
}
else{
i32 map = view_get_map(view);
Command_Binding cmd_bind = map_extract_recursive(&models->mapping, map, *key_ptr);
if (cmd_bind.function != 0){
Assert(models->command_coroutine == 0);
Coroutine_Head *command_coroutine = system->create_coroutine(command_caller);
models->command_coroutine = command_coroutine;
Command_In cmd_in;
cmd_in.models = models;
cmd_in.bind = cmd_bind;
models->command_coroutine = app_launch_coroutine(system, &models->app_links, Co_Command, models->command_coroutine, &cmd_in, models->command_coroutine_flags);
models->prev_command = cmd_bind;
if (keycode != key_animate){
app_result.animating = true;
}
}
}
}break;
}
}break;
case APP_STATE_RESIZING:
{
Key_Code keycode = key_ptr->keycode;
u32 event_flags = get_event_flags(keycode);
if (event_flags & EventOnAnyKey || keycode == key_mouse_left_release){
vars->state = APP_STATE_EDIT;
}
else if (keycode == key_mouse_move){
if (input->mouse.l){
Panel_Divider *divider = vars->resizing.divider;
i32 mouse_position = 0;
i32 absolute_positions[MAX_VIEWS];
i32 min = 0;
i32 max = 0;
i32 div_id = (i32)(divider - models->layout.dividers);
layout_compute_absolute_positions(&models->layout, absolute_positions);
mouse_position = (divider->v_divider)?(mx):(my);
layout_get_min_max(&models->layout, divider, absolute_positions, &min, &max);
absolute_positions[div_id] = clamp(min, mouse_position, max);
layout_update_all_positions(&models->layout, absolute_positions);
layout_fix_all_panels(&models->layout);
if (models->layout.panel_state_dirty && models->hooks[hook_view_size_change] != 0){
models->layout.panel_state_dirty = false;
models->hooks[hook_view_size_change](&models->app_links);
}
} }
else{ else{
max = (f32)models->layout.full_height; vars->state = APP_STATE_EDIT;
} }
i32 divider_id = div.id;
do{
Divider_And_ID other_div = layout_get_divider(&models->layout, divider_id);
b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical);
f32 pos = layout_get_position(&models->layout, divider_id);
if (divider_match && pos > mid && pos < max){
max = pos;
}
else if (divider_match && pos < mid && pos > min){
min = pos;
}
divider_id = other_div.divider->parent;
}while(divider_id != -1);
Temp_Memory temp = begin_temp_memory(&models->mem.part);
i32 *divider_stack = push_array(&models->mem.part, i32, models->layout.panel_count);
i32 top = 0;
divider_stack[top++] = div.id;
for (;top > 0;){
--top;
Divider_And_ID other_div = layout_get_divider(&models->layout, divider_stack[top]);
b32 divider_match = (other_div.divider->v_divider == mouse_divider_vertical);
f32 pos = layout_get_position(&models->layout, divider_stack[top]);
if (divider_match && pos > mid && pos < max){
max = pos;
}
else if (divider_match && pos < mid && pos > min){
min = pos;
}
if (other_div.divider->child1 != -1){
divider_stack[top++] = other_div.divider->child1;
}
if (other_div.divider->child2 != -1){
divider_stack[top++] = other_div.divider->child2;
}
}
end_temp_memory(temp);
} }
} }break;
}break;
case APP_STATE_RESIZING:
{
if (input->mouse.l){
Panel_Divider *divider = vars->resizing.divider;
i32 mouse_position = 0;
i32 absolute_positions[MAX_VIEWS];
i32 min = 0;
i32 max = 0;
i32 div_id = (i32)(divider - models->layout.dividers);
layout_compute_absolute_positions(&models->layout, absolute_positions);
mouse_position = (divider->v_divider)?(mx):(my);
layout_get_min_max(&models->layout, divider, absolute_positions, &min, &max);
absolute_positions[div_id] = clamp(min, mouse_position, max);
layout_update_all_positions(&models->layout, absolute_positions);
layout_fix_all_panels(&models->layout);
}
else{
vars->state = APP_STATE_EDIT;
}
}break;
}
if (models->layout.panel_state_dirty && models->hooks[hook_view_size_change] != 0){
models->layout.panel_state_dirty = 0;
models->hooks[hook_view_size_change](&models->app_links);
}
if (mouse_in_edit_area && mouse_panel != 0 && input->mouse.press_l){
i32 new_panel_id = (i32)(mouse_panel - models->layout.panels);
if (models->layout.active_panel != new_panel_id){
if (models->command_coroutine != 0){
User_Input user_in = {0};
user_in.abort = true;
for (u32 j = 0; j < 10 && models->command_coroutine != 0; ++j){
models->command_coroutine = app_resume_coroutine(system, &models->app_links, Co_Command, models->command_coroutine, &user_in, models->command_coroutine_flags);
}
if (models->command_coroutine != 0){
// TODO(allen): post grave warning
models->command_coroutine = 0;
}
Panel *active_panel = &models->layout.panels[models->layout.active_panel];
View *view = active_panel->view;
init_query_set(&view->transient.query_set);
}
models->layout.active_panel = new_panel_id;
app_result.animating = true;
{
Key_Event_Data key = {};
key.keycode = key_view_activate;
models->key = key;
Panel *active_panel = &models->layout.panels[models->layout.active_panel];
View *view = active_panel->view;
i32 map = view_get_map(view);
Command_Binding cmd_bind = map_extract_recursive(&models->mapping, map, key);
if (cmd_bind.function != 0){
Assert(models->command_coroutine == 0);
Coroutine_Head *command_coroutine = system->create_coroutine(command_caller);
models->command_coroutine = command_coroutine;
Command_In cmd_in;
cmd_in.models = models;
cmd_in.bind = cmd_bind;
models->command_coroutine = app_launch_coroutine(system, &models->app_links, Co_Command, models->command_coroutine, &cmd_in, models->command_coroutine_flags);
models->prev_command = cmd_bind;
}
}
} }
} }
////
////
//// END INPUT PROCESSING
////
////
#endif
// NOTE(allen): step panels // NOTE(allen): step panels
{ {
Panel *active_panel = &models->layout.panels[models->layout.active_panel]; Panel *active_panel = &models->layout.panels[models->layout.active_panel];

6
4ed.h
View File

@ -39,12 +39,6 @@ struct Key_Input_Data{
i32 count; i32 count;
}; };
struct Input_Summary{
Mouse_State mouse;
Key_Input_Data keys;
f32 dt;
};
typedef u8 Log_To_Type; typedef u8 Log_To_Type;
enum{ enum{
LogTo_Nothing, LogTo_Nothing,

View File

@ -3026,7 +3026,7 @@ DOC_RETURN(This call returns the current mouse state as of the beginning of the
DOC_SEE(Mouse_State) DOC_SEE(Mouse_State)
*/{ */{
Models *models = (Models*)app->cmd_context; Models *models = (Models*)app->cmd_context;
return(direct_get_mouse_state(&models->vars->available_input)); return(models->input->mouse);
} }
API_EXPORT bool32 API_EXPORT bool32

View File

@ -27,27 +27,6 @@ struct App_Settings{
b32 use_hinting; b32 use_hinting;
}; };
struct Command_Data___{
struct Models *models;
struct App_Vars *vars;
System_Functions *system;
Live_Views *live_set;
i32 screen_width;
i32 screen_height;
Key_Event_Data key;
// Render Context
View *render_view;
Render_Target *target;
i32_Rect render_rect;
Full_Cursor render_cursor;
Range render_range;
Buffer_Render_Item *render_items;
i32 render_item_count;
};
struct Models{ struct Models{
Mem_Options mem; Mem_Options mem;
App_Settings settings; App_Settings settings;
@ -121,6 +100,7 @@ struct Models{
struct App_Vars *vars; struct App_Vars *vars;
// Event Context // Event Context
Application_Step_Input *input;
Key_Event_Data key; Key_Event_Data key;
// Render Context // Render Context
@ -170,21 +150,11 @@ struct Consumption_Record{
char consumer[32]; char consumer[32];
}; };
struct Available_Input{
Key_Input_Data *keys;
Mouse_State *mouse;
Consumption_Record records[Input_Count];
};
struct App_Vars{ struct App_Vars{
Models models; Models models;
CLI_List cli_processes; CLI_List cli_processes;
App_State state; App_State state;
App_State_Resizing resizing; App_State_Resizing resizing;
Available_Input available_input;
}; };
enum Coroutine_Type{ enum Coroutine_Type{
@ -207,15 +177,6 @@ struct File_Init{
b32 read_only; b32 read_only;
}; };
enum{
Event_Keyboard,
Event_Mouse,
};
struct Coroutine_Event{
u32 type;
u32 key_i;
};
enum Command_Line_Action{ enum Command_Line_Action{
CLAct_Nothing, CLAct_Nothing,
CLAct_Ignore, CLAct_Ignore,

View File

@ -1230,7 +1230,7 @@ render_loaded_file_in_view(System_Functions *system, View *view, Models *models,
Buffer_Layout_Stop stop = {0}; Buffer_Layout_Stop stop = {0};
f32 line_shift = 0.f; f32 line_shift = 0.f;
b32 do_wrap = 0; b32 do_wrap = false;
i32 wrap_unit_end = 0; i32 wrap_unit_end = 0;
b32 first_wrap_determination = 1; b32 first_wrap_determination = 1;
@ -1245,18 +1245,18 @@ render_loaded_file_in_view(System_Functions *system, View *view, Models *models,
wrap_array_index = binary_search(file->state.wrap_positions, stop.pos, 0, file->state.wrap_position_count); wrap_array_index = binary_search(file->state.wrap_positions, stop.pos, 0, file->state.wrap_position_count);
++wrap_array_index; ++wrap_array_index;
if (file->state.wrap_positions[wrap_array_index] == stop.pos){ if (file->state.wrap_positions[wrap_array_index] == stop.pos){
do_wrap = 1; do_wrap = true;
wrap_unit_end = file->state.wrap_positions[wrap_array_index]; wrap_unit_end = file->state.wrap_positions[wrap_array_index];
} }
else{ else{
do_wrap = 0; do_wrap = false;
wrap_unit_end = file->state.wrap_positions[wrap_array_index]; wrap_unit_end = file->state.wrap_positions[wrap_array_index];
} }
first_wrap_determination = 0; first_wrap_determination = 0;
} }
else{ else{
Assert(stop.pos == wrap_unit_end); Assert(stop.pos == wrap_unit_end);
do_wrap = 1; do_wrap = true;
++wrap_array_index; ++wrap_array_index;
wrap_unit_end = file->state.wrap_positions[wrap_array_index]; wrap_unit_end = file->state.wrap_positions[wrap_array_index];
} }
@ -1278,7 +1278,7 @@ render_loaded_file_in_view(System_Functions *system, View *view, Models *models,
on_screen_range.first = render_cursor.pos; on_screen_range.first = render_cursor.pos;
on_screen_range.one_past_last = end_pos; on_screen_range.one_past_last = end_pos;
//// ////////////////////////////////
if (models->render_caller != 0){ if (models->render_caller != 0){
models->target = target; models->target = target;
@ -1291,9 +1291,7 @@ render_loaded_file_in_view(System_Functions *system, View *view, Models *models,
models->render_caller(&models->app_links, view->persistent.id + 1, on_screen_range, do_core_render); models->render_caller(&models->app_links, view->persistent.id + 1, on_screen_range, do_core_render);
} }
else{ else{
render_loaded_file_in_view__inner(models, target, view, render_loaded_file_in_view__inner(models, target, view, rect, render_cursor, on_screen_range, items, item_count);
rect, render_cursor, on_screen_range,
items, item_count);
} }
end_temp_memory(temp); end_temp_memory(temp);