[wip, input system] Fixed bug on macOS, where keyUp events are not received when the command modifier key is down and makes a meaningful combination with the pressed key (note this is normal macOS event handling behaviour, but we still want all events to arrive to track key states).
Fixed by overloading the sendEvent method of our derived NSApplication class. There we check if modifier is down and send the event. Note glfw solves that by adding a block handler for the keyUp event with addLocalMonitorForEventsMatchingMask.
This commit is contained in:
parent
c04e8639ab
commit
e95efe85e8
185
src/mp_app.c
185
src/mp_app.c
|
@ -129,23 +129,47 @@ bool mp_next_event(mp_event* event)
|
||||||
// Input state updating
|
// Input state updating
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
static void mp_update_key_state(mp_key_state* key, bool down)
|
static void mp_update_key_state(mp_key_state* key, mp_key_action action)
|
||||||
{
|
{
|
||||||
u64 frameCounter = __mpApp.inputState.frameCounter;
|
u64 frameCounter = __mpApp.inputState.frameCounter;
|
||||||
if(key->lastUpdate != frameCounter)
|
if(key->lastUpdate != frameCounter)
|
||||||
{
|
{
|
||||||
key->transitionCounter = 0;
|
key->transitionCount = 0;
|
||||||
key->clicked = false;
|
key->repeatCount = 0;
|
||||||
key->doubleClicked = false;
|
key->sysClicked = false;
|
||||||
|
key->sysDoubleClicked = false;
|
||||||
key->lastUpdate = frameCounter;
|
key->lastUpdate = frameCounter;
|
||||||
}
|
}
|
||||||
if(key->down != down)
|
|
||||||
|
switch(action)
|
||||||
{
|
{
|
||||||
key->transitionCounter++;
|
case MP_KEY_PRESS:
|
||||||
|
{
|
||||||
|
if(!key->down)
|
||||||
|
{
|
||||||
|
key->transitionCount++;
|
||||||
|
}
|
||||||
|
key->down = true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_KEY_REPEAT:
|
||||||
|
{
|
||||||
|
key->repeatCount++;
|
||||||
|
key->down = true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_KEY_RELEASE:
|
||||||
|
{
|
||||||
|
if(key->down)
|
||||||
|
{
|
||||||
|
key->transitionCount++;
|
||||||
|
}
|
||||||
|
key->down = false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
key->down = down;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mp_update_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY)
|
static void mp_update_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY)
|
||||||
|
@ -204,107 +228,138 @@ static void mp_update_text(utf32 codepoint)
|
||||||
// Input state polling
|
// Input state polling
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
mp_key_state mp_input_get_key_state(mp_key_code key)
|
mp_key_state mp_key_get_state(mp_key_code key)
|
||||||
{
|
{
|
||||||
|
mp_key_state state = {0};
|
||||||
if(key <= MP_KEY_COUNT)
|
if(key <= MP_KEY_COUNT)
|
||||||
{
|
{
|
||||||
return(__mpApp.inputState.keyboard.keys[key]);
|
state = __mpApp.inputState.keyboard.keys[key];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return((mp_key_state){0});
|
|
||||||
}
|
}
|
||||||
|
return(state);
|
||||||
}
|
}
|
||||||
mp_key_state mp_input_get_mouse_button_state(mp_mouse_button button)
|
|
||||||
|
mp_key_state mp_mouse_button_get_state(mp_mouse_button button)
|
||||||
{
|
{
|
||||||
|
mp_key_state state = {0};
|
||||||
if(button <= MP_MOUSE_BUTTON_COUNT)
|
if(button <= MP_MOUSE_BUTTON_COUNT)
|
||||||
{
|
{
|
||||||
return(__mpApp.inputState.mouse.buttons[button]);
|
state = __mpApp.inputState.mouse.buttons[button];
|
||||||
}
|
}
|
||||||
else
|
return(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mp_key_state_press_count(mp_key_state* key)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
if(key->lastUpdate == __mpApp.inputState.frameCounter)
|
||||||
{
|
{
|
||||||
return((mp_key_state){0});
|
count = key->transitionCount / 2;
|
||||||
|
if(key->down)
|
||||||
|
{
|
||||||
|
//NOTE: add one if state is down transition count is odd
|
||||||
|
count += (key->transitionCount & 0x01);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_check_key_transition(mp_key_state* key, bool pressed)
|
int mp_key_state_release_count(mp_key_state* key)
|
||||||
{
|
{
|
||||||
bool res = ( (key->lastUpdate == __mpApp.inputState.frameCounter)
|
int count = 0;
|
||||||
&& key->transitionCounter
|
if(key->lastUpdate == __mpApp.inputState.frameCounter)
|
||||||
&&(key->down == pressed || key->transitionCounter > 1));
|
{
|
||||||
return(res);
|
count = key->transitionCount / 2;
|
||||||
|
if(!key->down)
|
||||||
|
{
|
||||||
|
//NOTE: add one if state is up and transition count is odd
|
||||||
|
count += (key->transitionCount & 0x01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_key_down(mp_key_code key)
|
int mp_key_state_repeat_count(mp_key_state* key)
|
||||||
{
|
{
|
||||||
mp_key_state state = mp_input_get_key_state(key);
|
int count = 0;
|
||||||
return(state.down);
|
if(key->lastUpdate == __mpApp.inputState.frameCounter)
|
||||||
}
|
{
|
||||||
bool mp_input_key_pressed(mp_key_code key)
|
count = key->repeatCount;
|
||||||
{
|
}
|
||||||
mp_key_state state = mp_input_get_key_state(key);
|
return(count);
|
||||||
bool res = mp_input_check_key_transition(&state, true);
|
|
||||||
return(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_key_released(mp_key_code key)
|
bool mp_key_down(mp_key_code key)
|
||||||
{
|
{
|
||||||
mp_key_state state = mp_input_get_key_state(key);
|
mp_key_state state = mp_key_get_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);
|
return(state.down);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_mouse_pressed(mp_mouse_button button)
|
int mp_key_pressed(mp_key_code key)
|
||||||
{
|
{
|
||||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
mp_key_state state = mp_key_get_state(key);
|
||||||
bool res = mp_input_check_key_transition(&state, true);
|
int res = mp_key_state_press_count(&state);
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_mouse_released(mp_mouse_button button)
|
int mp_key_released(mp_key_code key)
|
||||||
{
|
{
|
||||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
mp_key_state state = mp_key_get_state(key);
|
||||||
bool res = mp_input_check_key_transition(&state, false);
|
int res = mp_key_state_release_count(&state);
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_mouse_clicked(mp_mouse_button button)
|
int mp_key_repeated(mp_key_code key)
|
||||||
{
|
{
|
||||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
mp_key_state state = mp_key_get_state(key);
|
||||||
bool clicked = state.clicked && (state.lastUpdate == __mpApp.inputState.frameCounter);
|
int res = mp_key_state_repeat_count(&state);
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mp_mouse_down(mp_mouse_button button)
|
||||||
|
{
|
||||||
|
mp_key_state state = mp_mouse_button_get_state(button);
|
||||||
|
return(state.down);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mp_mouse_pressed(mp_mouse_button button)
|
||||||
|
{
|
||||||
|
mp_key_state state = mp_mouse_button_get_state(button);
|
||||||
|
int res = mp_key_state_press_count(&state);
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mp_mouse_released(mp_mouse_button button)
|
||||||
|
{
|
||||||
|
mp_key_state state = mp_mouse_button_get_state(button);
|
||||||
|
int res = mp_key_state_release_count(&state);
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mp_mouse_clicked(mp_mouse_button button)
|
||||||
|
{
|
||||||
|
mp_key_state state = mp_mouse_button_get_state(button);
|
||||||
|
bool clicked = state.sysClicked && (state.lastUpdate == __mpApp.inputState.frameCounter);
|
||||||
return(clicked);
|
return(clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_mouse_double_clicked(mp_mouse_button button)
|
bool mp_mouse_double_clicked(mp_mouse_button button)
|
||||||
{
|
{
|
||||||
mp_key_state state = mp_input_get_mouse_button_state(button);
|
mp_key_state state = mp_mouse_button_get_state(button);
|
||||||
if(state.lastUpdate == __mpApp.inputState.frameCounter)
|
bool doubleClicked = state.sysClicked && (state.lastUpdate == __mpApp.inputState.frameCounter);
|
||||||
{
|
return(doubleClicked);
|
||||||
return(state.doubleClicked);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_key_mods mp_input_key_mods()
|
mp_keymod_flags mp_key_mods()
|
||||||
{
|
{
|
||||||
return(__mpApp.inputState.keyboard.mods);
|
return(__mpApp.inputState.keyboard.mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 mp_input_mouse_position()
|
vec2 mp_mouse_position()
|
||||||
{
|
{
|
||||||
return(__mpApp.inputState.mouse.pos);
|
return(__mpApp.inputState.mouse.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 mp_input_mouse_delta()
|
vec2 mp_mouse_delta()
|
||||||
{
|
{
|
||||||
if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter)
|
if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter)
|
||||||
{
|
{
|
||||||
|
@ -316,7 +371,7 @@ vec2 mp_input_mouse_delta()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 mp_input_mouse_wheel()
|
vec2 mp_mouse_wheel()
|
||||||
{
|
{
|
||||||
if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter)
|
if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter)
|
||||||
{
|
{
|
||||||
|
|
34
src/mp_app.h
34
src/mp_app.h
|
@ -193,7 +193,7 @@ typedef enum {
|
||||||
MP_KEYMOD_ALT = 0x01,
|
MP_KEYMOD_ALT = 0x01,
|
||||||
MP_KEYMOD_SHIFT = 0x02,
|
MP_KEYMOD_SHIFT = 0x02,
|
||||||
MP_KEYMOD_CTRL = 0x04,
|
MP_KEYMOD_CTRL = 0x04,
|
||||||
MP_KEYMOD_CMD = 0x08 } mp_key_mods;
|
MP_KEYMOD_CMD = 0x08 } mp_keymod_flags;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MP_MOUSE_LEFT = 0x00,
|
MP_MOUSE_LEFT = 0x00,
|
||||||
|
@ -207,7 +207,7 @@ typedef struct mp_key_event // keyboard and mouse buttons input
|
||||||
{
|
{
|
||||||
mp_key_action action;
|
mp_key_action action;
|
||||||
i32 code;
|
i32 code;
|
||||||
mp_key_mods mods;
|
mp_keymod_flags mods;
|
||||||
char label[8];
|
char label[8];
|
||||||
u8 labelLen;
|
u8 labelLen;
|
||||||
int clickCount;
|
int clickCount;
|
||||||
|
@ -226,7 +226,7 @@ typedef struct mp_move_event // mouse move/scroll
|
||||||
f32 y;
|
f32 y;
|
||||||
f32 deltaX;
|
f32 deltaX;
|
||||||
f32 deltaY;
|
f32 deltaY;
|
||||||
mp_key_mods mods;
|
mp_keymod_flags mods;
|
||||||
} mp_move_event;
|
} mp_move_event;
|
||||||
|
|
||||||
typedef struct mp_frame_event // window resize / move
|
typedef struct mp_frame_event // window resize / move
|
||||||
|
@ -322,27 +322,27 @@ MP_API mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_win
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// Input state polling
|
// Input state polling
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
MP_API bool mp_input_key_down(mp_key_code key);
|
|
||||||
MP_API bool mp_input_key_pressed(mp_key_code key);
|
|
||||||
MP_API bool mp_input_key_released(mp_key_code key);
|
|
||||||
MP_API mp_key_mods mp_input_key_mods(void);
|
|
||||||
|
|
||||||
MP_API str8 mp_key_to_label(mp_key_code key);
|
MP_API bool mp_key_down(mp_key_code key);
|
||||||
MP_API mp_key_code mp_label_to_key(str8 label);
|
MP_API int mp_key_pressed(mp_key_code key);
|
||||||
|
MP_API int mp_key_released(mp_key_code key);
|
||||||
|
MP_API int mp_key_repeated(mp_key_code key);
|
||||||
|
|
||||||
MP_API bool mp_input_mouse_down(mp_mouse_button button);
|
MP_API bool mp_mouse_down(mp_mouse_button button);
|
||||||
MP_API bool mp_input_mouse_pressed(mp_mouse_button button);
|
MP_API int mp_mouse_pressed(mp_mouse_button button);
|
||||||
MP_API bool mp_input_mouse_released(mp_mouse_button button);
|
MP_API int mp_mouse_released(mp_mouse_button button);
|
||||||
MP_API bool mp_input_mouse_clicked(mp_mouse_button button);
|
MP_API bool mp_mouse_clicked(mp_mouse_button button);
|
||||||
MP_API bool mp_input_mouse_double_clicked(mp_mouse_button button);
|
MP_API bool mp_mouse_double_clicked(mp_mouse_button button);
|
||||||
|
|
||||||
MP_API vec2 mp_input_mouse_position(void);
|
MP_API vec2 mp_mouse_position(void);
|
||||||
MP_API vec2 mp_input_mouse_delta(void);
|
MP_API vec2 mp_mouse_delta(void);
|
||||||
MP_API vec2 mp_input_mouse_wheel(void);
|
MP_API vec2 mp_mouse_wheel(void);
|
||||||
|
|
||||||
MP_API str32 mp_input_text_utf32(mem_arena* arena);
|
MP_API str32 mp_input_text_utf32(mem_arena* arena);
|
||||||
MP_API str8 mp_input_text_utf8(mem_arena* arena);
|
MP_API str8 mp_input_text_utf8(mem_arena* arena);
|
||||||
|
|
||||||
|
MP_API mp_keymod_flags mp_key_mods();
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// Clipboard
|
// Clipboard
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
|
@ -35,17 +35,18 @@ typedef struct mp_key_utf8
|
||||||
typedef struct mp_key_state
|
typedef struct mp_key_state
|
||||||
{
|
{
|
||||||
u64 lastUpdate;
|
u64 lastUpdate;
|
||||||
u32 transitionCounter;
|
u32 transitionCount;
|
||||||
|
u32 repeatCount;
|
||||||
bool down;
|
bool down;
|
||||||
bool clicked;
|
bool sysClicked;
|
||||||
bool doubleClicked;
|
bool sysDoubleClicked;
|
||||||
|
|
||||||
} mp_key_state;
|
} mp_key_state;
|
||||||
|
|
||||||
typedef struct mp_keyboard_state
|
typedef struct mp_keyboard_state
|
||||||
{
|
{
|
||||||
mp_key_state keys[MP_KEY_COUNT];
|
mp_key_state keys[MP_KEY_COUNT];
|
||||||
mp_key_mods mods;
|
mp_keymod_flags mods;
|
||||||
} mp_keyboard_state;
|
} mp_keyboard_state;
|
||||||
|
|
||||||
typedef struct mp_mouse_state
|
typedef struct mp_mouse_state
|
||||||
|
|
112
src/osx_app.m
112
src/osx_app.m
|
@ -236,9 +236,9 @@ static int mp_convert_osx_key(unsigned short nsCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_key_mods mp_convert_osx_mods(NSUInteger nsFlags)
|
static mp_keymod_flags mp_convert_osx_mods(NSUInteger nsFlags)
|
||||||
{
|
{
|
||||||
mp_key_mods mods = MP_KEYMOD_NONE;
|
mp_keymod_flags mods = MP_KEYMOD_NONE;
|
||||||
if(nsFlags & NSEventModifierFlagShift)
|
if(nsFlags & NSEventModifierFlagShift)
|
||||||
{
|
{
|
||||||
mods |= MP_KEYMOD_SHIFT;
|
mods |= MP_KEYMOD_SHIFT;
|
||||||
|
@ -369,7 +369,7 @@ void mp_install_keyboard_layout_listener()
|
||||||
object:nil];
|
object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mp_update_key_mods(mp_key_mods mods)
|
static void mp_update_key_mods(mp_keymod_flags mods)
|
||||||
{
|
{
|
||||||
__mpApp.inputState.keyboard.mods = mods;
|
__mpApp.inputState.keyboard.mods = mods;
|
||||||
}
|
}
|
||||||
|
@ -384,6 +384,15 @@ static void mp_update_key_mods(mp_key_mods mods)
|
||||||
@implementation MPApplication
|
@implementation MPApplication
|
||||||
-(void)noOpThread:(id)object
|
-(void)noOpThread:(id)object
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
//This is necessary in order to receive keyUp events when we have a key combination with Cmd.
|
||||||
|
- (void)sendEvent:(NSEvent *)event {
|
||||||
|
if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand))
|
||||||
|
[[self keyWindow] sendEvent:event];
|
||||||
|
else
|
||||||
|
[super sendEvent:event];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface MPAppDelegate : NSObject <NSApplicationDelegate>
|
@interface MPAppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
@ -791,101 +800,61 @@ static void mp_update_key_mods(mp_key_mods mods)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDown:(NSEvent *)nsEvent
|
static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp_mouse_button button, mp_key_action action)
|
||||||
{
|
{
|
||||||
mp_event event = {};
|
mp_event event = {};
|
||||||
event.window = mp_window_handle_from_ptr(window);
|
event.window = mp_window_handle_from_ptr(window);
|
||||||
event.type = MP_EVENT_MOUSE_BUTTON;
|
event.type = MP_EVENT_MOUSE_BUTTON;
|
||||||
event.key.action = MP_KEY_PRESS;
|
event.key.action = action;
|
||||||
event.key.code = MP_MOUSE_LEFT;
|
event.key.code = button;
|
||||||
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
||||||
event.key.clickCount = [nsEvent clickCount];
|
event.key.clickCount = [nsEvent clickCount];
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.mouse.buttons[event.key.code], true);
|
mp_key_state* keyState = &__mpApp.inputState.mouse.buttons[event.key.code];
|
||||||
if(event.key.clickCount >= 1)
|
mp_update_key_state(keyState, action);
|
||||||
|
if(action == MP_KEY_PRESS)
|
||||||
{
|
{
|
||||||
__mpApp.inputState.mouse.buttons[event.key.code].clicked = true;
|
if(event.key.clickCount >= 1)
|
||||||
|
{
|
||||||
|
keyState->sysClicked = true;
|
||||||
|
}
|
||||||
|
if(event.key.clickCount >= 2)
|
||||||
|
{
|
||||||
|
keyState->sysDoubleClicked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(event.key.clickCount >= 2)
|
|
||||||
{
|
|
||||||
|
|
||||||
__mpApp.inputState.mouse.buttons[event.key.code].doubleClicked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_queue_event(&event);
|
mp_queue_event(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDown:(NSEvent *)nsEvent
|
||||||
|
{
|
||||||
|
mp_process_mouse_button(nsEvent, window, MP_MOUSE_LEFT, MP_KEY_PRESS);
|
||||||
[window->osx.nsWindow makeFirstResponder:self];
|
[window->osx.nsWindow makeFirstResponder:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseUp:(NSEvent*)nsEvent
|
- (void)mouseUp:(NSEvent*)nsEvent
|
||||||
{
|
{
|
||||||
mp_event event = {};
|
mp_process_mouse_button(nsEvent, window, MP_MOUSE_LEFT, MP_KEY_RELEASE);
|
||||||
event.window = mp_window_handle_from_ptr(window);
|
|
||||||
event.type = MP_EVENT_MOUSE_BUTTON;
|
|
||||||
event.key.action = MP_KEY_RELEASE;
|
|
||||||
event.key.code = MP_MOUSE_LEFT;
|
|
||||||
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
|
||||||
event.key.clickCount = [nsEvent clickCount];
|
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.mouse.buttons[event.key.code], false);
|
|
||||||
|
|
||||||
mp_queue_event(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)rightMouseDown:(NSEvent*)nsEvent
|
- (void)rightMouseDown:(NSEvent*)nsEvent
|
||||||
{
|
{
|
||||||
mp_event event = {};
|
mp_process_mouse_button(nsEvent, window, MP_MOUSE_RIGHT, MP_KEY_PRESS);
|
||||||
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_RIGHT;
|
|
||||||
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.mouse.buttons[event.key.code], true);
|
|
||||||
|
|
||||||
mp_queue_event(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)rightMouseUp:(NSEvent*)nsEvent
|
- (void)rightMouseUp:(NSEvent*)nsEvent
|
||||||
{
|
{
|
||||||
mp_event event = {};
|
mp_process_mouse_button(nsEvent, window, MP_MOUSE_RIGHT, MP_KEY_RELEASE);
|
||||||
event.window = mp_window_handle_from_ptr(window);
|
|
||||||
event.type = MP_EVENT_MOUSE_BUTTON;
|
|
||||||
event.key.action = MP_KEY_RELEASE;
|
|
||||||
event.key.code = MP_MOUSE_RIGHT;
|
|
||||||
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.mouse.buttons[event.key.code], false);
|
|
||||||
|
|
||||||
mp_queue_event(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)otherMouseDown:(NSEvent*)nsEvent
|
- (void)otherMouseDown:(NSEvent*)nsEvent
|
||||||
{
|
{
|
||||||
mp_event event = {};
|
mp_process_mouse_button(nsEvent, window, [nsEvent buttonNumber], MP_KEY_PRESS);
|
||||||
event.window = mp_window_handle_from_ptr(window);
|
|
||||||
event.type = MP_EVENT_MOUSE_BUTTON;
|
|
||||||
event.key.action = MP_KEY_PRESS;
|
|
||||||
event.key.code = [nsEvent buttonNumber];
|
|
||||||
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.mouse.buttons[event.key.code], true);
|
|
||||||
|
|
||||||
mp_queue_event(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)otherMouseUp:(NSEvent*)nsEvent
|
- (void)otherMouseUp:(NSEvent*)nsEvent
|
||||||
{
|
{
|
||||||
mp_event event = {};
|
mp_process_mouse_button(nsEvent, window, [nsEvent buttonNumber], MP_KEY_RELEASE);
|
||||||
event.window = mp_window_handle_from_ptr(window);
|
|
||||||
event.type = MP_EVENT_MOUSE_BUTTON;
|
|
||||||
event.key.action = MP_KEY_RELEASE;
|
|
||||||
event.key.code = [nsEvent buttonNumber];
|
|
||||||
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.mouse.buttons[event.key.code], false);
|
|
||||||
|
|
||||||
mp_queue_event(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDragged:(NSEvent*)nsEvent
|
- (void)mouseDragged:(NSEvent*)nsEvent
|
||||||
|
@ -946,10 +915,10 @@ static void mp_update_key_mods(mp_key_mods mods)
|
||||||
mp_queue_event(&event);
|
mp_queue_event(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- (void)keyDown:(NSEvent*)nsEvent
|
- (void)keyDown:(NSEvent*)nsEvent
|
||||||
{
|
{
|
||||||
|
mp_key_action action = [nsEvent isARepeat] ? MP_KEY_REPEAT : MP_KEY_PRESS;
|
||||||
|
|
||||||
mp_event event = {};
|
mp_event event = {};
|
||||||
event.window = mp_window_handle_from_ptr(window);
|
event.window = mp_window_handle_from_ptr(window);
|
||||||
event.type = MP_EVENT_KEYBOARD_KEY;
|
event.type = MP_EVENT_KEYBOARD_KEY;
|
||||||
|
@ -961,7 +930,7 @@ static void mp_update_key_mods(mp_key_mods mods)
|
||||||
event.key.labelLen = label.len;
|
event.key.labelLen = label.len;
|
||||||
memcpy(event.key.label, label.ptr, label.len);
|
memcpy(event.key.label, label.ptr, label.len);
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], true);
|
mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], MP_KEY_PRESS);
|
||||||
|
|
||||||
mp_queue_event(&event);
|
mp_queue_event(&event);
|
||||||
|
|
||||||
|
@ -977,7 +946,7 @@ static void mp_update_key_mods(mp_key_mods mods)
|
||||||
event.key.code = mp_convert_osx_key([nsEvent keyCode]);
|
event.key.code = mp_convert_osx_key([nsEvent keyCode]);
|
||||||
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
||||||
|
|
||||||
mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], false);
|
mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], MP_KEY_RELEASE);
|
||||||
|
|
||||||
mp_queue_event(&event);
|
mp_queue_event(&event);
|
||||||
}
|
}
|
||||||
|
@ -1092,7 +1061,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
{
|
{
|
||||||
NSString* characters;
|
NSString* characters;
|
||||||
NSEvent* nsEvent = [NSApp currentEvent];
|
NSEvent* nsEvent = [NSApp currentEvent];
|
||||||
mp_key_mods mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
mp_keymod_flags mods = mp_convert_osx_mods([nsEvent modifierFlags]);
|
||||||
|
|
||||||
if([string isKindOfClass:[NSAttributedString class]])
|
if([string isKindOfClass:[NSAttributedString class]])
|
||||||
{
|
{
|
||||||
|
@ -2265,7 +2234,6 @@ int mp_alert_popup(const char* title,
|
||||||
|
|
||||||
[alert setAlertStyle:NSAlertStyleWarning];
|
[alert setAlertStyle:NSAlertStyleWarning];
|
||||||
int result = count - ([alert runModal]-NSAlertFirstButtonReturn) - 1;
|
int result = count - ([alert runModal]-NSAlertFirstButtonReturn) - 1;
|
||||||
printf("result = %i, NSAlertFirstButtonReturn = %li\n", result, (long)NSAlertFirstButtonReturn);
|
|
||||||
[keyWindow makeKeyWindow];
|
[keyWindow makeKeyWindow];
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
44
src/ui.c
44
src/ui.c
|
@ -450,7 +450,7 @@ vec2 ui_mouse_position(void)
|
||||||
{
|
{
|
||||||
ui_context* ui = ui_get_context();
|
ui_context* ui = ui_get_context();
|
||||||
|
|
||||||
vec2 mousePos = mp_input_mouse_position();
|
vec2 mousePos = mp_mouse_position();
|
||||||
mousePos.y = ui->height - mousePos.y;
|
mousePos.y = ui->height - mousePos.y;
|
||||||
return(mousePos);
|
return(mousePos);
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ vec2 ui_mouse_position(void)
|
||||||
vec2 ui_mouse_delta(void)
|
vec2 ui_mouse_delta(void)
|
||||||
{
|
{
|
||||||
ui_context* ui = ui_get_context();
|
ui_context* ui = ui_get_context();
|
||||||
vec2 delta = mp_input_mouse_delta();
|
vec2 delta = mp_mouse_delta();
|
||||||
delta.y *= -1.;
|
delta.y *= -1.;
|
||||||
return(delta);
|
return(delta);
|
||||||
}
|
}
|
||||||
|
@ -466,7 +466,7 @@ vec2 ui_mouse_delta(void)
|
||||||
vec2 ui_mouse_wheel(void)
|
vec2 ui_mouse_wheel(void)
|
||||||
{
|
{
|
||||||
ui_context* ui = ui_get_context();
|
ui_context* ui = ui_get_context();
|
||||||
vec2 delta = mp_input_mouse_wheel();
|
vec2 delta = mp_mouse_wheel();
|
||||||
delta.y *= -1.;
|
delta.y *= -1.;
|
||||||
return(delta);
|
return(delta);
|
||||||
}
|
}
|
||||||
|
@ -642,30 +642,25 @@ ui_sig ui_box_sig(ui_box* box)
|
||||||
{
|
{
|
||||||
if(sig.hovering)
|
if(sig.hovering)
|
||||||
{
|
{
|
||||||
if(mp_input_mouse_clicked(MP_MOUSE_LEFT))
|
sig.pressed = mp_mouse_pressed(MP_MOUSE_LEFT);
|
||||||
{
|
|
||||||
printf("clicked while hovering!\n");
|
|
||||||
}
|
|
||||||
sig.pressed = mp_input_mouse_pressed(MP_MOUSE_LEFT);
|
|
||||||
if(sig.pressed)
|
if(sig.pressed)
|
||||||
{
|
{
|
||||||
box->dragging = true;
|
box->dragging = true;
|
||||||
}
|
}
|
||||||
|
sig.doubleClicked = mp_mouse_double_clicked(MP_MOUSE_LEFT);
|
||||||
sig.clicked = mp_input_mouse_clicked(MP_MOUSE_LEFT);
|
sig.rightPressed = mp_mouse_pressed(MP_MOUSE_RIGHT);
|
||||||
sig.doubleClicked = mp_input_mouse_double_clicked(MP_MOUSE_LEFT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sig.released = mp_input_mouse_released(MP_MOUSE_LEFT);
|
sig.released = mp_mouse_released(MP_MOUSE_LEFT);
|
||||||
if(sig.released)
|
if(sig.released)
|
||||||
{
|
{
|
||||||
if(box->dragging && sig.hovering)
|
if(box->dragging && sig.hovering)
|
||||||
{
|
{
|
||||||
sig.triggered = true;
|
sig.clicked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mp_input_mouse_down(MP_MOUSE_LEFT))
|
if(!mp_mouse_down(MP_MOUSE_LEFT))
|
||||||
{
|
{
|
||||||
box->dragging = false;
|
box->dragging = false;
|
||||||
}
|
}
|
||||||
|
@ -1589,7 +1584,7 @@ void ui_menu_bar_begin(const char* name)
|
||||||
ui_push_size(UI_AXIS_Y, UI_SIZE_TEXT, 0, 0);
|
ui_push_size(UI_AXIS_Y, UI_SIZE_TEXT, 0, 0);
|
||||||
|
|
||||||
ui_sig sig = ui_box_sig(bar);
|
ui_sig sig = ui_box_sig(bar);
|
||||||
if(!sig.hovering && mp_input_mouse_released(MP_MOUSE_LEFT))
|
if(!sig.hovering && mp_mouse_released(MP_MOUSE_LEFT))
|
||||||
{
|
{
|
||||||
ui_box_deactivate(bar);
|
ui_box_deactivate(bar);
|
||||||
}
|
}
|
||||||
|
@ -1725,11 +1720,8 @@ void ui_edit_copy_selection_to_clipboard(ui_context* ui, str32 codepoints)
|
||||||
u32 start = minimum(ui->editCursor, ui->editMark);
|
u32 start = minimum(ui->editCursor, ui->editMark);
|
||||||
u32 end = maximum(ui->editCursor, ui->editMark);
|
u32 end = maximum(ui->editCursor, ui->editMark);
|
||||||
str32 selection = str32_slice(codepoints, start, end);
|
str32 selection = str32_slice(codepoints, start, end);
|
||||||
|
|
||||||
str8 string = utf8_push_from_codepoints(&ui->frameArena, selection);
|
str8 string = utf8_push_from_codepoints(&ui->frameArena, selection);
|
||||||
|
|
||||||
printf("copying '%.*s' to clipboard\n", (int)string.len, string.ptr);
|
|
||||||
|
|
||||||
mp_clipboard_clear();
|
mp_clipboard_clear();
|
||||||
mp_clipboard_set_string(string);
|
mp_clipboard_set_string(string);
|
||||||
}
|
}
|
||||||
|
@ -1737,9 +1729,6 @@ void ui_edit_copy_selection_to_clipboard(ui_context* ui, str32 codepoints)
|
||||||
str32 ui_edit_replace_selection_with_clipboard(ui_context* ui, str32 codepoints)
|
str32 ui_edit_replace_selection_with_clipboard(ui_context* ui, str32 codepoints)
|
||||||
{
|
{
|
||||||
str8 string = mp_clipboard_get_string(&ui->frameArena);
|
str8 string = mp_clipboard_get_string(&ui->frameArena);
|
||||||
|
|
||||||
printf("pasting '%.*s' from clipboard\n", (int)string.len, string.ptr);
|
|
||||||
|
|
||||||
str32 input = utf8_push_to_codepoints(&ui->frameArena, string);
|
str32 input = utf8_push_to_codepoints(&ui->frameArena, string);
|
||||||
str32 result = ui_edit_replace_selection_with_codepoints(ui, codepoints, input);
|
str32 result = ui_edit_replace_selection_with_codepoints(ui, codepoints, input);
|
||||||
return(result);
|
return(result);
|
||||||
|
@ -1764,7 +1753,7 @@ typedef enum {
|
||||||
typedef struct ui_edit_command
|
typedef struct ui_edit_command
|
||||||
{
|
{
|
||||||
mp_key_code key;
|
mp_key_code key;
|
||||||
mp_key_mods mods;
|
mp_keymod_flags mods;
|
||||||
|
|
||||||
ui_edit_op operation;
|
ui_edit_op operation;
|
||||||
ui_edit_move move;
|
ui_edit_move move;
|
||||||
|
@ -2186,18 +2175,13 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text)
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE handle shortcuts
|
//NOTE handle shortcuts
|
||||||
mp_key_mods mods = mp_input_key_mods();
|
mp_keymod_flags mods = mp_key_mods();
|
||||||
|
|
||||||
for(int i=0; i<UI_EDIT_COMMAND_COUNT; i++)
|
for(int i=0; i<UI_EDIT_COMMAND_COUNT; i++)
|
||||||
{
|
{
|
||||||
const ui_edit_command* command = &(UI_EDIT_COMMANDS[i]);
|
const ui_edit_command* command = &(UI_EDIT_COMMANDS[i]);
|
||||||
|
|
||||||
if(mp_input_key_pressed(MP_KEY_C))
|
if(mp_key_pressed(command->key) && mods == command->mods)
|
||||||
{
|
|
||||||
printf("press C!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mp_input_key_pressed(command->key) && mods == command->mods)
|
|
||||||
{
|
{
|
||||||
codepoints = ui_edit_perform_operation(ui, command->operation, command->move, command->direction, codepoints);
|
codepoints = ui_edit_perform_operation(ui, command->operation, command->move, command->direction, codepoints);
|
||||||
break;
|
break;
|
||||||
|
@ -2205,7 +2189,7 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text)
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE(martin): text box focus shortcuts
|
//NOTE(martin): text box focus shortcuts
|
||||||
if(mp_input_key_pressed(MP_KEY_ENTER))
|
if(mp_key_pressed(MP_KEY_ENTER))
|
||||||
{
|
{
|
||||||
//TODO(martin): extract in gui_edit_complete() (and use below)
|
//TODO(martin): extract in gui_edit_complete() (and use below)
|
||||||
ui_box_deactivate(frame);
|
ui_box_deactivate(frame);
|
||||||
|
|
4
src/ui.h
4
src/ui.h
|
@ -123,10 +123,10 @@ typedef struct ui_sig
|
||||||
|
|
||||||
bool pressed;
|
bool pressed;
|
||||||
bool released;
|
bool released;
|
||||||
bool triggered;
|
|
||||||
bool clicked;
|
bool clicked;
|
||||||
bool doubleClicked;
|
bool doubleClicked;
|
||||||
bool rightClicked;
|
bool rightPressed;
|
||||||
|
|
||||||
bool dragging;
|
bool dragging;
|
||||||
bool hovering;
|
bool hovering;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue