// File: utkukaratas[P]xkeylayers/xkeylayers.cpp
// Function: intercept(char*, XRecordInterceptData*)
void intercept(XPointer user_data, XRecordInterceptData* data)
{
    static bool mouse_pressed = False;

    if (data->category == XRecordFromServer)
    {
        xEvent* event = reinterpret_cast<xEvent*>(data->data);
        int     key_event = event->u.u.type;
        KeyCode key_code  = event->u.u.detail;
        debug("Intercepted key event %d, key code %d\n", key_event, key_code);

        TKey *g, *g_prev = NULL;

        for (g = app.generated; g != NULL; g = g->next)
        {
            if (g->key == key_code)
            {
                debug("Ignoring generated event.\n");
                if (g_prev != NULL)
                {
                    g_prev->next = g->next;
                }
                else
                {
                    app.generated = g->next;
                }
                free (g);
                goto exit;
            }
            g_prev = g;
        }

        // log last N keys for heuristics
        // todo: make this a circular buffer or something
        if (key_event == KeyRelease) {
            timeval now;
            gettimeofday(&now, NULL);
            auto p = make_pair(sym_from_code(key_code), now);
            app.last_presses.push_back(p);
        }

        if (key_event == ButtonPress)
        {
            mouse_pressed = True;
        }
        else if (key_event == ButtonRelease)
        {
            mouse_pressed = False;
        }
        else
        {
            for (TModifierKey* mod : app.modifiers) {
                if ((mod->use_keycode == False && sym_from_code(key_code) == mod->keysym)
                    ||
                    (mod->use_keycode == True && key_code == mod->keycode))
                {
                    handle_modifier(mod, mouse_pressed, key_event);
                }
                else if (mod->is_down && key_event == KeyPress)
                {
                    mod->used = True;
                }
            }
        }
    }

exit:
    XRecordFreeData(data);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x18(%rax)
jne 0x2d66
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x18(%rbp), %rax
movb 0x1(%rax), %al
movb %al, -0x1d(%rbp)
movl -0x1c(%rbp), %esi
movzbl -0x1d(%rbp), %edx
leaq 0x45ab(%rip), %rdi      # 0x712a
movb $0x0, %al
callq 0x26d0
movq $0x0, -0x30(%rbp)
movq 0x8753(%rip), %rax      # 0xb2e8
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x2c09
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
movzbl -0x1d(%rbp), %ecx
cmpl %ecx, %eax
jne 0x2bf3
leaq 0x459b(%rip), %rdi      # 0x7151
movb $0x0, %al
callq 0x26d0
cmpq $0x0, -0x30(%rbp)
je 0x2bd6
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x2be5
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x8703(%rip)      # 0xb2e8
movq -0x28(%rbp), %rdi
callq 0x21f0
jmp 0x2d68
movq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x2b99
cmpl $0x3, -0x1c(%rbp)
jne 0x2c51
leaq -0x40(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x22e0
movzbl -0x1d(%rbp), %edi
callq 0x3e70
movq %rax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0x40(%rbp), %rdx
callq 0x3ec0
leaq 0x85cf(%rip), %rdi      # 0xb210
addq $0xc0, %rdi
leaq -0x58(%rbp), %rsi
callq 0x3ef0
cmpl $0x4, -0x1c(%rbp)
jne 0x2c63
movb $0x1, 0x86aa(%rip)      # 0xb308
jmp 0x2d64
cmpl $0x5, -0x1c(%rbp)
jne 0x2c75
movb $0x0, 0x8698(%rip)      # 0xb308
jmp 0x2d62
leaq 0x8594(%rip), %rax      # 0xb210
addq $0xa8, %rax
movq %rax, -0x68(%rbp)
leaq 0x8583(%rip), %rdi      # 0xb210
addq $0xa8, %rdi
callq 0x3f60
movq %rax, -0x70(%rbp)
leaq 0x856c(%rip), %rdi      # 0xb210
addq $0xa8, %rdi
callq 0x3f90
movq %rax, -0x78(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x3fc0
testb $0x1, %al
jne 0x2cca
jmp 0x2d60
leaq -0x70(%rbp), %rdi
callq 0x4000
movq (%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movb (%rax), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x2cfd
movzbl -0x1d(%rbp), %edi
callq 0x3e70
movq -0x80(%rbp), %rcx
cmpq 0x8(%rcx), %rax
je 0x2d1d
movq -0x80(%rbp), %rax
movb (%rax), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
jne 0x2d36
movzbl -0x1d(%rbp), %eax
movq -0x80(%rbp), %rcx
movzbl 0x1(%rcx), %ecx
cmpl %ecx, %eax
jne 0x2d36
movq -0x80(%rbp), %rdi
movb 0x85e1(%rip), %al       # 0xb308
movl -0x1c(%rbp), %edx
andb $0x1, %al
movzbl %al, %esi
callq 0x2d80
jmp 0x2d50
movq -0x80(%rbp), %rax
testb $0x1, 0x29(%rax)
je 0x2d4e
cmpl $0x2, -0x1c(%rbp)
jne 0x2d4e
movq -0x80(%rbp), %rax
movb $0x1, 0x28(%rax)
jmp 0x2d50
jmp 0x2d52
leaq -0x70(%rbp), %rdi
callq 0x4020
jmp 0x2cb4
jmp 0x2d62
jmp 0x2d64
jmp 0x2d66
jmp 0x2d68
movq -0x10(%rbp), %rdi
callq 0x20b0
addq $0x80, %rsp
popq %rbp
retq
nopw (%rax,%rax)