// File: /workspace/github_cpp_makefile_star2_O3/kazzmir[P]xborder/src/main.cpp
// Function: run_xborder(bool)
void run_xborder(bool glow){
    Display * display;

    display = XOpenDisplay(NULL);
    if (display == NULL){
        std::cerr << "Cannot open display" << std::endl;
        return;
    }

    srand(time(NULL));

    XSetErrorHandler(x_error);

    /*
    std::cout << "Once a window has been selected you can press the following keys in the selected window" << std::endl;
    std::cout << "Press 'right alt + right shift' to bring up the options window" << std::endl;
    std::cout << "Press 'left shift + right shift' to close the border" << std::endl;
    */
    std::cout << "Select an existing window to wrap in xborder" << std::endl;
    std::cout << "kill the xborder program with ctrl-c, or press the X window button will also stop the xborder program" << std::endl;

    struct sigaction action;
    action.sa_handler = &handle_signal;
    action.sa_flags = SA_RESTART;
    sigfillset(&action.sa_mask);
    sigaction(SIGHUP, &action, NULL);
    sigaction(SIGINT, &action, NULL);

    int screen = DefaultScreen(display);

    Window child_window = find_terminal(display);
    if (child_window == RootWindow(display, screen) || child_window == 0){
        std::cout << "Invalid window chosen" << std::endl;
        return;
    }
    std::cout << "Child window " << child_window << std::endl;

    int child_x, child_y;
    XWindowAttributes child_attributes;
    XGetWindowAttributes(display, child_window, &child_attributes);
    Window child;
    XTranslateCoordinates(display, child_window, child_attributes.root, 0, 0, &child_x, &child_y, &child);
    // std::cout << "Window at " << child_x << ", " << child_y << std::endl;

    int border_size = 3;

    int use_width = child_attributes.width + border_size * 2;
    int use_height = child_attributes.height + border_size * 2;
    window = XCreateSimpleWindow(display, RootWindow(display, screen), child_x, child_y, use_width, use_height, 1, BlackPixel(display, screen), start_color(display).pixel);

    set_xborder_window(display, window);

    XSelectInput(display, window,
                 ExposureMask |
                 FocusChangeMask |
                 SubstructureNotifyMask |
                 StructureNotifyMask);
    std::cout << "Xborder window " << window << std::endl;
    XMapWindow(display, window);

    Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", false);
    XSetWMProtocols(display, window, &wm_delete_window, 1);

    // delete_properties(display, child_window);
    set_override_redirect(display, child_window, true);

    XReparentWindow(display, child_window, window, border_size, border_size);
    /*
    std::cout << "Child root window " << get_root_window(display, child_window) << std::endl;
    std::cout << "Child parent window " << get_parent_window(display, child_window) << std::endl;
    // xdebug("XReparentWindow: %d\n", XReparentWindow(display, child_window, window, border_size, border_size));
    std::cout << "Child root window after reparent " << get_root_window(display, child_window) << std::endl;
    std::cout << "Child parent window after reparent " << get_parent_window(display, child_window) << std::endl;
    */
    // XSelectInput(display, child_window, KeyPressMask | KeyReleaseMask);
    XMoveWindow(display, window, child_x, child_y);

    Atom wm_protocols_atom = XInternAtom(display, "WM_PROTOCOLS", true);

    bool shift_pressed = false;
    bool alt_pressed = false;

    OptionWindow* optionWindow = NULL;
    // Window option_window = 0;
    // int palette_start = 20;
    std::string window_title = get_window_title(display, child_window);

    GC graphics = NULL;
    XStoreName(display, window, window_title.c_str());

    uint64_t glow_start = time_now();
    int glow_color = rand() % 360;
    int glow_speed = 0;
    if (glow){
        glow_speed = 50;
    }
    
    Atom xborder_atom = XInternAtom(display, "xborder", false);

    while (1){
        if (quit_now){
            std::cout << "Bye!" << std::endl;
            break;
        }

        /* TODO: move all the glow code into an object */
        if (glow_speed > 0){
            uint64_t check = time_now();
            int use_speed = glow_max_speed - glow_speed;
            if (use_speed < 1){
                use_speed = 1;
            }
            int move = (check - glow_start) / use_speed / 2;
            if (move > 0){
                glow_color = (glow_color + move) % 360;
                rgb next_color = get_rgb(glow_color, 1.0, 1.0);
                change_background_color(display, window, next_color);
                glow_start += move * use_speed;
            }
        }

        if (get_parent_window(display, child_window) != window){
            XReparentWindow(display, child_window, window, border_size, border_size);
        }

        if (XPending(display) == 0){
            usleep(1000);
            continue;
        }

        /*
        Window focus;
        int state;
        XGetInputFocus(display, &focus, &state);
        std::cout << "Focus state " << focus << std::endl;
        */

        XEvent event;
        XNextEvent(display, &event);

        if (optionWindow != NULL){
            optionWindow->handleEvent(&event, &glow_speed);
            if (optionWindow->isDead()){
                delete optionWindow;
                optionWindow = NULL;
            }
        }

        if (event.xany.window == window){
            if (event.type == Expose){
                /* anything to do here? the child already seems to get expose events */
            } else if (event.type == FocusIn){
                if (child_window != 0){
                    /* FIXME: somehow the child_window can be destroyed before we get here. check that the child is a valid window? */
                    XSetInputFocus(display, child_window, RevertToPointerRoot, CurrentTime);
                }
            } else if (event.type == ClientMessage){
                XClientMessageEvent * client = &event.xclient;

                // std::cout << "Got client message: " << XGetAtomName(display, client->message_type) << std::endl;

                if (client->message_type == xborder_atom &&
                    client->data.b[0] == XBorderConfigure){
                    std::cout << "Reconfigure xborder" << std::endl;

                    if (optionWindow != NULL){
                        optionWindow->raise();
                    } else {
                        optionWindow = OptionWindow::create(display, window);
                    }
                } else if (client->message_type == wm_protocols_atom &&
                           (Atom) client->data.l[0] == wm_delete_window){
                    break;
                }
            } else if (event.type == DestroyNotify){
                // std::cout << "Child window " << child_window << " event.event " << event.xdestroywindow.event << " event.window " << event.xdestroywindow.window << std::endl;
                /* there is no more child to deal with */
                if (event.xdestroywindow.window == child_window){
                    child_window = 0;
                    break;
                }
            } else if (event.type == ConfigureNotify){
                XWindowAttributes self;
                XGetWindowAttributes(display, window, &self);
                XResizeWindow(display, child_window, self.width - border_size * 2, self.height - border_size * 2);
            }
        }
    }

    if (optionWindow != NULL){
        delete optionWindow;
        optionWindow = NULL;
    }

    if (child_window != 0){
        set_override_redirect(display, child_window, false);
        Window child_root = child_attributes.root;
        /* Place the window wherever the container is now */
        XGetWindowAttributes(display, window, &child_attributes);
        XReparentWindow(display, child_window, child_root, child_attributes.x, child_attributes.y);
        XTranslateCoordinates(display, window, child_attributes.root, 0, 0, &child_x, &child_y, &child);
        XMoveWindow(display, child_window, child_x, child_y - border_size * 2);
    }

    XDestroyWindow(display, window);
    XCloseDisplay(display);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x308, %rsp            # imm = 0x308
movl %edi, %r15d
xorl %edi, %edi
callq 0x33e0
testq %rax, %rax
je 0x4be4
movq %rax, %rbx
xorl %edi, %edi
callq 0x3280
movl %eax, %edi
callq 0x32b0
leaq -0x517(%rip), %rdi      # 0x4033
callq 0x30e0
movq 0x3a7a(%rip), %r12      # 0x7fd0
leaq 0x1c9f(%rip), %rsi      # 0x61fc
movl $0x2c, %edx
movq %r12, %rdi
callq 0x3350
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq %r12, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x31d0
leaq 0x1c90(%rip), %rsi      # 0x6229
movl $0x65, %edx
movq %r12, %rdi
callq 0x3350
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq %r12, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x31d0
leaq -0x661(%rip), %rax      # 0x3f74
leaq -0x308(%rbp), %rdi
movq %rax, -0x8(%rdi)
movl $0x10000000, 0x80(%rdi) # imm = 0x10000000
callq 0x3100
leaq -0x310(%rbp), %r14
movl $0x1, %edi
movq %r14, %rsi
xorl %edx, %edx
callq 0x3390
movl $0x2, %edi
movq %r14, %rsi
xorl %edx, %edx
callq 0x3390
movslq 0xe0(%rbx), %r14
movq %rbx, %rdi
callq 0x3938
testq %rax, %rax
je 0x4c37
movq %rax, %r13
movq 0xe8(%rbx), %rax
shlq $0x7, %r14
cmpq 0x10(%rax,%r14), %r13
je 0x4c37
movl %r15d, -0x54(%rbp)
movq 0x3980(%rip), %r15      # 0x7fd0
leaq 0x1c4e(%rip), %rsi      # 0x62a5
movl $0xd, %edx
movq %r15, %rdi
callq 0x3350
movq %r15, %rdi
movq %r13, %rsi
callq 0x31c0
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq %r12, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x31d0
movq %r13, %r15
leaq -0x1f0(%rbp), %r13
movq %rbx, %rdi
movq %r15, %rsi
movq %r15, -0x48(%rbp)
movq %r13, %rdx
callq 0x3560
movq 0x20(%r13), %rdx
leaq -0x70(%rbp), %rax
movq %rax, 0x8(%rsp)
leaq -0x2c(%rbp), %rax
movq %rax, (%rsp)
leaq -0x34(%rbp), %r12
movq %rbx, %rdi
movq %r15, %rsi
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r12, %r9
callq 0x3510
movl 0x8(%r13), %r15d
movl 0xc(%r13), %r13d
addl $0x6, %r15d
addl $0x6, %r13d
movq 0xe8(%rbx), %rax
movl (%r12), %ecx
movl %ecx, -0x40(%rbp)
leaq -0x2c(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, -0x50(%rbp)
movq 0x10(%rax,%r14), %r12
movq 0x60(%rax,%r14), %r14
movq %rbx, %rdi
callq 0x3f81
movq %rax, 0x10(%rsp)
movq %r14, 0x8(%rsp)
movl $0x1, %r14d
movl %r14d, (%rsp)
movq %rbx, %rdi
movq %r12, %rsi
movl -0x40(%rbp), %edx
movl -0x50(%rbp), %ecx
movl %r15d, %r8d
movl %r13d, %r9d
callq 0x30d0
movq %rax, 0x3bcc(%rip)      # 0x8318
movq %rbx, %rdi
movq %rax, %rsi
callq 0x44c0
movq 0x3bba(%rip), %rsi      # 0x8318
movl $0x2a8000, %edx         # imm = 0x2A8000
movq %rbx, %rdi
callq 0x31b0
leaq 0x1b41(%rip), %rsi      # 0x62b3
movl $0xf, %edx
movq 0x3852(%rip), %r15      # 0x7fd0
movq %r15, %rdi
callq 0x3350
movq 0x3b8b(%rip), %rsi      # 0x8318
movq %r15, %rdi
callq 0x31c0
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq %r15, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x31d0
movq 0x3b52(%rip), %rsi      # 0x8318
movq %rbx, %rdi
callq 0x3330
leaq 0x1aee(%rip), %rsi      # 0x62c3
movq %rbx, %rdi
xorl %edx, %edx
callq 0x3200
leaq -0x68(%rbp), %rdx
movq %rax, (%rdx)
movq 0x3b2b(%rip), %rsi      # 0x8318
movq %rbx, %rdi
movl $0x1, %ecx
callq 0x3180
leaq -0x168(%rbp), %rcx
movl %r14d, 0x58(%rcx)
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
movq -0x48(%rbp), %r14
movq %r14, %rsi
callq 0x34f0
movq 0x3af8(%rip), %rdx      # 0x8318
movq %rbx, %rdi
movq %r14, %rsi
movl $0x3, %ecx
movl $0x3, %r8d
callq 0x3030
movq 0x3adb(%rip), %rsi      # 0x8318
leaq -0x34(%rbp), %rax
movl (%rax), %edx
leaq -0x2c(%rbp), %rax
movl (%rax), %ecx
movq %rbx, %rdi
callq 0x3240
leaq 0x1a7c(%rip), %rsi      # 0x62d4
movq %rbx, %rdi
movl $0x1, %edx
callq 0x3200
movq %rax, -0x60(%rbp)
leaq -0x90(%rbp), %r15
movq %r15, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x4192
movq 0x3a93(%rip), %rsi      # 0x8318
movq (%r15), %rdx
movq %rbx, %rdi
callq 0x3060
callq 0x3d34
movq %rax, -0x40(%rbp)
callq 0x3090
movl %eax, %r13d
cmpb $0x0, -0x54(%rbp)
movl $0x32, %eax
movl $0x0, %ecx
cmovel %ecx, %eax
movl %eax, -0x30(%rbp)
leaq 0x1a36(%rip), %rsi      # 0x62f2
movq %rbx, %rdi
xorl %edx, %edx
callq 0x3200
movq %rax, -0x50(%rbp)
movslq %r13d, %r15
imulq $-0x49f49f49, %r15, %rax # imm = 0xB60B60B7
shrq $0x20, %rax
addl %r15d, %eax
movl %eax, %ecx
shrl $0x1f, %ecx
sarl $0x8, %eax
addl %ecx, %eax
imull $0x168, %eax, %eax      # imm = 0x168
subl %eax, %r15d
xorl %r12d, %r12d
movq -0x40(%rbp), %r13
movq %r14, -0x48(%rbp)
movq %r12, -0x40(%rbp)
movb 0x3a0e(%rip), %al       # 0x8311
cmpb $0x1, %al
je 0x4c78
cmpl $0x0, -0x30(%rbp)
jle 0x4a05
callq 0x3d34
movl $0x64, %r14d
subl -0x30(%rbp), %r14d
cmpl $0x2, %r14d
movl $0x1, %ecx
cmovll %ecx, %r14d
movq %r13, %r12
subq %r13, %rax
xorl %edx, %edx
divq %r14
movq %rax, %r13
shrq %r13
testl %r13d, %r13d
jle 0x49f7
addl %r13d, %r15d
movslq %r15d, %r15
imulq $-0x49f49f49, %r15, %rax # imm = 0xB60B60B7
shrq $0x20, %rax
addl %r15d, %eax
movl %eax, %ecx
shrl $0x1f, %ecx
sarl $0x8, %eax
addl %ecx, %eax
imull $0x168, %eax, %eax      # imm = 0x168
subl %eax, %r15d
xorps %xmm0, %xmm0
cvtsi2sd %r15d, %xmm0
movsd %xmm0, -0x168(%rbp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, -0x160(%rbp)
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rax
movq %rax, 0x10(%rsp)
movups -0x168(%rbp), %xmm0
movups %xmm0, (%rsp)
leaq -0xa8(%rbp), %rdi
callq 0x3a7b
movq 0x3954(%rip), %rsi      # 0x8318
movq -0x98(%rbp), %rax
movq %rax, 0x10(%rsp)
movups -0xa8(%rbp), %xmm0
movups %xmm0, (%rsp)
movq %rbx, %rdi
callq 0x3ecd
imull %r13d, %r14d
movq %r12, %r13
addq %r14, %r13
movq -0x48(%rbp), %r14
movq -0x40(%rbp), %r12
jmp 0x4a05
movq -0x48(%rbp), %r14
movq -0x40(%rbp), %rax
movq %r12, %r13
movq %rax, %r12
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4475
movq 0x3901(%rip), %rdx      # 0x8318
cmpq %rdx, %rax
je 0x4a32
movq %rbx, %rdi
movq %r14, %rsi
movl $0x3, %ecx
movl $0x3, %r8d
callq 0x3030
movq %rbx, %rdi
callq 0x3270
testl %eax, %eax
jne 0x4a4d
movl $0x3e8, %edi            # imm = 0x3E8
callq 0x33f0
jmp 0x48fd
movq %rbx, %rdi
leaq -0x168(%rbp), %rsi
callq 0x3400
testq %r12, %r12
je 0x4a86
movq %r12, %rdi
leaq -0x168(%rbp), %rsi
leaq -0x30(%rbp), %rdx
callq 0x51d8
cmpb $0x1, 0x28(%r12)
jne 0x4a89
movq (%r12), %rax
movq %r12, %rdi
callq *0x8(%rax)
xorl %r12d, %r12d
movq -0x148(%rbp), %rsi
cmpq 0x3881(%rip), %rsi      # 0x8318
jne 0x48f5
movl -0x168(%rbp), %eax
cmpl $0xc, %eax
je 0x48f5
cmpl $0x20, %eax
jg 0x4ae7
cmpl $0x16, %eax
jne 0x4b26
movq %rbx, %rdi
leaq -0x278(%rbp), %rdx
callq 0x3560
movl -0x270(%rbp), %edx
movl -0x26c(%rbp), %ecx
addl $-0x6, %edx
addl $-0x6, %ecx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3460
jmp 0x48f9
cmpl $0x21, %eax
jne 0x48f5
movq -0x140(%rbp), %rax
cmpq -0x50(%rbp), %rax
jne 0x4b06
cmpb $0x0, -0x130(%rbp)
je 0x4b62
cmpq -0x60(%rbp), %rax
jne 0x48f5
movq -0x130(%rbp), %rax
cmpq -0x68(%rbp), %rax
jne 0x48f9
jmp 0x4cbe
cmpl $0x9, %eax
je 0x4b46
cmpl $0x11, %eax
jne 0x48f5
cmpq %r14, -0x140(%rbp)
jne 0x48f5
jmp 0x4daf
testq %r14, %r14
je 0x4bc5
movq %rbx, %rdi
movq %r14, %rsi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x3210
jmp 0x48f5
movl $0x13, %edx
movq 0x3462(%rip), %rdi      # 0x7fd0
leaq 0x1771(%rip), %rsi      # 0x62e6
callq 0x3350
movq 0x344f(%rip), %rcx      # 0x7fd0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq 0x3431(%rip), %rdi      # 0x7fd0
callq 0x3040
movq %rax, %rdi
callq 0x31d0
testq %r12, %r12
je 0x4bcd
movq 0x8(%r12), %rsi
movq 0x20(%r12), %rdi
callq 0x3340
jmp 0x48f5
xorl %r14d, %r14d
jmp 0x48f5
movq 0x3744(%rip), %rsi      # 0x8318
movq %rbx, %rdi
callq 0x5548
movq %rax, %r12
jmp 0x48f5
movq 0x3405(%rip), %rbx      # 0x7ff0
leaq 0x15f6(%rip), %rsi      # 0x61e8
movl $0x13, %edx
movq %rbx, %rdi
callq 0x3350
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3040
movq %rax, %rdi
addq $0x308, %rsp            # imm = 0x308
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x31d0
leaq 0x1651(%rip), %rsi      # 0x628f
movl $0x15, %edx
movq %r12, %rdi
callq 0x3350
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq %r12, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x31d0
jmp 0x4d9d
movq 0x3351(%rip), %r15      # 0x7fd0
leaq 0x165b(%rip), %rsi      # 0x62e1
movl $0x4, %edx
movq %r15, %rdi
callq 0x3350
movq (%r15), %rax
addq -0x18(%rax), %r15
movq %r15, %rdi
movl $0xa, %esi
callq 0x32c0
movsbl %al, %esi
movq 0x331f(%rip), %rdi      # 0x7fd0
callq 0x3040
movq %rax, %rdi
callq 0x31d0
testq %r12, %r12
je 0x4ccd
movq (%r12), %rax
movq %r12, %rdi
callq *0x8(%rax)
testq %r14, %r14
je 0x4d6d
leaq -0x168(%rbp), %rcx
movl $0x0, 0x58(%rcx)
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
movq %r14, %rsi
callq 0x34f0
leaq -0x1f0(%rbp), %rdx
movq 0x20(%rdx), %r15
movq 0x3612(%rip), %rsi      # 0x8318
movq %rbx, %rdi
callq 0x3560
movl -0x1f0(%rbp), %ecx
movl -0x1ec(%rbp), %r8d
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x3030
movq 0x35e8(%rip), %rsi      # 0x8318
movq -0x1d0(%rbp), %rdx
leaq -0x70(%rbp), %rax
movq %rax, 0x8(%rsp)
leaq -0x2c(%rbp), %rax
movq %rax, (%rsp)
leaq -0x34(%rbp), %r9
movq %rbx, %rdi
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x3510
movl -0x34(%rbp), %edx
movl -0x2c(%rbp), %ecx
addl $-0x6, %ecx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3240
movq 0x35a4(%rip), %rsi      # 0x8318
movq %rbx, %rdi
callq 0x34b0
movq %rbx, %rdi
callq 0x35a0
leaq -0x80(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4d9d
movq -0x80(%rbp), %rsi
incq %rsi
callq 0x3300
addq $0x308, %rsp            # imm = 0x308
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %r14d, %r14d
jmp 0x4cbe
jmp 0x4dc7
jmp 0x4dc7
jmp 0x4dc7
jmp 0x4dc7
jmp 0x4dc7
jmp 0x4dc7
jmp 0x4dc7
jmp 0x4dc7
movq %rax, %rbx
leaq -0x80(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4de3
movq -0x80(%rbp), %rsi
incq %rsi
callq 0x3300
movq %rbx, %rdi
callq 0x3550