-
Notifications
You must be signed in to change notification settings - Fork 793
Open
Description
hscroll_label的bug
hscroll_label在滚动过程中,设置空字符串,后台timer没有移除,仍然在运行占用CPU,对于嵌入式设备来说,hlab一直在运行timer刷新,挺占用CPU的,patch如下:
diff --git a/src/ext_widgets/scroll_label/hscroll_label.c b/src/ext_widgets/scroll_label/hscroll_label.c
index 39ca077..7be3ec4 100644
--- a/src/ext_widgets/scroll_label/hscroll_label.c
+++ b/src/ext_widgets/scroll_label/hscroll_label.c
@@ -310,6 +310,9 @@ static ret_t hscroll_label_set_prop(widget_t* widget, const char* name, const va
if (hscroll_label->timer_id != TK_INVALID_ID) {
hscroll_label->elapsed = 0;
}
+ if (tk_strlen(value_str(v)) <= 0) {
+ hscroll_label_stop(widget);
+ }
return RET_NOT_FOUND;
} else if (tk_str_eq(name, HSCROLL_LABEL_PROP_STOP_AT_BEGIN)) {
return hscroll_label_set_stop_at_begin(widget, value_bool(v));
slide_view的bug
slide_view存在两个bug:
- 一是在开启auto_play的情况下,正常会自动翻页到第二页—第三页— ... —第一页,但是slide_view里面只添加一个子控件,也会翻页到第二页,但是第二页会显示空白,然后再回到第一页,这是有问题的。
- 二是slide_view在用手指触摸左右翻页的过程中,如果此时有销毁里面的子控件,会导致野指针死机,比如你可以直接widget_destroy_children(slide_view)试试,左右翻页的操作可以这样:目前处于第一页,你可以向第二页翻页,但是不要松手,此时屏幕上显示第一页在左半边,右半边会显示第二页,这样方便观察,当执行widget_destroy_children之后,我这边是有重新add进去几页,会发现屏幕出现空白页,此时松开手指让slide_view翻到第二页(其实是显示的空白页了),这种情况下是有野指针会导致死机的。
- 修改点说明,针对第一个bug,slide_view_on_timer_next里面判断next指针是否为NULL,因为slide_view_get_next里面其实是没有判断nr==1的情况,导致如果只有一页的时候会返回NULL,NULL的时候是不需要进行翻页的。针对第二个bug,添加on_remove_child指针,移除child的时候要把prev和next指针置为NULL,否则这两个指针可能成为野指针,此时slide_view_on_scroll_done里面的widget_index_of会返回-1,所以active变量需要改为int32_t,并且重新设置一下active = active < 0 ? 0 : active; 实际上野指针死机也是widget_index_of这里,因为next和prev野指针了。
- patch如下:
diff --git a/src/ext_widgets/slide_view/slide_view.c b/src/ext_widgets/slide_view/slide_view.c
index ecfdd13..f54e8db 100644
--- a/src/ext_widgets/slide_view/slide_view.c
+++ b/src/ext_widgets/slide_view/slide_view.c
@@ -140,6 +140,18 @@ static ret_t slide_view_on_paint_self(widget_t* widget, canvas_t* c) {
return RET_OK;
}
+static ret_t slide_view_on_remove_child(widget_t* widget, widget_t* child) {
+ slide_view_t* slide_view = SLIDE_VIEW(widget);
+ return_value_if_fail(slide_view != NULL && widget != NULL && child != NULL, RET_BAD_PARAMS);
+ if (slide_view->next == child) {
+ slide_view->next = NULL;
+ } else if (slide_view->prev == child) {
+ slide_view->prev = NULL;
+ }
+
+ return RET_FAIL;
+}
+
static ret_t slide_view_on_pointer_down(slide_view_t* slide_view, pointer_event_t* e) {
velocity_t* v = &(slide_view->velocity);
@@ -152,13 +164,14 @@ static ret_t slide_view_on_pointer_down(slide_view_t* slide_view, pointer_event_
}
static ret_t slide_view_on_scroll_done(void* ctx, event_t* e) {
- uint32_t active;
+ int32_t active;
widget_t* widget = WIDGET(ctx);
slide_view_t* slide_view = SLIDE_VIEW(ctx);
return_value_if_fail(widget != NULL && slide_view != NULL, RET_BAD_PARAMS);
if (slide_view->xoffset < 0 || slide_view->yoffset < 0) {
active = widget_index_of(slide_view->prev);
+ active = active < 0 ? 0 : active; /* Maybe children are destroyed before, slide_view->prev and next had been already set NULL */
if (slide_view->check_last) {
active = active == slide_view->last_active ? active : slide_view->last_active;
}
@@ -170,6 +183,7 @@ static ret_t slide_view_on_scroll_done(void* ctx, event_t* e) {
}
} else if (slide_view->xoffset > 0 || slide_view->yoffset > 0) {
active = widget_index_of(slide_view->next);
+ active = active < 0 ? 0 : active;
if (slide_view->check_last) {
active = active == slide_view->last_active ? active : slide_view->last_active;
}
@@ -808,6 +822,7 @@ TK_DECL_VTABLE(slide_view) = {.size = sizeof(slide_view_t),
.find_target = slide_view_find_target,
.on_paint_children = slide_view_on_paint_children,
.on_paint_self = slide_view_on_paint_self,
+ .on_remove_child = slide_view_on_remove_child,
.on_destroy = slide_view_on_destroy};
static ret_t slide_view_on_idle_init_save_target(const idle_info_t* idle) {
@@ -1067,7 +1082,9 @@ static ret_t slide_view_on_timer_next(const timer_info_t* timer) {
}
slide_view->next = slide_view_get_next(slide_view);
- slide_view_animate_to(slide_view, 0, 0, xoffset_end, yoffset_end);
+ if (slide_view->next != NULL) {
+ slide_view_animate_to(slide_view, 0, 0, xoffset_end, yoffset_end);
+ }
return RET_REPEAT;
}
edit的优化
- 我一直都想把edit改成手指抬起后再弹出键盘,目前手指按下就会弹出键盘,体验上会有很大问题,比如一个list_view里面有好几行edit,根本不能滑动了,因为点击到edit就直接弹出键盘了,只能在edit区域之外触摸滑动,但用户怎么知道,这在交互上非常糟糕。所以我的修改点如下,增加手指抬起后的键盘弹出属性,以及该属性下需要禁止聚焦后自动弹出键盘(当然也可以内部直接强制):
diff --git a/src/widgets/edit.c b/src/widgets/edit.c
index 166a091..5514c64 100644
--- a/src/widgets/edit.c
+++ b/src/widgets/edit.c
@@ -831,12 +831,14 @@ ret_t edit_on_event(widget_t* widget, event_t* e) {
widget_grab(widget->parent, widget);
}
- if (widget->target == NULL && !edit->readonly) {
- input_method_request(input_method(), widget);
+ if (!edit->open_im_when_pointer_up || input_method()->keyboard != NULL) {
+ if (widget->target == NULL && !edit->readonly) {
+ input_method_request(input_method(), widget);
+ }
+ edit_start_update_caret(edit);
}
edit_update_status(widget);
widget_invalidate(widget, NULL);
- edit_start_update_caret(edit);
break;
}
case EVT_POINTER_DOWN_ABORT: {
@@ -848,13 +850,19 @@ ret_t edit_on_event(widget_t* widget, event_t* e) {
pointer_event_t evt = *(pointer_event_t*)e;
if (widget->parent && widget->parent->grab_widget == widget) {
text_edit_drag(edit->model, evt.x, evt.y);
- ret = RET_STOP;
+ //ret = RET_STOP;
}
widget_invalidate(widget, NULL);
break;
}
case EVT_POINTER_UP: {
+ if (edit->open_im_when_pointer_up && input_method()->keyboard == NULL && widget->parent && widget->parent->grab_widget == widget) {
+ if (widget->target == NULL && !edit->readonly) {
+ input_method_request(input_method(), widget);
+ }
+ edit_start_update_caret(edit);
+ }
widget_ungrab(widget->parent, widget);
widget_invalidate(widget, NULL);
break;
@@ -1388,6 +1396,9 @@ ret_t edit_get_prop(widget_t* widget, const char* name, value_t* v) {
} else if (tk_str_eq(name, WIDGET_PROP_CLOSE_IM_WHEN_BLURED)) {
value_set_bool(v, edit->close_im_when_blured);
return RET_OK;
+ } else if (tk_str_eq(name, EDIT_PROP_OPEN_IM_WHEN_POINTER_UP)) {
+ value_set_bool(v, edit->open_im_when_pointer_up);
+ return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_LEFT_MARGIN)) {
uint32_t margin = 0;
if (widget->astyle != NULL) {
@@ -1596,6 +1607,9 @@ ret_t edit_set_prop(widget_t* widget, const char* name, const value_t* v) {
} else if (tk_str_eq(name, WIDGET_PROP_CLOSE_IM_WHEN_BLURED)) {
edit->close_im_when_blured = value_bool(v);
return RET_OK;
+ } else if (tk_str_eq(name, EDIT_PROP_OPEN_IM_WHEN_POINTER_UP)) {
+ edit->open_im_when_pointer_up = value_bool(v);
+ return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_MARGIN)) {
edit->margin = value_int(v);
edit_reset_layout(widget);
@@ -2122,6 +2136,7 @@ static ret_t edit_init(widget_t* widget) {
edit->close_im_when_blured = TRUE;
edit->open_im_when_focused = TRUE;
edit->focus_next_when_enter = FALSE;
+ edit->open_im_when_pointer_up = FALSE;
edit_set_text_limit(widget, 0, 1024);
edit_update_status(widget);
diff --git a/src/widgets/edit.h b/src/widgets/edit.h
index 29e80f8..ac23364 100644
--- a/src/widgets/edit.h
+++ b/src/widgets/edit.h
@@ -228,7 +228,13 @@ typedef struct _edit_t {
* 输入回车后是否跳到下一个控件中。
*
*/
- bool_t focus_next_when_enter;
+ bool_t focus_next_when_enter;^M
+ /**^M
+ * @property {bool_t} open_im_when_pointer_up^M
+ * @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]^M
+ * 手指抬起后再时打开输入法。^M
+ */^M
+ bool_t open_im_when_pointer_up;
/*private*/
uint8_t margin;
uint8_t top_margin;
@@ -733,7 +739,8 @@ ret_t edit_pre_delete_with_sep(widget_t* widget, delete_type_t delete_type, char
#define STR_EDIT_DEC_NAME "dec"
#define STR_EDIT_CLEAR_NAME "clear"
#define STR_EDIT_VISIBLE_NAME "visible"
-#define EDIT_PROP_FOCUS_NEXT_WHEN_ENTER "focus_next_when_enter"
+#define EDIT_PROP_FOCUS_NEXT_WHEN_ENTER "focus_next_when_enter"^M
+#define EDIT_PROP_OPEN_IM_WHEN_POINTER_UP "open_im_when_pointer_up"
#define TK_EDIT_PROPS \
WIDGET_PROP_MIN, WIDGET_PROP_MAX, WIDGET_PROP_STEP, WIDGET_PROP_INPUT_TYPE, \
- 改完之后使用上只有一个问题,不好触摸选中edit内容了,因为EVT_POINTER_MOVE事件中注释掉了ret = RET_STOP,但我这边实际上不需要这种功能,无所谓。如果需要这个功能的话,我觉得是要能判断出手指滑动过程中在这个edit范围内就仍然返回RET_STOP,否则就不返回RET_STOP,并且要ungrab控件,类似这样你们可以优化一下。
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels