// File: /workspace/github_c_makefile_star2_O2/OnionIoT[P]lv_example/lvgl/src/lv_objx/lv_sw.c
// Function: lv_sw_signal
static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param)
{
    lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);

    /*Save the current (old) value before slider signal modifies it. It will be required in the
     * later calculations*/
    int16_t old_val;
    if(sign == LV_SIGNAL_PRESSING)
        old_val = ext->slider.drag_value;
    else
        old_val = lv_slider_get_value(sw);

    /*Don't let the slider to call the action. Switch handles it differently*/
    lv_event_cb_t event_cb = sw->event_cb;
    sw->event_cb           = NULL;

    lv_res_t res;
    /* Include the ancient signal function */

    res = ancestor_signal(sw, sign, param);
    if(res != LV_RES_OK) return res;
    if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);

    sw->event_cb = event_cb;

    if(sign == LV_SIGNAL_CLEANUP) {
        /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
    } else if(sign == LV_SIGNAL_PRESSED) {

        /*Save the x coordinate of the pressed point to see if the switch was slid*/
        lv_indev_t * indev = lv_indev_get_act();
        if(indev) {
            lv_point_t p;
            lv_indev_get_point(indev, &p);
            ext->start_x = p.x;
        }
        ext->slided  = 0;
        ext->changed = 0;
    } else if(sign == LV_SIGNAL_PRESSING) {
        /*See if the switch was slid (moved at least a little)*/
        lv_indev_t * indev = lv_indev_get_act();
        if(indev) {
            lv_point_t p = {0, 0};
            lv_indev_get_point(indev, &p);
            if(LV_MATH_ABS(p.x - ext->start_x) > LV_INDEV_DEF_DRAG_LIMIT) ext->slided = 1;
        }

        /*If didn't slide then revert the min/max value. So click without slide won't move the
         * switch as a slider*/
        if(ext->slided == 0) {
            if(lv_sw_get_state(sw))
                ext->slider.drag_value = LV_SW_MAX_VALUE;
            else
                ext->slider.drag_value = 0;
        }

        /*If explicitly changed (by slide) don't need to be toggled on release*/
        int16_t threshold = LV_SW_MAX_VALUE / 2;
        if((old_val < threshold && ext->slider.drag_value > threshold) ||
           (old_val > threshold && ext->slider.drag_value < threshold)) {
            ext->changed = 1;
        }
    } else if(sign == LV_SIGNAL_PRESS_LOST) {
        if(lv_sw_get_state(sw)) {
            lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on);
            lv_slider_set_value(sw, LV_SW_MAX_VALUE, LV_ANIM_ON);
            if(res != LV_RES_OK) return res;
        } else {
            lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
            lv_slider_set_value(sw, 0, LV_ANIM_ON);
            if(res != LV_RES_OK) return res;
        }
    } else if(sign == LV_SIGNAL_RELEASED) {
        /*If not dragged then toggle the switch*/
        if(ext->changed == 0) {
            int32_t state;
            if(lv_sw_get_state(sw)) {
                lv_sw_off(sw, LV_ANIM_ON);
                state = 0;
            } else {
                lv_sw_on(sw, LV_ANIM_ON);
                state = 1;
            }

            res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state);
            if(res != LV_RES_OK) return res;
        }
        /*If the switch was dragged then calculate the new state based on the current position*/
        else {
            int16_t v = lv_slider_get_value(sw);
            int32_t state;
            if(v > LV_SW_MAX_VALUE / 2) {
                lv_sw_on(sw, LV_ANIM_ON);
                state = 1;
            } else {
                lv_sw_off(sw, LV_ANIM_ON);
                state = 0;
            }
            res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state);
            if(res != LV_RES_OK) return res;
        }
    } else if(sign == LV_SIGNAL_CONTROL) {
        char c = *((char *)param);
        uint32_t state;
        if(c == LV_KEY_RIGHT || c == LV_KEY_UP) {
            lv_slider_set_value(sw, LV_SW_MAX_VALUE, true);
            state = 1;
            res   = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state);
            if(res != LV_RES_OK) return res;
        } else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
            lv_slider_set_value(sw, 0, true);
            state = 0;
            res   = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state);
            if(res != LV_RES_OK) return res;
        }
    } else if(sign == LV_SIGNAL_GET_EDITABLE) {
        bool * editable = (bool *)param;
        *editable       = false; /*The ancestor slider is editable the switch is not*/
    }

    return res;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %r12
