support key long press event

This commit is contained in:
xianjimli 2020-09-15 09:23:54 +08:00
parent b7e3df2f7d
commit 99af46c719
6 changed files with 118 additions and 8 deletions

View File

@ -162,7 +162,7 @@ OS_PROJECTS=[]
OS_WHOLE_ARCHIVE=''
if OS_NAME == 'Darwin':
TOOLS_NAME = ''
OS_FLAGS='-g -Wall -fPIC '
OS_FLAGS='-g -Wall -fPIC -DWITHOUT_GLAD=1 '
OS_LIBS = ['stdc++', 'iconv','pthread', 'm', 'dl']
OS_LINKFLAGS='-framework IOKit -framework Cocoa -framework QuartzCore -framework OpenGL -weak_framework Metal -weak_framework MetalKit'
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -DHAS_SEM_OPEN '

View File

@ -1,4 +1,7 @@
# 最新动态
* 2020/09/15
* 支持长按键事件
* 2020/09/11
* 支持 packed 图片。
* 增加 [如何使用 packed 图](docs/how_to_use_packed_image.md)

View File

@ -121,6 +121,11 @@ typedef enum _event_type_t {
* (key_event_t)
*/
EVT_KEY_DOWN,
/**
* @const EVT_KEY_LONG_PRESS
* (key_event_t)
*/
EVT_KEY_LONG_PRESS,
/**
* @const EVT_KEY_DOWN_BEFORE_CHILDREN
* (key_event_t)

View File

@ -20,6 +20,7 @@
*/
#include "tkc/mem.h"
#include "tkc/time_now.h"
#include "base/keys.h"
#include "base/system_info.h"
#include "base/input_device_status.h"
@ -31,6 +32,89 @@ input_device_status_t* input_device_status_init(input_device_status_t* ids) {
return ids;
}
static key_pressed_info_t* input_device_status_find_press_info(input_device_status_t* ids,
uint32_t key) {
uint32_t i = 0;
for (i = 0; i < MAX_PRESSED_KEYS_NR; i++) {
key_pressed_info_t* iter = ids->pressed_info + i;
if (iter->key == key) {
return iter;
}
}
return NULL;
}
static bool_t input_device_status_has_pressed_key(input_device_status_t* ids) {
uint32_t i = 0;
for (i = 0; i < MAX_PRESSED_KEYS_NR; i++) {
key_pressed_info_t* iter = ids->pressed_info + i;
if (iter->key) {
return TRUE;
}
}
return FALSE;
}
static ret_t input_device_status_dispatch_long_press(input_device_status_t* ids) {
uint32_t i = 0;
key_event_t evt;
uint64_t now = time_now_ms();
widget_t* widget = ids->widget;
for (i = 0; i < MAX_PRESSED_KEYS_NR; i++) {
key_pressed_info_t* iter = ids->pressed_info + i;
if (iter->key && !iter->emitted) {
uint64_t t = now - iter->time;
if (t >= TK_LONG_PRESS_TIME) {
key_event_init(&evt, EVT_KEY_LONG_PRESS, widget, iter->key);
widget_on_keydown(widget, &evt);
log_debug("long press:%d\n", iter->key);
iter->emitted = TRUE;
}
}
}
return RET_OK;
}
static ret_t long_press_check_on_timer(const timer_info_t* info) {
input_device_status_t* ids = (input_device_status_t*)(info->ctx);
input_device_status_dispatch_long_press(ids);
if (input_device_status_has_pressed_key(ids)) {
return RET_REPEAT;
} else {
ids->long_press_check_timer = TK_INVALID_ID;
return RET_REMOVE;
}
}
static ret_t input_device_status_update_key_press_info(input_device_status_t* ids, uint32_t key,
bool_t down) {
key_pressed_info_t* info = input_device_status_find_press_info(ids, key);
if (down) {
if (info == NULL) {
info = input_device_status_find_press_info(ids, 0);
return_value_if_fail(info != NULL, RET_BAD_PARAMS);
info->key = key;
info->time = time_now_ms();
}
if (ids->long_press_check_timer == TK_INVALID_ID) {
ids->long_press_check_timer = timer_add(long_press_check_on_timer, ids, TK_LONG_PRESS_TIME);
}
} else {
return_value_if_fail(info != NULL, RET_BAD_PARAMS);
memset(info, 0x00, sizeof(key_pressed_info_t));
}
return RET_OK;
}
static ret_t input_device_status_update_key_status(input_device_status_t* ids, uint32_t key,
bool_t down) {
if (key == TK_KEY_LSHIFT) {
@ -62,6 +146,7 @@ static ret_t input_device_status_update_key_status(input_device_status_t* ids, u
ids->capslock = !(ids->capslock);
}
}
input_device_status_update_key_press_info(ids, key, down);
return RET_OK;
}
@ -148,6 +233,7 @@ static ret_t input_device_status_init_key_event(input_device_status_t* ids, key_
ret_t input_device_status_on_input_event(input_device_status_t* ids, widget_t* widget, event_t* e) {
return_value_if_fail(ids != NULL && e != NULL, RET_BAD_PARAMS);
ids->widget = widget;
switch (e->type) {
case EVT_POINTER_DOWN: {
pointer_event_t* evt = (pointer_event_t*)e;

View File

@ -26,6 +26,14 @@
BEGIN_C_DECLS
#define MAX_PRESSED_KEYS_NR 16
typedef struct _key_pressed_info_t {
uint32_t key;
uint32_t emitted;
uint64_t time;
} key_pressed_info_t;
/**
* @class input_device_status_t
* 使
@ -47,6 +55,9 @@ typedef struct _input_device_status_t {
xy_t last_x;
xy_t last_y;
bool_t pressed;
widget_t* widget;
uint32_t long_press_check_timer;
key_pressed_info_t pressed_info[MAX_PRESSED_KEYS_NR + 1];
} input_device_status_t;
/**

View File

@ -2198,6 +2198,7 @@ ret_t widget_on_keydown(widget_t* widget, key_event_t* e) {
widget_ref(widget);
widget_map_key(widget, e);
if (e->e.type == EVT_KEY_DOWN) {
ret = widget_on_keydown_impl(widget, e);
if (widget->feedback) {
ui_feedback_request(widget, (event_t*)e);
@ -2207,6 +2208,10 @@ ret_t widget_on_keydown(widget_t* widget, key_event_t* e) {
if (ret != RET_STOP) {
ret = widget_on_keydown_general(widget, e);
}
} else if (e->e.type == EVT_KEY_LONG_PRESS) {
return_if_equal(widget_on_keydown_children(widget, e), RET_STOP);
ret = widget_on_keydown_after_children(widget, e);
}
widget_unref(widget);
return ret;