update state

This commit is contained in:
Siyuan Miao 2025-09-25 15:08:43 +00:00
parent 76c4144565
commit 70db172287
10 changed files with 180 additions and 55 deletions

View File

@ -38,17 +38,17 @@ func updateDisplay() {
if usbState == "configured" {
nativeInstance.UpdateLabelIfChanged("usb_status_label", "Connected")
_, _ = nativeInstance.UIObjSetState("usb_status", "LV_STATE_DEFAULT")
_, _ = nativeInstance.UIObjAddState("usb_status_label", "LV_STATE_CHECKED")
} else {
nativeInstance.UpdateLabelIfChanged("usb_status_label", "Disconnected")
_, _ = nativeInstance.UIObjSetState("usb_status", "LV_STATE_DISABLED")
_, _ = nativeInstance.UIObjClearState("usb_status_label", "LV_STATE_CHECKED")
}
if lastVideoState.Ready {
nativeInstance.UpdateLabelIfChanged("hdmi_status_label", "Connected")
_, _ = nativeInstance.UIObjSetState("hdmi_status", "LV_STATE_DEFAULT")
_, _ = nativeInstance.UIObjAddState("hdmi_status_label", "LV_STATE_CHECKED")
} else {
nativeInstance.UpdateLabelIfChanged("hdmi_status_label", "Disconnected")
_, _ = nativeInstance.UIObjSetState("hdmi_status", "LV_STATE_DISABLED")
_, _ = nativeInstance.UIObjClearState("hdmi_status_label", "LV_STATE_CHECKED")
}
nativeInstance.UpdateLabelIfChanged("cloud_status_label", fmt.Sprintf("%d active", actionSessions))

View File

@ -247,36 +247,55 @@ void jetkvm_ui_set_image(const char *obj_name, const char *image_name) {
lv_img_set_src(obj, image_name);
}
void jetkvm_ui_set_state(const char *obj_name, const char *state_name) {
lv_state_t str_to_lv_state(const char *state_name) {
if (strcmp(state_name, "LV_STATE_USER_1") == 0) {
return LV_STATE_USER_1;
}
else if (strcmp(state_name, "LV_STATE_USER_2") == 0) {
return LV_STATE_USER_2;
}
else if (strcmp(state_name, "LV_STATE_USER_3") == 0) {
return LV_STATE_USER_3;
}
else if (strcmp(state_name, "LV_STATE_USER_4") == 0) {
return LV_STATE_USER_4;
}
else if (strcmp(state_name, "LV_STATE_DISABLED") == 0) {
return LV_STATE_DISABLED;
}
else if (strcmp(state_name, "LV_STATE_DEFAULT") == 0) {
return LV_STATE_DEFAULT;
}
else if (strcmp(state_name, "LV_STATE_CHECKED") == 0) {
return LV_STATE_CHECKED;
}
else if (strcmp(state_name, "LV_STATE_FOCUSED") == 0) {
return LV_STATE_FOCUSED;
}
return LV_STATE_DEFAULT;
}
void jetkvm_ui_add_state(const char *obj_name, const char *state_name) {
lv_obj_t *obj = ui_get_obj(obj_name);
if (obj == NULL) {
return;
}
lv_obj_add_state(obj, LV_STATE_USER_1);
lv_state_t state_val = LV_STATE_DEFAULT;
if (strcmp(state_name, "LV_STATE_USER_1") == 0)
{
state_val = LV_STATE_USER_1;
}
else if (strcmp(state_name, "LV_STATE_USER_2") == 0)
{
state_val = LV_STATE_USER_2;
}
else if (strcmp(state_name, "LV_STATE_USER_3") == 0)
{
state_val = LV_STATE_USER_3;
}
else if (strcmp(state_name, "LV_STATE_USER_4") == 0)
{
state_val = LV_STATE_USER_4;
}
else if (strcmp(state_name, "LV_STATE_DISABLED") == 0)
{
state_val = LV_STATE_DISABLED;
}
// TODO: use LV_STATE_USER_* once eez supports it
lv_obj_clear_state(obj, LV_STATE_USER_1 | LV_STATE_USER_2 | LV_STATE_USER_3 | LV_STATE_USER_4 | LV_STATE_DISABLED);
lv_state_t state_val = str_to_lv_state(state_name);
lv_obj_add_state(obj, state_val);
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
}
void jetkvm_ui_clear_state(const char *obj_name, const char *state_name) {
lv_obj_t *obj = ui_get_obj(obj_name);
if (obj == NULL) {
return;
}
lv_state_t state_val = str_to_lv_state(state_name);
lv_obj_clear_state(obj, state_val);
log_info("cleared state %s from object %s: %d", state_name, obj_name, state_val);
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
}
int jetkvm_ui_add_flag(const char *obj_name, const char *flag_name) {

View File

@ -39,7 +39,8 @@ const char *jetkvm_ui_get_current_screen();
void jetkvm_ui_load_screen(const char *obj_name);
int jetkvm_ui_set_text(const char *obj_name, const char *text);
void jetkvm_ui_set_image(const char *obj_name, const char *image_name);
void jetkvm_ui_set_state(const char *obj_name, const char *state_name);
void jetkvm_ui_add_state(const char *obj_name, const char *state_name);
void jetkvm_ui_clear_state(const char *obj_name, const char *state_name);
void jetkvm_ui_fade_in(const char *obj_name, u_int32_t duration);
void jetkvm_ui_fade_out(const char *obj_name, u_int32_t duration);
void jetkvm_ui_set_opacity(const char *obj_name, u_int8_t opacity);

View File

@ -4,6 +4,7 @@ package native
import (
"fmt"
"sync"
"unsafe"
"github.com/rs/zerolog"
@ -45,6 +46,8 @@ static inline void jetkvm_cgo_setup_rpc_handler() {
*/
import "C"
var cgoLock sync.Mutex
//export jetkvm_go_video_state_handler
func jetkvm_go_video_state_handler(state *C.jetkvm_video_state_t) {
videoState := VideoState{
@ -100,6 +103,9 @@ func uiEventCodeToName(code int) string {
}
func setUpNativeHandlers() {
cgoLock.Lock()
defer cgoLock.Unlock()
C.jetkvm_cgo_setup_log_handler()
C.jetkvm_cgo_setup_video_state_handler()
C.jetkvm_cgo_setup_video_handler()
@ -108,6 +114,9 @@ func setUpNativeHandlers() {
}
func uiInit(rotation uint16) {
cgoLock.Lock()
defer cgoLock.Unlock()
cRotation := C.u_int16_t(rotation)
defer C.free(unsafe.Pointer(&cRotation))
@ -115,10 +124,16 @@ func uiInit(rotation uint16) {
}
func uiTick() {
cgoLock.Lock()
defer cgoLock.Unlock()
C.jetkvm_ui_tick()
}
func videoInit() error {
cgoLock.Lock()
defer cgoLock.Unlock()
ret := C.jetkvm_video_init()
if ret != 0 {
return fmt.Errorf("failed to initialize video: %d", ret)
@ -127,18 +142,30 @@ func videoInit() error {
}
func videoShutdown() {
cgoLock.Lock()
defer cgoLock.Unlock()
C.jetkvm_video_shutdown()
}
func videoStart() {
cgoLock.Lock()
defer cgoLock.Unlock()
C.jetkvm_video_start()
}
func videoStop() {
cgoLock.Lock()
defer cgoLock.Unlock()
C.jetkvm_video_stop()
}
func uiSetVar(name string, value string) {
cgoLock.Lock()
defer cgoLock.Unlock()
nameCStr := C.CString(name)
defer C.free(unsafe.Pointer(nameCStr))
@ -149,6 +176,9 @@ func uiSetVar(name string, value string) {
}
func uiGetVar(name string) string {
cgoLock.Lock()
defer cgoLock.Unlock()
nameCStr := C.CString(name)
defer C.free(unsafe.Pointer(nameCStr))
@ -156,31 +186,58 @@ func uiGetVar(name string) string {
}
func uiSwitchToScreen(screen string) {
cgoLock.Lock()
defer cgoLock.Unlock()
screenCStr := C.CString(screen)
defer C.free(unsafe.Pointer(screenCStr))
C.jetkvm_ui_load_screen(screenCStr)
}
func uiGetCurrentScreen() string {
cgoLock.Lock()
defer cgoLock.Unlock()
screenCStr := C.jetkvm_ui_get_current_screen()
return C.GoString(screenCStr)
}
func uiObjSetState(objName string, state string) (bool, error) {
func uiObjAddState(objName string, state string) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
stateCStr := C.CString(state)
defer C.free(unsafe.Pointer(stateCStr))
C.jetkvm_ui_set_state(objNameCStr, stateCStr)
C.jetkvm_ui_add_state(objNameCStr, stateCStr)
return true, nil
}
func uiObjClearState(objName string, state string) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
stateCStr := C.CString(state)
defer C.free(unsafe.Pointer(stateCStr))
C.jetkvm_ui_clear_state(objNameCStr, stateCStr)
return true, nil
}
func uiGetLVGLVersion() string {
cgoLock.Lock()
defer cgoLock.Unlock()
return C.GoString(C.jetkvm_ui_get_lvgl_version())
}
// TODO: use Enum instead of string but it's not a hot path and performance is not a concern now
func uiObjAddFlag(objName string, flag string) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
flagCStr := C.CString(flag)
@ -190,6 +247,9 @@ func uiObjAddFlag(objName string, flag string) (bool, error) {
}
func uiObjClearFlag(objName string, flag string) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
flagCStr := C.CString(flag)
@ -207,6 +267,9 @@ func uiObjShow(objName string) (bool, error) {
}
func uiObjSetOpacity(objName string, opacity int) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
@ -215,6 +278,9 @@ func uiObjSetOpacity(objName string, opacity int) (bool, error) {
}
func uiObjFadeIn(objName string, duration uint32) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
@ -224,6 +290,9 @@ func uiObjFadeIn(objName string, duration uint32) (bool, error) {
}
func uiObjFadeOut(objName string, duration uint32) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
@ -233,6 +302,9 @@ func uiObjFadeOut(objName string, duration uint32) (bool, error) {
}
func uiLabelSetText(objName string, text string) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
@ -247,6 +319,9 @@ func uiLabelSetText(objName string, text string) (bool, error) {
}
func uiImgSetSrc(objName string, src string) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
objNameCStr := C.CString(objName)
defer C.free(unsafe.Pointer(objNameCStr))
@ -259,6 +334,9 @@ func uiImgSetSrc(objName string, src string) (bool, error) {
}
func uiDispSetRotation(rotation uint16) (bool, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
nativeLogger.Info().Uint16("rotation", rotation).Msg("setting rotation")
cRotation := C.u_int16_t(rotation)
@ -269,21 +347,33 @@ func uiDispSetRotation(rotation uint16) (bool, error) {
}
func videoGetStreamQualityFactor() (float64, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
factor := C.jetkvm_video_get_quality_factor()
return float64(factor), nil
}
func videoSetStreamQualityFactor(factor float64) error {
cgoLock.Lock()
defer cgoLock.Unlock()
C.jetkvm_video_set_quality_factor(C.float(factor))
return nil
}
func videoGetEDID() (string, error) {
cgoLock.Lock()
defer cgoLock.Unlock()
edidCStr := C.jetkvm_video_get_edid_hex()
return C.GoString(edidCStr), nil
}
func videoSetEDID(edid string) error {
cgoLock.Lock()
defer cgoLock.Unlock()
edidCStr := C.CString(edid)
defer C.free(unsafe.Pointer(edidCStr))
C.jetkvm_video_set_edid(edidCStr)

View File

@ -28,7 +28,12 @@ func uiGetCurrentScreen() string {
return ""
}
func uiObjSetState(objName string, state string) (bool, error) {
func uiObjAddState(objName string, state string) (bool, error) {
panicPlatformNotSupported()
return false, nil
}
func uiObjClearState(objName string, state string) (bool, error) {
panicPlatformNotSupported()
return false, nil
}

View File

@ -47,9 +47,14 @@ func (n *Native) UIGetVar(name string) string {
return uiGetVar(name)
}
// UIObjSetState clears the state then adds the new state
func (n *Native) UIObjSetState(objName string, state string) (bool, error) {
return uiObjSetState(objName, state)
// UIObjAddState adds the state to the object
func (n *Native) UIObjAddState(objName string, state string) (bool, error) {
return uiObjAddState(objName, state)
}
// UIObjClearState clears the state from the object
func (n *Native) UIObjClearState(objName string, state string) (bool, error) {
return uiObjClearState(objName, state)
}
// UIObjAddFlag adds the flag to the object

View File

@ -1577,7 +1577,7 @@
"type": "LVGLLabelWidget",
"left": 0,
"top": 0,
"width": 81,
"width": 68,
"height": 17,
"customInputs": [],
"customOutputs": [],
@ -1595,9 +1595,10 @@
"widthUnit": "content",
"heightUnit": "content",
"children": [],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE|CHECKABLE",
"hiddenFlagType": "literal",
"clickableFlagType": "literal",
"checkedState": false,
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
@ -1607,16 +1608,16 @@
"definition": {
"MAIN": {
"DEFAULT": {
"text_color": "22C55E"
},
"DISABLED": {
"text_color": "808080"
},
"CHECKED": {
"text_color": "22C55E"
}
}
}
},
"groupIndex": 0,
"text": "Connected",
"text": "Unknown",
"textType": "literal",
"longMode": "WRAP",
"recolor": false
@ -1795,7 +1796,7 @@
"type": "LVGLLabelWidget",
"left": 0,
"top": 0,
"width": 100,
"width": 68,
"height": 17,
"customInputs": [],
"customOutputs": [],
@ -1813,11 +1814,12 @@
"widthUnit": "content",
"heightUnit": "content",
"children": [],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE|CHECKABLE",
"hiddenFlagType": "literal",
"clickableFlagType": "literal",
"checkedState": false,
"checkedStateType": "literal",
"disabledState": true,
"disabledState": false,
"disabledStateType": "literal",
"states": "",
"useStyle": "LabelFont16",
@ -1825,17 +1827,17 @@
"objID": "00742432-4b32-47f4-a4c5-5bc75f6b458d",
"definition": {
"MAIN": {
"DEFAULT": {
"CHECKED": {
"text_color": "22C55E"
},
"DISABLED": {
"DEFAULT": {
"text_color": "808080"
}
}
}
},
"groupIndex": 0,
"text": "Disconnected",
"text": "Unknown",
"textType": "literal",
"longMode": "WRAP",
"recolor": false

View File

@ -432,10 +432,11 @@ void create_screen_home_screen() {
objects.usb_status_label = obj;
lv_obj_set_pos(obj, LV_PCT(0), LV_PCT(0));
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE);
add_style_label_font16(obj);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff22c55e), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff808080), LV_PART_MAIN | LV_STATE_DISABLED);
lv_label_set_text(obj, "Connected");
lv_obj_set_style_text_color(obj, lv_color_hex(0xff808080), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff22c55e), LV_PART_MAIN | LV_STATE_CHECKED);
lv_label_set_text(obj, "Unknown");
}
}
}
@ -494,11 +495,11 @@ void create_screen_home_screen() {
objects.hdmi_status_label = obj;
lv_obj_set_pos(obj, LV_PCT(0), LV_PCT(0));
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_add_state(obj, LV_STATE_DISABLED);
lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE);
add_style_label_font16(obj);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff22c55e), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff808080), LV_PART_MAIN | LV_STATE_DISABLED);
lv_label_set_text(obj, "Disconnected");
lv_obj_set_style_text_color(obj, lv_color_hex(0xff22c55e), LV_PART_MAIN | LV_STATE_CHECKED);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff808080), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_label_set_text(obj, "Unknown");
}
}
}

Binary file not shown.

View File

@ -20,6 +20,7 @@ type Native struct {
onIndevEvent func(event string)
onRpcEvent func(event string)
videoLock sync.Mutex
screenLock sync.Mutex
}
type NativeOptions struct {
@ -73,6 +74,7 @@ func NewNative(opts NativeOptions) *Native {
onIndevEvent: opts.OnIndevEvent,
onRpcEvent: opts.OnRpcEvent,
videoLock: sync.Mutex{},
screenLock: sync.Mutex{},
}
}