movl %esi, %r13d
movq %rdi, %r14
callq 0x6747
cmpl $0x9, %r13d
jne 0x24ee7
movq %rax, %rbx
movzwl 0x20(%rax), %eax
jmp 0x24ef2
movq %rax, %rbx
movq %r14, %rdi
callq 0x1c203
movw %ax, 0x6(%rsp)
movq 0x28(%r14), %r15
andq $0x0, 0x28(%r14)
movzbl %r13b, %ebp
movq %r14, %rdi
movl %ebp, %esi
movq %r12, %rdx
callq *0x39566(%rip)          # 0x5e478
cmpb $0x1, %al
jne 0x24f6f
cmpb $0x7, %r13b
jne 0x24f39
leaq 0x16bf5(%rip), %rsi     # 0x3bb18
movq %r12, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x684b
movq %r15, 0x28(%r14)
movb $0x1, %al
testb %r13b, %r13b
je 0x24f6f
cmpl $0x8, %ebp
jne 0x24f7e
callq 0x35b3
testq %rax, %rax
je 0x24f69
movq %rsp, %r14
movq %rax, %rdi
movq %r14, %rsi
callq 0x3661
movzwl (%r14), %eax
movw %ax, 0x38(%rbx)
andb $-0x4, 0x3a(%rbx)
movb $0x1, %al
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpb $0x9, %r13b
jne 0x24fef
callq 0x35b3
testq %rax, %rax
je 0x24fbd
movq %rsp, %r12
andl $0x0, (%r12)
movq %rax, %rdi
movq %r12, %rsi
callq 0x3661
movswl (%r12), %eax
movswl 0x38(%rbx), %ecx
subl %ecx, %eax
movl %eax, %ecx
negl %ecx
cmovsl %eax, %ecx
cmpw $0xb, %cx
jb 0x24fbd
orb $0x2, 0x3a(%rbx)
testb $0x2, 0x3a(%rbx)
jne 0x24fd9
movq %r14, %rdi
callq 0x251da
xorl %ecx, %ecx
testb %al, %al
pushq $0x64
popq %rax
cmovel %ecx, %eax
movw %ax, 0x20(%rbx)
movzwl 0x6(%rsp), %ecx
cmpw $0x31, %cx
movb $0x1, %al
jg 0x25038
cmpw $0x32, 0x20(%rbx)
jle 0x24f6f
jmp 0x2504d
addl $-0xa, %ebp
cmpl $0x9, %ebp
ja 0x24f6f
leaq 0x16ace(%rip), %rdx     # 0x3bad0
movslq (%rdx,%rbp,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq %r14, %rdi
callq 0x251da
testb %al, %al
je 0x250ed
movq 0x30(%rbx), %rdx
pushq $0x2
popq %rsi
movq %r14, %rdi
callq 0x1c13f
pushq $0x64
popq %rsi
pushq $0x1
popq %rdx
movq %r14, %rdi
jmp 0x25104
cmpw $0x32, %cx
je 0x24f6f
cmpw $0x31, 0x20(%rbx)
jg 0x24f6f
orb $0x1, 0x3a(%rbx)
jmp 0x24f6f
movzbl (%r12), %eax
movl %eax, %ecx
andb $-0x3, %cl
cmpb $0x11, %cl
jne 0x250b4
pushq $0x64
popq %rsi
pushq $0x1
popq %rdx
movq %r14, %rdi
callq 0x8a31
movq %rsp, %rdx
movl $0x1, (%rdx)
jmp 0x250d5
testb $0x1, 0x3a(%rbx)
jne 0x2510e
movq %r14, %rdi
callq 0x251da
testb %al, %al
je 0x25120
pushq $0x1
popq %rsi
movq %r14, %rdi
callq 0x25239
xorl %ebx, %ebx
jmp 0x2512d
movb $0x0, (%r12)
jmp 0x24f6f
cmpl $0x14, %eax
je 0x250c2
cmpl $0x12, %eax
jne 0x24f6d
pushq $0x1
popq %rdx
movq %r14, %rdi
xorl %esi, %esi
callq 0x8a31
movq %rsp, %rdx
andl $0x0, (%rdx)
pushq $0xe
popq %rsi
movq %r14, %rdi
callq 0x4caf
cmpb $0x1, %al
je 0x24f6d
jmp 0x24f6f
movq 0x28(%rbx), %rdx
pushq $0x2
popq %rsi
movq %r14, %rdi
callq 0x1c13f
pushq $0x1
popq %rdx
movq %r14, %rdi
xorl %esi, %esi
callq 0x8a31
jmp 0x24f6d
movq %r14, %rdi
callq 0x1c203
cmpw $0x33, %ax
jl 0x25098
pushq $0x1
popq %rbx
movq %r14, %rdi
movl %ebx, %esi
callq 0x251e9
movq %rsp, %rdx
movl %ebx, (%rdx)
pushq $0xe
popq %rsi
movq %r14, %rdi
callq 0x4caf
jmp 0x24f6f