Extracted commonalities from platform specific app backends
This commit is contained in:
parent
30bd704af2
commit
72338b1a25
|
@ -2,5 +2,5 @@
|
|||
if not exist bin mkdir bin
|
||||
|
||||
set INCLUDES=/I src /I src/util /I src/platform /I ext
|
||||
cl /Zi /Zc:preprocessor /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
|
||||
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
|
||||
lib bin/milepost.obj /OUT:bin/milepost.lib
|
||||
|
|
|
@ -107,7 +107,8 @@ int main()
|
|||
|
||||
glUseProgram(program);
|
||||
|
||||
mp_window_bring_to_front_and_focus(window);
|
||||
mp_window_bring_to_front(window);
|
||||
// mp_window_focus(window);
|
||||
|
||||
while(!mp_should_quit())
|
||||
{
|
||||
|
@ -117,18 +118,72 @@ int main()
|
|||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case MP_EVENT_KEYBOARD_CHAR:
|
||||
{
|
||||
printf("entered char %s\n", event.character.sequence);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_WINDOW_CLOSE:
|
||||
{
|
||||
mp_do_quit();
|
||||
mp_request_quit();
|
||||
} break;
|
||||
|
||||
case MP_EVENT_WINDOW_RESIZE:
|
||||
{
|
||||
printf("resized, rect = {%f, %f, %f, %f}\n",
|
||||
event.frame.rect.x,
|
||||
event.frame.rect.y,
|
||||
event.frame.rect.w,
|
||||
event.frame.rect.h);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_WINDOW_MOVE:
|
||||
{
|
||||
printf("moved, rect = {%f, %f, %f, %f}\n",
|
||||
event.frame.rect.x,
|
||||
event.frame.rect.y,
|
||||
event.frame.rect.w,
|
||||
event.frame.rect.h);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_MOUSE_MOVE:
|
||||
{
|
||||
printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n",
|
||||
event.move.x,
|
||||
event.move.y,
|
||||
event.move.deltaX,
|
||||
event.move.deltaY);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_MOUSE_WHEEL:
|
||||
{
|
||||
printf("mouse wheel, delta = {%f, %f}\n",
|
||||
event.move.deltaX,
|
||||
event.move.deltaY);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_MOUSE_ENTER:
|
||||
{
|
||||
printf("mouse enter\n");
|
||||
} break;
|
||||
|
||||
case MP_EVENT_MOUSE_LEAVE:
|
||||
{
|
||||
printf("mouse leave\n");
|
||||
} break;
|
||||
|
||||
case MP_EVENT_MOUSE_BUTTON:
|
||||
{
|
||||
printf("mouse button %i: %i\n",
|
||||
event.key.code,
|
||||
event.key.action == MP_KEY_PRESS ? 1 : 0);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_KEYBOARD_KEY:
|
||||
{
|
||||
printf("key %i: %s\n",
|
||||
event.key.code,
|
||||
event.key.action == MP_KEY_PRESS ? "press" : (event.key.action == MP_KEY_RELEASE ? "release" : "repeat"));
|
||||
} break;
|
||||
|
||||
case MP_EVENT_KEYBOARD_CHAR:
|
||||
{
|
||||
printf("entered char %s\n", event.character.sequence);
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: mp_app_internal.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 23/12/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include"mp_app_internal.h"
|
||||
|
||||
#define LOG_SUBSYSTEM "Application"
|
||||
|
||||
mp_app __mpApp = {0};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Window handles
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void mp_init_window_handles()
|
||||
{
|
||||
ListInit(&__mpApp.windowFreeList);
|
||||
for(int i=0; i<MP_APP_MAX_WINDOWS; i++)
|
||||
{
|
||||
__mpApp.windowPool[i].generation = 1;
|
||||
ListAppend(&__mpApp.windowFreeList, &__mpApp.windowPool[i].freeListElt);
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_window_handle_is_null(mp_window window)
|
||||
{
|
||||
return(window.h == 0);
|
||||
}
|
||||
|
||||
mp_window mp_window_null_handle()
|
||||
{
|
||||
return((mp_window){.h = 0});
|
||||
}
|
||||
|
||||
mp_window_data* mp_window_alloc()
|
||||
{
|
||||
return(ListPopEntry(&__mpApp.windowFreeList, mp_window_data, freeListElt));
|
||||
}
|
||||
|
||||
mp_window_data* mp_window_ptr_from_handle(mp_window handle)
|
||||
{
|
||||
u32 index = handle.h>>32;
|
||||
u32 generation = handle.h & 0xffffffff;
|
||||
if(index >= MP_APP_MAX_WINDOWS)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
mp_window_data* window = &__mpApp.windowPool[index];
|
||||
if(window->generation != generation)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(window);
|
||||
}
|
||||
}
|
||||
|
||||
mp_window mp_window_handle_from_ptr(mp_window_data* window)
|
||||
{
|
||||
DEBUG_ASSERT( (window - __mpApp.windowPool) >= 0
|
||||
&& (window - __mpApp.windowPool) < MP_APP_MAX_WINDOWS);
|
||||
|
||||
u64 h = ((u64)(window - __mpApp.windowPool))<<32
|
||||
| ((u64)window->generation);
|
||||
|
||||
return((mp_window){h});
|
||||
}
|
||||
|
||||
void mp_window_recycle_ptr(mp_window_data* window)
|
||||
{
|
||||
window->generation++;
|
||||
ListPush(&__mpApp.windowFreeList, &window->freeListElt);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Init
|
||||
//---------------------------------------------------------------
|
||||
|
||||
static void mp_init_common()
|
||||
{
|
||||
mp_init_window_handles();
|
||||
ringbuffer_init(&__mpApp.eventQueue, 16);
|
||||
}
|
||||
|
||||
static void mp_terminate_common()
|
||||
{
|
||||
ringbuffer_cleanup(&__mpApp.eventQueue);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Event handling
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void mp_queue_event(mp_event* event)
|
||||
{
|
||||
if(ringbuffer_write_available(&__mpApp.eventQueue) < sizeof(mp_event))
|
||||
{
|
||||
LOG_ERROR("event queue full\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 written = ringbuffer_write(&__mpApp.eventQueue, sizeof(mp_event), (u8*)event);
|
||||
DEBUG_ASSERT(written == sizeof(mp_event));
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_next_event(mp_event* event)
|
||||
{
|
||||
//NOTE pop and return event from queue
|
||||
if(ringbuffer_read_available(&__mpApp.eventQueue) >= sizeof(mp_event))
|
||||
{
|
||||
u64 read = ringbuffer_read(&__mpApp.eventQueue, sizeof(mp_event), (u8*)event);
|
||||
DEBUG_ASSERT(read == sizeof(mp_event));
|
||||
return(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Input state updating
|
||||
//---------------------------------------------------------------
|
||||
|
||||
static void mp_update_key_state(mp_key_state* key, bool down)
|
||||
{
|
||||
u64 frameCounter = __mpApp.inputState.frameCounter;
|
||||
if(key->lastUpdate != frameCounter)
|
||||
{
|
||||
key->transitionCounter = 0;
|
||||
key->clicked = false;
|
||||
key->doubleClicked = false;
|
||||
key->lastUpdate = frameCounter;
|
||||
}
|
||||
if(key->down == down)
|
||||
{
|
||||
key->transitionCounter++;
|
||||
}
|
||||
key->down = down;
|
||||
}
|
||||
|
||||
static void mp_update_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY)
|
||||
{
|
||||
u64 frameCounter = __mpApp.inputState.frameCounter;
|
||||
mp_mouse_state* mouse = &__mpApp.inputState.mouse;
|
||||
if(mouse->lastUpdate != frameCounter)
|
||||
{
|
||||
mouse->delta = (vec2){0, 0};
|
||||
mouse->wheel = (vec2){0, 0};
|
||||
mouse->lastUpdate = frameCounter;
|
||||
}
|
||||
mouse->pos = (vec2){x, y};
|
||||
mouse->delta.x += deltaX;
|
||||
mouse->delta.y += deltaY;
|
||||
}
|
||||
|
||||
static void mp_update_mouse_wheel(f32 deltaX, f32 deltaY)
|
||||
{
|
||||
u64 frameCounter = __mpApp.inputState.frameCounter;
|
||||
mp_mouse_state* mouse = &__mpApp.inputState.mouse;
|
||||
if(mouse->lastUpdate != frameCounter)
|
||||
{
|
||||
mouse->delta = (vec2){0, 0};
|
||||
mouse->wheel = (vec2){0, 0};
|
||||
mouse->lastUpdate = frameCounter;
|
||||
}
|
||||
mouse->wheel.x += deltaX;
|
||||
mouse->wheel.y += deltaY;
|
||||
}
|
||||
|
||||
static void mp_update_text(utf32 codepoint)
|
||||
{
|
||||
u64 frameCounter = __mpApp.inputState.frameCounter;
|
||||
mp_text_state* text = &__mpApp.inputState.text;
|
||||
|
||||
if(text->lastUpdate != frameCounter)
|
||||
{
|
||||
text->codePoints.len = 0;
|
||||
text->lastUpdate = frameCounter;
|
||||
}
|
||||
|
||||
text->codePoints.ptr = text->backing;
|
||||
if(text->codePoints.len < MP_INPUT_TEXT_BACKING_SIZE)
|
||||
{
|
||||
text->codePoints.ptr[text->codePoints.len] = codepoint;
|
||||
text->codePoints.len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("too many input codepoints per frame, dropping input");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Input state polling
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
mp_key_state mp_input_get_key_state(mp_key_code key)
|
||||
{
|
||||
if(key <= MP_KEY_COUNT)
|
||||
{
|
||||
return(__mpApp.inputState.keyboard.keys[key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((mp_key_state){0});
|
||||
}
|
||||
}
|
||||
mp_key_state mp_input_get_mouse_button_state(mp_mouse_button button)
|
||||
{
|
||||
if(button <= MP_MOUSE_BUTTON_COUNT)
|
||||
{
|
||||
return(__mpApp.inputState.mouse.buttons[button]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((mp_key_state){0});
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_input_check_key_transition(mp_key_state* key, bool pressed)
|
||||
{
|
||||
bool res = ( (key->lastUpdate == __mpApp.inputState.frameCounter)
|
||||
&& key->transitionCounter
|
||||
&&(key->down == pressed || key->transitionCounter > 1));
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_key_down(mp_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_input_get_key_state(key);
|
||||
return(state.down);
|
||||
}
|
||||
bool mp_input_key_pressed(mp_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_input_get_key_state(key);
|
||||
bool res = mp_input_check_key_transition(&state, true);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_key_released(mp_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_input_get_key_state(key);
|
||||
bool res = mp_input_check_key_transition(&state, false);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_down(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
return(state.down);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_pressed(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
bool res = mp_input_check_key_transition(&state, true);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_released(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
bool res = mp_input_check_key_transition(&state, false);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_clicked(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
return(state.clicked);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_double_clicked(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
if(state.lastUpdate == __mpApp.inputState.frameCounter)
|
||||
{
|
||||
return(state.doubleClicked);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
mp_key_mods mp_input_key_mods()
|
||||
{
|
||||
return(__mpApp.inputState.keyboard.mods);
|
||||
}
|
||||
|
||||
vec2 mp_input_mouse_position()
|
||||
{
|
||||
return(__mpApp.inputState.mouse.pos);
|
||||
}
|
||||
|
||||
vec2 mp_input_mouse_delta()
|
||||
{
|
||||
if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter)
|
||||
{
|
||||
return(__mpApp.inputState.mouse.delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((vec2){0, 0});
|
||||
}
|
||||
}
|
||||
|
||||
vec2 mp_input_mouse_wheel()
|
||||
{
|
||||
if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter)
|
||||
{
|
||||
return(__mpApp.inputState.mouse.wheel);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((vec2){0, 0});
|
||||
}
|
||||
}
|
||||
|
||||
str32 mp_input_text_utf32(mem_arena* arena)
|
||||
{
|
||||
str32 res = {0};
|
||||
if(__mpApp.inputState.text.lastUpdate == __mpApp.inputState.frameCounter)
|
||||
{
|
||||
res = str32_push_copy(arena, __mpApp.inputState.text.codePoints);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
str8 mp_input_text_utf8(mem_arena* arena)
|
||||
{
|
||||
str8 res = {0};
|
||||
if(__mpApp.inputState.text.lastUpdate == __mpApp.inputState.frameCounter)
|
||||
{
|
||||
res = utf8_push_from_codepoints(arena, __mpApp.inputState.text.codePoints);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
|
||||
#undef LOG_SUBSYSTEM
|
120
src/mp_app.h
120
src/mp_app.h
|
@ -42,7 +42,7 @@ static const mp_window_style MP_WINDOW_STYLE_NO_TITLE = 0x01<<0,
|
|||
MP_WINDOW_STYLE_NO_BUTTONS = 0x01<<7;
|
||||
|
||||
typedef enum { MP_EVENT_NONE,
|
||||
MP_EVENT_KEYBOARD_MODS,
|
||||
MP_EVENT_KEYBOARD_MODS, //TODO: remove, keep only key?
|
||||
MP_EVENT_KEYBOARD_KEY,
|
||||
MP_EVENT_KEYBOARD_CHAR,
|
||||
MP_EVENT_MOUSE_BUTTON,
|
||||
|
@ -54,10 +54,9 @@ typedef enum { MP_EVENT_NONE,
|
|||
MP_EVENT_WINDOW_MOVE,
|
||||
MP_EVENT_WINDOW_FOCUS,
|
||||
MP_EVENT_WINDOW_UNFOCUS,
|
||||
MP_EVENT_WINDOW_HIDE,
|
||||
MP_EVENT_WINDOW_SHOW,
|
||||
MP_EVENT_WINDOW_HIDE, // rename to minimize?
|
||||
MP_EVENT_WINDOW_SHOW, // rename to restore?
|
||||
MP_EVENT_WINDOW_CLOSE,
|
||||
MP_EVENT_CLIPBOARD,
|
||||
MP_EVENT_PATHDROP,
|
||||
MP_EVENT_FRAME,
|
||||
MP_EVENT_QUIT } mp_event_type;
|
||||
|
@ -67,7 +66,10 @@ typedef enum { MP_KEY_NO_ACTION,
|
|||
MP_KEY_RELEASE,
|
||||
MP_KEY_REPEAT } mp_key_action;
|
||||
|
||||
typedef enum { MP_KEY_UNKNOWN = -1,
|
||||
typedef enum { MP_KEY_UNKNOWN = 0,
|
||||
MP_KEY_SPACE = 32,
|
||||
MP_KEY_APOSTROPHE = 39, /* ' */
|
||||
MP_KEY_COMMA = 44, /* , */
|
||||
MP_KEY_MINUS = 45, // -
|
||||
MP_KEY_PERIOD = 46, // .
|
||||
MP_KEY_SLASH = 47, // /
|
||||
|
@ -185,24 +187,22 @@ typedef enum { MP_KEY_UNKNOWN = -1,
|
|||
MP_KEY_RIGHT_ALT = 346,
|
||||
MP_KEY_RIGHT_SUPER = 347,
|
||||
MP_KEY_MENU = 348,
|
||||
MP_KEY_MAX } mp_key_code;
|
||||
MP_KEY_COUNT } mp_key_code;
|
||||
|
||||
typedef u8 mp_key_mods;
|
||||
static const mp_key_mods MP_KEYMOD_NONE = 0x00,
|
||||
MP_KEYMOD_ALT = 0x01,
|
||||
MP_KEYMOD_SHIFT = 0x02,
|
||||
MP_KEYMOD_CTRL = 0x04,
|
||||
MP_KEYMOD_CMD = 0x08;
|
||||
typedef enum {
|
||||
MP_KEYMOD_NONE = 0x00,
|
||||
MP_KEYMOD_ALT = 0x01,
|
||||
MP_KEYMOD_SHIFT = 0x02,
|
||||
MP_KEYMOD_CTRL = 0x04,
|
||||
MP_KEYMOD_CMD = 0x08 } mp_key_mods;
|
||||
|
||||
typedef i32 mp_mouse_button;
|
||||
static const mp_mouse_button MP_MOUSE_LEFT = 0x00,
|
||||
MP_MOUSE_RIGHT = 0x01,
|
||||
MP_MOUSE_MIDDLE = 0x02,
|
||||
MP_MOUSE_EXT1 = 0x03,
|
||||
MP_MOUSE_EXT2 = 0x04;
|
||||
|
||||
static const u32 MP_KEY_COUNT = MP_KEY_MAX+1,
|
||||
MP_MOUSE_BUTTON_COUNT = 5;
|
||||
typedef enum {
|
||||
MP_MOUSE_LEFT = 0x00,
|
||||
MP_MOUSE_RIGHT = 0x01,
|
||||
MP_MOUSE_MIDDLE = 0x02,
|
||||
MP_MOUSE_EXT1 = 0x03,
|
||||
MP_MOUSE_EXT2 = 0x04,
|
||||
MP_MOUSE_BUTTON_COUNT } mp_mouse_button;
|
||||
|
||||
typedef struct mp_key_event // keyboard and mouse buttons input
|
||||
{
|
||||
|
@ -263,54 +263,63 @@ void mp_init();
|
|||
void mp_terminate();
|
||||
|
||||
bool mp_should_quit();
|
||||
void mp_do_quit();
|
||||
void mp_request_quit();
|
||||
void mp_cancel_quit();
|
||||
void mp_request_quit();
|
||||
|
||||
void mp_set_cursor(mp_mouse_cursor cursor);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// window management
|
||||
// Main loop and events handling
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
//#include"graphics.h"
|
||||
void mp_pump_events(f64 timeout);
|
||||
bool mp_next_event(mp_event* event);
|
||||
|
||||
typedef void(*mp_live_resize_callback)(mp_event event, void* data);
|
||||
void mp_set_live_resize_callback(mp_live_resize_callback callback, void* data);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// window management
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
bool mp_window_handle_is_null(mp_window window);
|
||||
mp_window mp_window_null_handle();
|
||||
|
||||
mp_window mp_window_create(mp_rect contentRect, const char* title, mp_window_style style);
|
||||
void mp_window_destroy(mp_window window);
|
||||
void* mp_window_native_pointer(mp_window window);
|
||||
|
||||
bool mp_window_should_close(mp_window window);
|
||||
void mp_window_request_close(mp_window window);
|
||||
void mp_window_cancel_close(mp_window window);
|
||||
|
||||
void* mp_window_native_pointer(mp_window window);
|
||||
|
||||
void mp_window_center(mp_window window);
|
||||
|
||||
bool mp_window_is_hidden(mp_window window);
|
||||
bool mp_window_is_focused(mp_window window);
|
||||
|
||||
void mp_window_hide(mp_window window);
|
||||
void mp_window_show(mp_window window);
|
||||
|
||||
bool mp_window_is_minimized(mp_window window);
|
||||
bool mp_window_is_maximized(mp_window window);
|
||||
void mp_window_minimize(mp_window window);
|
||||
void mp_window_maximize(mp_window window);
|
||||
void mp_window_restore(mp_window window);
|
||||
|
||||
bool mp_window_has_focus(mp_window window);
|
||||
void mp_window_focus(mp_window window);
|
||||
void mp_window_unfocus(mp_window window);
|
||||
|
||||
void mp_window_send_to_back(mp_window window);
|
||||
void mp_window_bring_to_front(mp_window window);
|
||||
|
||||
void mp_window_bring_to_front_and_focus(mp_window window);
|
||||
mp_rect mp_window_get_content_rect(mp_window window);
|
||||
mp_rect mp_window_get_frame_rect(mp_window window);
|
||||
void mp_window_set_content_rect(mp_window window, mp_rect contentRect);
|
||||
void mp_window_set_frame_rect(mp_window window, mp_rect frameRect);
|
||||
|
||||
void mp_window_center(mp_window window);
|
||||
|
||||
mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style);
|
||||
mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style);
|
||||
|
||||
mp_rect mp_window_get_content_rect(mp_window window);
|
||||
mp_rect mp_window_get_absolute_content_rect(mp_window window);
|
||||
mp_rect mp_window_get_frame_rect(mp_window window);
|
||||
|
||||
void mp_window_set_content_rect(mp_window window, mp_rect contentRect);
|
||||
void mp_window_set_frame_rect(mp_window window, mp_rect frameRect);
|
||||
void mp_window_set_frame_size(mp_window window, int width, int height);
|
||||
void mp_window_set_content_size(mp_window window, int width, int height);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// View management
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -321,26 +330,6 @@ mp_view mp_view_create(mp_window window, mp_rect frame);
|
|||
void mp_view_destroy(mp_view view);
|
||||
void mp_view_set_frame(mp_view view, mp_rect frame);
|
||||
|
||||
/*TODO
|
||||
mp_view mp_view_bring_to_front(mp_view view);
|
||||
mp_view mp_view_send_to_back(mp_view view);
|
||||
*/
|
||||
//--------------------------------------------------------------------
|
||||
// Main loop and events handling
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
typedef void(*mp_event_callback)(mp_event event, void* data);
|
||||
void mp_set_event_callback(mp_event_callback callback, void* data);
|
||||
void mp_set_target_fps(u32 fps);
|
||||
void mp_run_loop();
|
||||
void mp_end_input_frame();
|
||||
|
||||
void mp_pump_events(f64 timeout);
|
||||
bool mp_next_event(mp_event* event);
|
||||
|
||||
typedef void(*mp_live_resize_callback)(mp_event event, void* data);
|
||||
void mp_set_live_resize_callback(mp_live_resize_callback callback, void* data);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Input state polling
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -364,11 +353,6 @@ vec2 mp_input_mouse_wheel();
|
|||
|
||||
str32 mp_input_text_utf32(mem_arena* arena);
|
||||
str8 mp_input_text_utf8(mem_arena* arena);
|
||||
//--------------------------------------------------------------------
|
||||
// app resources
|
||||
//--------------------------------------------------------------------
|
||||
str8 mp_app_get_resource_path(mem_arena* arena, const char* name);
|
||||
str8 mp_app_get_executable_path(mem_arena* arena);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Clipboard
|
||||
|
@ -414,6 +398,10 @@ int mp_file_remove(str8 path);
|
|||
|
||||
int mp_directory_create(str8 path);
|
||||
|
||||
str8 mp_app_get_resource_path(mem_arena* arena, const char* name);
|
||||
str8 mp_app_get_executable_path(mem_arena* arena);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: mp_app_internal.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 23/12/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __MP_APP_INTERNAL_H_
|
||||
#define __MP_APP_INTERNAL_H_
|
||||
|
||||
#include"platform.h"
|
||||
#include"ringbuffer.h"
|
||||
|
||||
#if defined(OS_WIN64) || defined(OS_WIN32)
|
||||
#include"win32_app.h"
|
||||
#elif defined(OS_MACOS)
|
||||
#include"osx_app.h"
|
||||
#else
|
||||
#error "platform not supported yet"
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Input State
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef struct mp_key_utf8
|
||||
{
|
||||
u8 labelLen;
|
||||
char label[8];
|
||||
} mp_key_utf8;
|
||||
|
||||
typedef struct mp_key_state
|
||||
{
|
||||
u64 lastUpdate;
|
||||
u32 transitionCounter;
|
||||
bool down;
|
||||
bool clicked;
|
||||
bool doubleClicked;
|
||||
|
||||
} mp_key_state;
|
||||
|
||||
typedef struct mp_keyboard_state
|
||||
{
|
||||
mp_key_state keys[MP_KEY_COUNT];
|
||||
mp_key_mods mods;
|
||||
} mp_keyboard_state;
|
||||
|
||||
typedef struct mp_mouse_state
|
||||
{
|
||||
u64 lastUpdate;
|
||||
bool posValid;
|
||||
vec2 pos;
|
||||
vec2 delta;
|
||||
vec2 wheel;
|
||||
|
||||
union
|
||||
{
|
||||
mp_key_state buttons[MP_MOUSE_BUTTON_COUNT];
|
||||
struct
|
||||
{
|
||||
mp_key_state left;
|
||||
mp_key_state right;
|
||||
mp_key_state middle;
|
||||
mp_key_state ext1;
|
||||
mp_key_state ext2;
|
||||
};
|
||||
};
|
||||
} mp_mouse_state;
|
||||
|
||||
enum { MP_INPUT_TEXT_BACKING_SIZE = 64 };
|
||||
|
||||
typedef struct mp_text_state
|
||||
{
|
||||
u64 lastUpdate;
|
||||
utf32 backing[MP_INPUT_TEXT_BACKING_SIZE];
|
||||
str32 codePoints;
|
||||
} mp_text_state;
|
||||
|
||||
typedef struct mp_input_state
|
||||
{
|
||||
u64 frameCounter;
|
||||
mp_keyboard_state keyboard;
|
||||
mp_mouse_state mouse;
|
||||
mp_text_state text;
|
||||
} mp_input_state;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Window structure
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef struct mp_frame_stats
|
||||
{
|
||||
f64 start;
|
||||
f64 workTime;
|
||||
f64 remainingTime;
|
||||
f64 targetFramePeriod;
|
||||
} mp_frame_stats;
|
||||
|
||||
typedef struct mp_window_data
|
||||
{
|
||||
list_elt freeListElt;
|
||||
u32 generation;
|
||||
|
||||
mp_rect contentRect;
|
||||
mp_rect frameRect;
|
||||
mp_window_style style;
|
||||
|
||||
bool shouldClose; //TODO could be in status flags
|
||||
bool hidden;
|
||||
bool minimized;
|
||||
|
||||
MP_PLATFORM_WINDOW_DATA
|
||||
} mp_window_data;
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Global App State
|
||||
//---------------------------------------------------------------
|
||||
|
||||
enum { MP_APP_MAX_WINDOWS = 128 };
|
||||
|
||||
typedef struct mp_app
|
||||
{
|
||||
bool init;
|
||||
bool shouldQuit;
|
||||
bool minimized;
|
||||
|
||||
str8 pendingPathDrop;
|
||||
mem_arena eventArena;
|
||||
|
||||
ringbuffer eventQueue;
|
||||
|
||||
mp_frame_stats frameStats;
|
||||
|
||||
mp_window_data windowPool[MP_APP_MAX_WINDOWS];
|
||||
list_info windowFreeList;
|
||||
|
||||
mp_input_state inputState;
|
||||
|
||||
mp_key_utf8 keyLabels[256];
|
||||
int keyCodes[256];
|
||||
int nativeKeys[MP_KEY_COUNT];
|
||||
|
||||
MP_PLATFORM_APP_DATA
|
||||
} mp_app;
|
||||
|
||||
|
||||
#endif // __MP_APP_INTERNAL_H_
|
147
src/osx_app.m
147
src/osx_app.m
|
@ -2283,153 +2283,6 @@ void mp_end_input_frame()
|
|||
mem_arena_clear(&__mpAppData.eventArena);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Input state polling
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
mp_key_state mp_input_get_key_state(mp_key_code key)
|
||||
{
|
||||
if(key <= MP_KEY_COUNT)
|
||||
{
|
||||
return(__mpAppData.inputState.keyboard.keys[key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((mp_key_state){0});
|
||||
}
|
||||
}
|
||||
mp_key_state mp_input_get_mouse_button_state(mp_mouse_button button)
|
||||
{
|
||||
if(button <= MP_MOUSE_BUTTON_COUNT)
|
||||
{
|
||||
return(__mpAppData.inputState.mouse.buttons[button]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((mp_key_state){0});
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_input_check_key_transition(mp_key_state* key, bool pressed)
|
||||
{
|
||||
bool res = ( (key->lastUpdate == __mpAppData.inputState.frameCounter)
|
||||
&& key->transitionCounter
|
||||
&&(key->down == pressed || key->transitionCounter > 1));
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_key_down(mp_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_input_get_key_state(key);
|
||||
return(state.down);
|
||||
}
|
||||
bool mp_input_key_pressed(mp_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_input_get_key_state(key);
|
||||
bool res = mp_input_check_key_transition(&state, true);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_key_released(mp_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_input_get_key_state(key);
|
||||
bool res = mp_input_check_key_transition(&state, false);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_down(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
return(state.down);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_pressed(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
bool res = mp_input_check_key_transition(&state, true);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_released(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
bool res = mp_input_check_key_transition(&state, false);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_clicked(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
return(state.clicked);
|
||||
}
|
||||
|
||||
bool mp_input_mouse_double_clicked(mp_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
||||
if(state.lastUpdate == __mpAppData.inputState.frameCounter)
|
||||
{
|
||||
return(state.doubleClicked);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
mp_key_mods mp_input_key_mods()
|
||||
{
|
||||
return(__mpAppData.inputState.keyboard.mods);
|
||||
}
|
||||
|
||||
vec2 mp_input_mouse_position()
|
||||
{
|
||||
return(__mpAppData.inputState.mouse.pos);
|
||||
}
|
||||
|
||||
vec2 mp_input_mouse_delta()
|
||||
{
|
||||
if(__mpAppData.inputState.mouse.lastUpdate == __mpAppData.inputState.frameCounter)
|
||||
{
|
||||
return(__mpAppData.inputState.mouse.delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((vec2){0, 0});
|
||||
}
|
||||
}
|
||||
|
||||
vec2 mp_input_mouse_wheel()
|
||||
{
|
||||
if(__mpAppData.inputState.mouse.lastUpdate == __mpAppData.inputState.frameCounter)
|
||||
{
|
||||
return(__mpAppData.inputState.mouse.wheel);
|
||||
}
|
||||
else
|
||||
{
|
||||
return((vec2){0, 0});
|
||||
}
|
||||
}
|
||||
|
||||
str32 mp_input_text_utf32(mem_arena* arena)
|
||||
{
|
||||
str32 res = {0};
|
||||
if(__mpAppData.inputState.text.lastUpdate == __mpAppData.inputState.frameCounter)
|
||||
{
|
||||
res = str32_push_copy(arena, __mpAppData.inputState.text.codePoints);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
str8 mp_input_text_utf8(mem_arena* arena)
|
||||
{
|
||||
str8 res = {0};
|
||||
if(__mpAppData.inputState.text.lastUpdate == __mpAppData.inputState.frameCounter)
|
||||
{
|
||||
res = utf8_push_from_codepoints(arena, __mpAppData.inputState.text.codePoints);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// app resources
|
||||
//--------------------------------------------------------------------
|
||||
|
|
718
src/win32_app.c
718
src/win32_app.c
|
@ -7,118 +7,240 @@
|
|||
*
|
||||
*****************************************************************/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include<windows.h>
|
||||
|
||||
#include"win32_app.h"
|
||||
#include"ringbuffer.h"
|
||||
#include"mp_app.c"
|
||||
|
||||
#define LOG_SUBSYSTEM "Application"
|
||||
|
||||
|
||||
enum { MP_APP_MAX_WINDOWS = 128 };
|
||||
|
||||
typedef struct mp_app_data
|
||||
void mp_init_keys()
|
||||
{
|
||||
bool init;
|
||||
bool shouldQuit;
|
||||
memset(__mpApp.keyCodes, MP_KEY_UNKNOWN, 256*sizeof(int));
|
||||
|
||||
mp_window_data windowPool[MP_APP_MAX_WINDOWS];
|
||||
list_info windowFreeList;
|
||||
__mpApp.keyCodes[0x00B] = MP_KEY_0;
|
||||
__mpApp.keyCodes[0x002] = MP_KEY_1;
|
||||
__mpApp.keyCodes[0x003] = MP_KEY_2;
|
||||
__mpApp.keyCodes[0x004] = MP_KEY_3;
|
||||
__mpApp.keyCodes[0x005] = MP_KEY_4;
|
||||
__mpApp.keyCodes[0x006] = MP_KEY_5;
|
||||
__mpApp.keyCodes[0x007] = MP_KEY_6;
|
||||
__mpApp.keyCodes[0x008] = MP_KEY_7;
|
||||
__mpApp.keyCodes[0x009] = MP_KEY_8;
|
||||
__mpApp.keyCodes[0x00A] = MP_KEY_9;
|
||||
__mpApp.keyCodes[0x01E] = MP_KEY_A;
|
||||
__mpApp.keyCodes[0x030] = MP_KEY_B;
|
||||
__mpApp.keyCodes[0x02E] = MP_KEY_C;
|
||||
__mpApp.keyCodes[0x020] = MP_KEY_D;
|
||||
__mpApp.keyCodes[0x012] = MP_KEY_E;
|
||||
__mpApp.keyCodes[0x021] = MP_KEY_F;
|
||||
__mpApp.keyCodes[0x022] = MP_KEY_G;
|
||||
__mpApp.keyCodes[0x023] = MP_KEY_H;
|
||||
__mpApp.keyCodes[0x017] = MP_KEY_I;
|
||||
__mpApp.keyCodes[0x024] = MP_KEY_J;
|
||||
__mpApp.keyCodes[0x025] = MP_KEY_K;
|
||||
__mpApp.keyCodes[0x026] = MP_KEY_L;
|
||||
__mpApp.keyCodes[0x032] = MP_KEY_M;
|
||||
__mpApp.keyCodes[0x031] = MP_KEY_N;
|
||||
__mpApp.keyCodes[0x018] = MP_KEY_O;
|
||||
__mpApp.keyCodes[0x019] = MP_KEY_P;
|
||||
__mpApp.keyCodes[0x010] = MP_KEY_Q;
|
||||
__mpApp.keyCodes[0x013] = MP_KEY_R;
|
||||
__mpApp.keyCodes[0x01F] = MP_KEY_S;
|
||||
__mpApp.keyCodes[0x014] = MP_KEY_T;
|
||||
__mpApp.keyCodes[0x016] = MP_KEY_U;
|
||||
__mpApp.keyCodes[0x02F] = MP_KEY_V;
|
||||
__mpApp.keyCodes[0x011] = MP_KEY_W;
|
||||
__mpApp.keyCodes[0x02D] = MP_KEY_X;
|
||||
__mpApp.keyCodes[0x015] = MP_KEY_Y;
|
||||
__mpApp.keyCodes[0x02C] = MP_KEY_Z;
|
||||
__mpApp.keyCodes[0x028] = MP_KEY_APOSTROPHE;
|
||||
__mpApp.keyCodes[0x02B] = MP_KEY_BACKSLASH;
|
||||
__mpApp.keyCodes[0x033] = MP_KEY_COMMA;
|
||||
__mpApp.keyCodes[0x00D] = MP_KEY_EQUAL;
|
||||
__mpApp.keyCodes[0x029] = MP_KEY_GRAVE_ACCENT;
|
||||
__mpApp.keyCodes[0x01A] = MP_KEY_LEFT_BRACKET;
|
||||
__mpApp.keyCodes[0x00C] = MP_KEY_MINUS;
|
||||
__mpApp.keyCodes[0x034] = MP_KEY_PERIOD;
|
||||
__mpApp.keyCodes[0x01B] = MP_KEY_RIGHT_BRACKET;
|
||||
__mpApp.keyCodes[0x027] = MP_KEY_SEMICOLON;
|
||||
__mpApp.keyCodes[0x035] = MP_KEY_SLASH;
|
||||
__mpApp.keyCodes[0x056] = MP_KEY_WORLD_2;
|
||||
__mpApp.keyCodes[0x00E] = MP_KEY_BACKSPACE;
|
||||
__mpApp.keyCodes[0x153] = MP_KEY_DELETE;
|
||||
__mpApp.keyCodes[0x14F] = MP_KEY_END;
|
||||
__mpApp.keyCodes[0x01C] = MP_KEY_ENTER;
|
||||
__mpApp.keyCodes[0x001] = MP_KEY_ESCAPE;
|
||||
__mpApp.keyCodes[0x147] = MP_KEY_HOME;
|
||||
__mpApp.keyCodes[0x152] = MP_KEY_INSERT;
|
||||
__mpApp.keyCodes[0x15D] = MP_KEY_MENU;
|
||||
__mpApp.keyCodes[0x151] = MP_KEY_PAGE_DOWN;
|
||||
__mpApp.keyCodes[0x149] = MP_KEY_PAGE_UP;
|
||||
__mpApp.keyCodes[0x045] = MP_KEY_PAUSE;
|
||||
__mpApp.keyCodes[0x146] = MP_KEY_PAUSE;
|
||||
__mpApp.keyCodes[0x039] = MP_KEY_SPACE;
|
||||
__mpApp.keyCodes[0x00F] = MP_KEY_TAB;
|
||||
__mpApp.keyCodes[0x03A] = MP_KEY_CAPS_LOCK;
|
||||
__mpApp.keyCodes[0x145] = MP_KEY_NUM_LOCK;
|
||||
__mpApp.keyCodes[0x046] = MP_KEY_SCROLL_LOCK;
|
||||
__mpApp.keyCodes[0x03B] = MP_KEY_F1;
|
||||
__mpApp.keyCodes[0x03C] = MP_KEY_F2;
|
||||
__mpApp.keyCodes[0x03D] = MP_KEY_F3;
|
||||
__mpApp.keyCodes[0x03E] = MP_KEY_F4;
|
||||
__mpApp.keyCodes[0x03F] = MP_KEY_F5;
|
||||
__mpApp.keyCodes[0x040] = MP_KEY_F6;
|
||||
__mpApp.keyCodes[0x041] = MP_KEY_F7;
|
||||
__mpApp.keyCodes[0x042] = MP_KEY_F8;
|
||||
__mpApp.keyCodes[0x043] = MP_KEY_F9;
|
||||
__mpApp.keyCodes[0x044] = MP_KEY_F10;
|
||||
__mpApp.keyCodes[0x057] = MP_KEY_F11;
|
||||
__mpApp.keyCodes[0x058] = MP_KEY_F12;
|
||||
__mpApp.keyCodes[0x064] = MP_KEY_F13;
|
||||
__mpApp.keyCodes[0x065] = MP_KEY_F14;
|
||||
__mpApp.keyCodes[0x066] = MP_KEY_F15;
|
||||
__mpApp.keyCodes[0x067] = MP_KEY_F16;
|
||||
__mpApp.keyCodes[0x068] = MP_KEY_F17;
|
||||
__mpApp.keyCodes[0x069] = MP_KEY_F18;
|
||||
__mpApp.keyCodes[0x06A] = MP_KEY_F19;
|
||||
__mpApp.keyCodes[0x06B] = MP_KEY_F20;
|
||||
__mpApp.keyCodes[0x06C] = MP_KEY_F21;
|
||||
__mpApp.keyCodes[0x06D] = MP_KEY_F22;
|
||||
__mpApp.keyCodes[0x06E] = MP_KEY_F23;
|
||||
__mpApp.keyCodes[0x076] = MP_KEY_F24;
|
||||
__mpApp.keyCodes[0x038] = MP_KEY_LEFT_ALT;
|
||||
__mpApp.keyCodes[0x01D] = MP_KEY_LEFT_CONTROL;
|
||||
__mpApp.keyCodes[0x02A] = MP_KEY_LEFT_SHIFT;
|
||||
__mpApp.keyCodes[0x15B] = MP_KEY_LEFT_SUPER;
|
||||
__mpApp.keyCodes[0x137] = MP_KEY_PRINT_SCREEN;
|
||||
__mpApp.keyCodes[0x138] = MP_KEY_RIGHT_ALT;
|
||||
__mpApp.keyCodes[0x11D] = MP_KEY_RIGHT_CONTROL;
|
||||
__mpApp.keyCodes[0x036] = MP_KEY_RIGHT_SHIFT;
|
||||
__mpApp.keyCodes[0x15C] = MP_KEY_RIGHT_SUPER;
|
||||
__mpApp.keyCodes[0x150] = MP_KEY_DOWN;
|
||||
__mpApp.keyCodes[0x14B] = MP_KEY_LEFT;
|
||||
__mpApp.keyCodes[0x14D] = MP_KEY_RIGHT;
|
||||
__mpApp.keyCodes[0x148] = MP_KEY_UP;
|
||||
__mpApp.keyCodes[0x052] = MP_KEY_KP_0;
|
||||
__mpApp.keyCodes[0x04F] = MP_KEY_KP_1;
|
||||
__mpApp.keyCodes[0x050] = MP_KEY_KP_2;
|
||||
__mpApp.keyCodes[0x051] = MP_KEY_KP_3;
|
||||
__mpApp.keyCodes[0x04B] = MP_KEY_KP_4;
|
||||
__mpApp.keyCodes[0x04C] = MP_KEY_KP_5;
|
||||
__mpApp.keyCodes[0x04D] = MP_KEY_KP_6;
|
||||
__mpApp.keyCodes[0x047] = MP_KEY_KP_7;
|
||||
__mpApp.keyCodes[0x048] = MP_KEY_KP_8;
|
||||
__mpApp.keyCodes[0x049] = MP_KEY_KP_9;
|
||||
__mpApp.keyCodes[0x04E] = MP_KEY_KP_ADD;
|
||||
__mpApp.keyCodes[0x053] = MP_KEY_KP_DECIMAL;
|
||||
__mpApp.keyCodes[0x135] = MP_KEY_KP_DIVIDE;
|
||||
__mpApp.keyCodes[0x11C] = MP_KEY_KP_ENTER;
|
||||
__mpApp.keyCodes[0x037] = MP_KEY_KP_MULTIPLY;
|
||||
__mpApp.keyCodes[0x04A] = MP_KEY_KP_SUBTRACT;
|
||||
|
||||
ringbuffer eventQueue;
|
||||
|
||||
} mp_app_data;
|
||||
|
||||
mp_app_data __mpAppData = {0};
|
||||
|
||||
void mp_init_window_handles()
|
||||
{
|
||||
ListInit(&__mpAppData.windowFreeList);
|
||||
for(int i=0; i<MP_APP_MAX_WINDOWS; i++)
|
||||
memset(__mpApp.nativeKeys, 0, sizeof(int)*MP_KEY_COUNT);
|
||||
for(int nativeKey=0; nativeKey<256; nativeKey++)
|
||||
{
|
||||
__mpAppData.windowPool[i].generation = 1;
|
||||
ListAppend(&__mpAppData.windowFreeList, &__mpAppData.windowPool[i].freeListElt);
|
||||
mp_key_code mpKey = __mpApp.keyCodes[nativeKey];
|
||||
if(mpKey)
|
||||
{
|
||||
__mpApp.nativeKeys[mpKey] = nativeKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mp_window_data* mp_window_alloc()
|
||||
{
|
||||
return(ListPopEntry(&__mpAppData.windowFreeList, mp_window_data, freeListElt));
|
||||
}
|
||||
|
||||
mp_window_data* mp_window_ptr_from_handle(mp_window handle)
|
||||
{
|
||||
u32 index = handle.h>>32;
|
||||
u32 generation = handle.h & 0xffffffff;
|
||||
if(index >= MP_APP_MAX_WINDOWS)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
mp_window_data* window = &__mpAppData.windowPool[index];
|
||||
if(window->generation != generation)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(window);
|
||||
}
|
||||
}
|
||||
|
||||
mp_window mp_window_handle_from_ptr(mp_window_data* window)
|
||||
{
|
||||
DEBUG_ASSERT( (window - __mpAppData.windowPool) >= 0
|
||||
&& (window - __mpAppData.windowPool) < MP_APP_MAX_WINDOWS);
|
||||
|
||||
u64 h = ((u64)(window - __mpAppData.windowPool))<<32
|
||||
| ((u64)window->generation);
|
||||
|
||||
return((mp_window){h});
|
||||
}
|
||||
|
||||
void mp_window_recycle_ptr(mp_window_data* window)
|
||||
{
|
||||
window->generation++;
|
||||
ListPush(&__mpAppData.windowFreeList, &window->freeListElt);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
||||
void mp_queue_event(mp_event* event)
|
||||
{
|
||||
if(ringbuffer_write_available(&__mpAppData.eventQueue) < sizeof(mp_event))
|
||||
{
|
||||
LOG_ERROR("event queue full\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 written = ringbuffer_write(&__mpAppData.eventQueue, sizeof(mp_event), (u8*)event);
|
||||
DEBUG_ASSERT(written == sizeof(mp_event));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
||||
void mp_init()
|
||||
{
|
||||
if(!__mpAppData.init)
|
||||
if(!__mpApp.init)
|
||||
{
|
||||
memset(&__mpAppData, 0, sizeof(__mpAppData));
|
||||
mp_init_window_handles();
|
||||
memset(&__mpApp, 0, sizeof(__mpApp));
|
||||
|
||||
ringbuffer_init(&__mpAppData.eventQueue, 16);
|
||||
mp_init_common();
|
||||
mp_init_keys();
|
||||
|
||||
__mpApp.win32.savedConsoleCodePage = GetConsoleOutputCP();
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_terminate()
|
||||
{
|
||||
if(__mpAppData.init)
|
||||
if(__mpApp.init)
|
||||
{
|
||||
__mpAppData = (mp_app_data){0};
|
||||
SetConsoleOutputCP(__mpApp.win32.savedConsoleCodePage);
|
||||
|
||||
mp_terminate_common();
|
||||
__mpApp = (mp_app){0};
|
||||
}
|
||||
}
|
||||
|
||||
static mp_key_code mp_convert_win32_key(int code)
|
||||
{
|
||||
return(__mpApp.keyCodes[code]);
|
||||
}
|
||||
|
||||
static mp_key_mods mp_get_mod_keys()
|
||||
{
|
||||
mp_key_mods mods = 0;
|
||||
if(GetKeyState(VK_SHIFT) & 0x8000)
|
||||
{
|
||||
mods |= MP_KEYMOD_SHIFT;
|
||||
}
|
||||
if(GetKeyState(VK_CONTROL) & 0x8000)
|
||||
{
|
||||
mods |= MP_KEYMOD_CTRL;
|
||||
}
|
||||
if(GetKeyState(VK_MENU) & 0x8000)
|
||||
{
|
||||
mods |= MP_KEYMOD_ALT;
|
||||
}
|
||||
if((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
|
||||
{
|
||||
mods |= MP_KEYMOD_CMD;
|
||||
}
|
||||
return(mods);
|
||||
}
|
||||
|
||||
static void process_mouse_event(mp_window_data* window, mp_key_action action, mp_key_code button)
|
||||
{
|
||||
if(action == MP_KEY_PRESS)
|
||||
{
|
||||
if(!__mpApp.win32.mouseCaptureMask)
|
||||
{
|
||||
SetCapture(window->win32.hWnd);
|
||||
}
|
||||
__mpApp.win32.mouseCaptureMask |= (1<<button);
|
||||
}
|
||||
else if(action == MP_KEY_RELEASE)
|
||||
{
|
||||
__mpApp.win32.mouseCaptureMask &= ~(1<<button);
|
||||
if(!__mpApp.win32.mouseCaptureMask)
|
||||
{
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
mp_update_key_state(&__mpApp.inputState.mouse.buttons[button], action == MP_KEY_PRESS);
|
||||
//TODO click/double click
|
||||
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(window);
|
||||
event.type = MP_EVENT_MOUSE_BUTTON;
|
||||
event.key.action = MP_KEY_PRESS;
|
||||
event.key.code = MP_MOUSE_LEFT;
|
||||
event.key.mods = mp_get_mod_keys();
|
||||
|
||||
mp_queue_event(&event);
|
||||
}
|
||||
|
||||
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.deltaY = y/30.0f;
|
||||
event.move.mods = mp_get_mod_keys();
|
||||
|
||||
mp_queue_event(&event);
|
||||
}
|
||||
|
||||
LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT result = 0;
|
||||
|
@ -133,9 +255,208 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_WINDOW_CLOSE;
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
//TODO: enter/exit size & move
|
||||
|
||||
case WM_SIZING:
|
||||
{
|
||||
RECT* rect = (RECT*)lParam;
|
||||
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_WINDOW_RESIZE;
|
||||
event.frame.rect = (mp_rect){rect->bottom, rect->left, rect->top - rect->bottom, rect->right - rect->left};
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
case WM_MOVING:
|
||||
{
|
||||
RECT* rect = (RECT*)lParam;
|
||||
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_WINDOW_MOVE;
|
||||
event.frame.rect = (mp_rect){rect->bottom, rect->left, rect->top - rect->bottom, rect->right - rect->left};
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
{
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_WINDOW_FOCUS;
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
{
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_WINDOW_UNFOCUS;
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
case WM_SIZE:
|
||||
{
|
||||
bool minimized = (wParam == SIZE_MINIMIZED);
|
||||
if(minimized != mpWindow->minimized)
|
||||
{
|
||||
mpWindow->minimized = minimized;
|
||||
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
|
||||
if(minimized)
|
||||
{
|
||||
event.type = MP_EVENT_WINDOW_HIDE;
|
||||
}
|
||||
else if(mpWindow->minimized)
|
||||
{
|
||||
event.type = MP_EVENT_WINDOW_SHOW;
|
||||
}
|
||||
mp_queue_event(&event);
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
{
|
||||
process_mouse_event(mpWindow, MP_KEY_PRESS, MP_MOUSE_LEFT);
|
||||
} break;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
{
|
||||
process_mouse_event(mpWindow, MP_KEY_PRESS, MP_MOUSE_RIGHT);
|
||||
} break;
|
||||
|
||||
case WM_MBUTTONDOWN:
|
||||
{
|
||||
process_mouse_event(mpWindow, MP_KEY_PRESS, MP_MOUSE_MIDDLE);
|
||||
} break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
{
|
||||
process_mouse_event(mpWindow, MP_KEY_RELEASE, MP_MOUSE_LEFT);
|
||||
} break;
|
||||
|
||||
case WM_RBUTTONUP:
|
||||
{
|
||||
process_mouse_event(mpWindow, MP_KEY_RELEASE, MP_MOUSE_RIGHT);
|
||||
} break;
|
||||
|
||||
case WM_MBUTTONUP:
|
||||
{
|
||||
process_mouse_event(mpWindow, MP_KEY_RELEASE, MP_MOUSE_MIDDLE);
|
||||
} break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(mpWindow->win32.hWnd, &rect);
|
||||
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_MOUSE_MOVE;
|
||||
event.move.x = LOWORD(lParam);
|
||||
event.move.y = rect.bottom - HIWORD(lParam);
|
||||
|
||||
if(__mpApp.inputState.mouse.posValid)
|
||||
{
|
||||
event.move.deltaX = event.move.x - __mpApp.inputState.mouse.pos.x;
|
||||
event.move.deltaY = event.move.y - __mpApp.inputState.mouse.pos.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
__mpApp.inputState.mouse.posValid = true;
|
||||
}
|
||||
|
||||
if(!__mpApp.win32.mouseTracked)
|
||||
{
|
||||
__mpApp.win32.mouseTracked = true;
|
||||
|
||||
TRACKMOUSEEVENT track;
|
||||
memset(&track, 0, sizeof(track));
|
||||
track.cbSize = sizeof(track);
|
||||
track.dwFlags = TME_LEAVE;
|
||||
track.hwndTrack = mpWindow->win32.hWnd;
|
||||
TrackMouseEvent(&track);
|
||||
|
||||
mp_event enter = {.window = event.window,
|
||||
.type = MP_EVENT_MOUSE_ENTER,
|
||||
.move.x = event.move.x,
|
||||
.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_queue_event(&event);
|
||||
} break;
|
||||
|
||||
case WM_MOUSELEAVE:
|
||||
{
|
||||
__mpApp.win32.mouseTracked = false;
|
||||
|
||||
if(!__mpApp.win32.mouseCaptureMask)
|
||||
{
|
||||
__mpApp.inputState.mouse.posValid = false;
|
||||
}
|
||||
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_MOUSE_LEAVE;
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
process_wheel_event(mpWindow, 0, (float)((i16)HIWORD(wParam)));
|
||||
} break;
|
||||
|
||||
case WM_MOUSEHWHEEL:
|
||||
{
|
||||
process_wheel_event(mpWindow, (float)((i16)HIWORD(wParam)), 0);
|
||||
} break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
{
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_KEYBOARD_KEY;
|
||||
event.key.action = (lParam & 0x40000000) ? MP_KEY_REPEAT : MP_KEY_PRESS;
|
||||
event.key.code = mp_convert_win32_key(HIWORD(lParam) & 0x1ff);
|
||||
event.key.mods = mp_get_mod_keys();
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
mp_event event = {0};
|
||||
event.window = mp_window_handle_from_ptr(mpWindow);
|
||||
event.type = MP_EVENT_KEYBOARD_KEY;
|
||||
event.key.action = MP_KEY_RELEASE;
|
||||
event.key.code = mp_convert_win32_key(HIWORD(lParam) & 0x1ff);
|
||||
event.key.mods = mp_get_mod_keys();
|
||||
mp_queue_event(&event);
|
||||
} break;
|
||||
|
||||
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);
|
||||
} break;
|
||||
|
||||
case WM_DROPFILES:
|
||||
{
|
||||
//TODO
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
@ -147,6 +468,40 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
return(result);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// app management
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
bool mp_should_quit()
|
||||
{
|
||||
return(__mpApp.shouldQuit);
|
||||
}
|
||||
|
||||
void mp_cancel_quit()
|
||||
{
|
||||
__mpApp.shouldQuit = false;
|
||||
}
|
||||
|
||||
void mp_request_quit()
|
||||
{
|
||||
__mpApp.shouldQuit = true;
|
||||
}
|
||||
|
||||
void mp_pump_events(f64 timeout)
|
||||
{
|
||||
MSG message;
|
||||
while(PeekMessage(&message, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&message);
|
||||
DispatchMessage(&message);
|
||||
}
|
||||
__mpApp.inputState.frameCounter++;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// window management
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
mp_window mp_window_create(mp_rect rect, const char* title, mp_window_style style)
|
||||
{
|
||||
WNDCLASS windowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
||||
|
@ -177,50 +532,44 @@ mp_window mp_window_create(mp_rect rect, const char* title, mp_window_style styl
|
|||
//TODO: return wrapped window
|
||||
quit:;
|
||||
mp_window_data* window = mp_window_alloc();
|
||||
window->windowHandle = windowHandle;
|
||||
window->win32.hWnd = windowHandle;
|
||||
|
||||
SetPropW(windowHandle, L"MilePost", window);
|
||||
|
||||
return(mp_window_handle_from_ptr(window));
|
||||
}
|
||||
|
||||
void mp_window_bring_to_front_and_focus(mp_window window)
|
||||
void mp_window_destroy(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
ShowWindow(windowData->windowHandle, 1);
|
||||
DestroyWindow(windowData->win32.hWnd);
|
||||
//TODO: check when to unregister class
|
||||
|
||||
mp_window_recycle_ptr(windowData);
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_should_quit()
|
||||
void* mp_window_native_pointer(mp_window window)
|
||||
{
|
||||
return(__mpAppData.shouldQuit);
|
||||
}
|
||||
|
||||
void mp_do_quit()
|
||||
{
|
||||
__mpAppData.shouldQuit = true;
|
||||
}
|
||||
|
||||
void mp_pump_events(f64 timeout)
|
||||
{
|
||||
MSG message;
|
||||
while(PeekMessage(&message, 0, 0, 0, PM_REMOVE))
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
TranslateMessage(&message);
|
||||
DispatchMessage(&message);
|
||||
return(windowData->win32.hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_next_event(mp_event* event)
|
||||
bool mp_window_should_close(mp_window window)
|
||||
{
|
||||
//NOTE pop and return event from queue
|
||||
if(ringbuffer_read_available(&__mpAppData.eventQueue) >= sizeof(mp_event))
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
u64 read = ringbuffer_read(&__mpAppData.eventQueue, sizeof(mp_event), (u8*)event);
|
||||
DEBUG_ASSERT(read == sizeof(mp_event));
|
||||
return(true);
|
||||
return(windowData->shouldClose);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -228,5 +577,148 @@ bool mp_next_event(mp_event* event)
|
|||
}
|
||||
}
|
||||
|
||||
void mp_window_request_close(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
windowData->shouldClose = true;
|
||||
PostMessage(windowData->win32.hWnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_cancel_close(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
windowData->shouldClose = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool mp_window_is_hidden(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
return(IsWindowVisible(windowData->win32.hWnd));
|
||||
}
|
||||
else
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_hide(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
ShowWindow(windowData->win32.hWnd, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_show(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
ShowWindow(windowData->win32.hWnd, SW_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_window_is_minimized(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
return(windowData->minimized);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_minimize(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
ShowWindow(windowData->win32.hWnd, SW_MINIMIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_maximize(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
ShowWindow(windowData->win32.hWnd, SW_MAXIMIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_restore(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
ShowWindow(windowData->win32.hWnd, SW_RESTORE);
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_window_has_focus(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
return(GetActiveWindow() == windowData->win32.hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_focus(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
SetFocus(windowData->win32.hWnd);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_unfocus(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
SetFocus(0);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_send_to_back(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
SetWindowPos(windowData->win32.hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_window_bring_to_front(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
if(!IsWindowVisible(windowData->win32.hWnd))
|
||||
{
|
||||
ShowWindow(windowData->win32.hWnd, SW_NORMAL);
|
||||
}
|
||||
SetWindowPos(windowData->win32.hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOG_SUBSYSTEM
|
||||
|
|
|
@ -10,17 +10,27 @@
|
|||
#ifndef __WIN32_APP_H_
|
||||
#define __WIN32_APP_H_
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include<windows.h>
|
||||
#include"mp_app.h"
|
||||
|
||||
typedef struct mp_window_data
|
||||
typedef struct win32_window_data
|
||||
{
|
||||
list_elt freeListElt;
|
||||
u32 generation;
|
||||
HWND hWnd;
|
||||
|
||||
HWND windowHandle;
|
||||
} mp_window_data;
|
||||
} win32_window_data;
|
||||
|
||||
mp_window_data* mp_window_ptr_from_handle(mp_window handle);
|
||||
//mp_view_data* mp_view_ptr_from_handle(mp_view handle);
|
||||
#define MP_PLATFORM_WINDOW_DATA win32_window_data win32;
|
||||
|
||||
typedef struct win32_app_data
|
||||
{
|
||||
u32 savedConsoleCodePage;
|
||||
|
||||
int mouseCaptureMask;
|
||||
bool mouseTracked;
|
||||
|
||||
} win32_app_data;
|
||||
|
||||
#define MP_PLATFORM_APP_DATA win32_app_data win32;
|
||||
|
||||
#endif __WIN32_APP_H_
|
||||
|
|
|
@ -166,7 +166,7 @@ mg_surface mg_gl_surface_create_for_window(mp_window window)
|
|||
WGL_STENCIL_BITS_ARB, 8,
|
||||
0};
|
||||
|
||||
HDC hDC = GetDC(windowData->windowHandle);
|
||||
HDC hDC = GetDC(windowData->win32.hWnd);
|
||||
u32 numFormats = 0;
|
||||
|
||||
wglChoosePixelFormatARB(hDC, pixelFormatAttrs, 0, 1, &pixelFormat, &numFormats);
|
||||
|
|
63
todo.txt
63
todo.txt
|
@ -1,4 +1,67 @@
|
|||
|
||||
Windows port
|
||||
------------
|
||||
[.] Finish events handling
|
||||
[x] window
|
||||
[x] mouse move/buttons/enter/leave
|
||||
[x] mouse wheel
|
||||
[.] keys
|
||||
[!] set key label
|
||||
[x] text input
|
||||
[/] pathdrop
|
||||
|
||||
[x] Unify app struct and window structs for different platforms?
|
||||
> define common app and window struct in mp_app_internal.h
|
||||
> this file conditionally includes platform specific headers, win32_app.h, osx_app.h, etc...
|
||||
> these define a macro to fill the common app and window structures with platform specific stuff.
|
||||
> Common app/window proc are defined in mp_app.c
|
||||
> Platform specific stuff is defined in platform specific files win32_app.c, osx_app.m, etc...
|
||||
(mp_app.c can 'see' platform specific stuff, so ObjectiveC defs pose a problem, but we can define id as void*
|
||||
when not in ObjC...)
|
||||
|
||||
[.] Implement input polling
|
||||
[ ] Simplify input polling API names
|
||||
[/] Try to simplify input state and polling once we have UI usage code
|
||||
|
||||
[ ] Finish window properties query/setting
|
||||
|
||||
[ ] use isARepeat in macos keyDown event and simplify update key state
|
||||
|
||||
[ ] Implement clipboard
|
||||
[ ] Implement file dialogs
|
||||
[ ] Impement resource path... -> maybe in abstracted file handling
|
||||
|
||||
|
||||
[ ] Clean backend selection (compile time and runtime)
|
||||
[ ] Finish OpenGL loader
|
||||
[ ] Test compute shaders
|
||||
[ ] Initial version of vector graphics backend
|
||||
[ ] Check integration of UI.
|
||||
|
||||
[ ] Views (using docked windows?) -- or see if we can use surfaces and restrict their location?
|
||||
|
||||
[ ] test new run loop structure on macos
|
||||
[ ] Remove unused APIs
|
||||
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
[ ] Clean-up file structure
|
||||
[ ] Move stb libs to ext/
|
||||
|
||||
[ ] Renaming/clean-up pass
|
||||
[ ] Separate Internal/API functions in mp_app.c
|
||||
[ ] Remove MP_EVENT_KEYBOARD_MODS
|
||||
[ ] Rename MP_EVENT_HIDE/SHOW to MINMIZE/UNMINIMIZE
|
||||
[ ] Remove frame
|
||||
[ ] Remove sequence from char event?
|
||||
[ ] Replace frame_event with mp_rect
|
||||
[ ] Document/unify quit/request_quit etc
|
||||
[ ] Document/unify close/request_close etc
|
||||
[ ] Cleanup window management
|
||||
[ ] Remove unused run loop constructs
|
||||
[ ]
|
||||
|
||||
Shortlist
|
||||
---------
|
||||
|
|
Loading…
Reference in New Issue