#include <stdint.h>
#include <dlfcn.h>

#include "debug.h"
#include "box32context.h"
#include "wrapper32.h"
#include "library.h"
#include "bridge.h"
#include "librarian/library_private.h"
#include "converter32.h"
#include "my_x11_defs.h"
#include "my_x11_defs_32.h"
#include "my_x11_conv.h"

typedef void(*convertXEvent_to_32)(my_XEvent_32_t* dst, my_XEvent_t* src);
typedef void(*convertXEvent_to_64)(my_XEvent_t* dst, my_XEvent_32_t* src);

typedef struct reg_event_s {
    uint32_t event;
    convertXEvent_to_32 to32;
    convertXEvent_to_64 to64;
} reg_event_t;
typedef struct register_events_s {
    void* id;
    uint32_t start_event;
    uint32_t end_event;
    size_t n;
    reg_event_t* events;
    struct register_events_s* next;
} register_events_t;

static register_events_t* register_events_head = NULL;

void convertXEvent(my_XEvent_32_t* dst, my_XEvent_t* src)
{
    if(!src->type) {
        // This is an XErrorEvent, and it's different!
        dst->xerror.type = src->xerror.type;
        dst->xerror.display = to_ptrv(FindDisplay(src->xerror.display));
        dst->xerror.resourceid = to_ulong(src->xerror.resourceid);
        dst->xerror.serial = to_ulong(src->xerror.serial);
        dst->xerror.error_code = src->xerror.error_code;
        dst->xerror.request_code = src->xerror.request_code;
        dst->xerror.minor_code = src->xerror.minor_code;
        return;
    }
    // convert the XAnyEvent first, as it's a common set
    int type = src->type;
    dst->type = src->type;
    dst->xany.serial = to_ulong(src->xany.serial);
    dst->xany.send_event = src->xany.serial;
    dst->xany.display = to_ptrv(FindDisplay(src->xany.display));
    if(type!=XEVT_GenericEvent)
        dst->xany.window = to_ulong(src->xany.window);
    switch(type) {
        case XEVT_KeyPress:
        case XEVT_KeyRelease:
            dst->xkey.root = to_ulong(src->xkey.root);
            dst->xkey.subwindow = to_ulong(src->xkey.subwindow);
            dst->xkey.time = to_ulong(src->xkey.time);
            dst->xkey.x = src->xkey.x;
            dst->xkey.y = src->xkey.y;
            dst->xkey.x_root = src->xkey.x_root;
            dst->xkey.y_root = src->xkey.y_root;
            dst->xkey.state = src->xkey.state;
            dst->xkey.keycode = src->xkey.keycode;
            dst->xkey.same_screen = src->xkey.same_screen;
            break;
        case XEVT_ButtonPress:
        case XEVT_ButtonRelease:
            dst->xbutton.root = to_ulong(src->xbutton.root);
            dst->xbutton.subwindow = to_ulong(src->xbutton.subwindow);
            dst->xbutton.time = to_ulong(src->xbutton.time);
            dst->xbutton.x = src->xbutton.x;
            dst->xbutton.y = src->xbutton.y;
            dst->xbutton.x_root = src->xbutton.x_root;
            dst->xbutton.y_root = src->xbutton.y_root;
            dst->xbutton.state = src->xbutton.state;
            dst->xbutton.button = src->xbutton.button;
            dst->xbutton.same_screen = src->xbutton.same_screen;
            break;
        case XEVT_MotionNotify:
            dst->xmotion.root = to_ulong(src->xmotion.root);
            dst->xmotion.subwindow = to_ulong(src->xmotion.subwindow);
            dst->xmotion.time = to_ulong(src->xmotion.time);
            dst->xmotion.x = src->xmotion.x;
            dst->xmotion.y = src->xmotion.y;
            dst->xmotion.x_root = src->xmotion.x_root;
            dst->xmotion.y_root = src->xmotion.y_root;
            dst->xmotion.state = src->xmotion.state;
            dst->xmotion.is_hint = src->xmotion.is_hint;
            dst->xmotion.same_screen = src->xmotion.same_screen;
            break;
        case XEVT_EnterNotify:
        case XEVT_LeaveNotify:
            dst->xcrossing.root = to_ulong(src->xcrossing.root);
            dst->xcrossing.subwindow = to_ulong(src->xcrossing.subwindow);
            dst->xcrossing.time = to_ulong(src->xcrossing.time);
            dst->xcrossing.x = src->xcrossing.x;
            dst->xcrossing.y = src->xcrossing.y;
            dst->xcrossing.x_root = src->xcrossing.x_root;
            dst->xcrossing.y_root = src->xcrossing.y_root;
            dst->xcrossing.mode = src->xcrossing.mode;
            dst->xcrossing.detail = src->xcrossing.detail;
            dst->xcrossing.same_screen = src->xcrossing.same_screen;
            dst->xcrossing.focus = src->xcrossing.focus;
            dst->xcrossing.state = src->xcrossing.state;
            break;
        case XEVT_FocusIn:
        case XEVT_FocusOut:
            dst->xfocus.mode = src->xfocus.mode;
            dst->xfocus.detail = src->xfocus.detail;
            break;
        case XEVT_KeymapNotify:
            memcpy(dst->xkeymap.key_vector, src->xkeymap.key_vector, 32);
            break;
        case XEVT_Expose:
            dst->xexpose.x = src->xexpose.x;
            dst->xexpose.y = src->xexpose.y;
            dst->xexpose.width = src->xexpose.width;
            dst->xexpose.height = src->xexpose.height;
            dst->xexpose.count = src->xexpose.count;
            break;
        case XEVT_GraphicsExpose:
            dst->xgraphicsexpose.x = src->xgraphicsexpose.x;
            dst->xgraphicsexpose.y = src->xgraphicsexpose.y;
            dst->xgraphicsexpose.width = src->xgraphicsexpose.width;
            dst->xgraphicsexpose.height = src->xgraphicsexpose.height;
            dst->xgraphicsexpose.count = src->xgraphicsexpose.count;
            dst->xgraphicsexpose.major_code = src->xgraphicsexpose.major_code;
            dst->xgraphicsexpose.minor_code = src->xgraphicsexpose.minor_code;
            break;
        case XEVT_NoExpose:
            dst->xnoexpose.major_code = src->xnoexpose.major_code;
            dst->xnoexpose.minor_code = src->xnoexpose.minor_code;
            break;
        case XEVT_VisibilityNotify:
            dst->xvisibility.state = src->xvisibility.state;
            break;
        case XEVT_CreateNotify:
            dst->xcreatewindow.window = to_ulong(src->xcreatewindow.window);
            dst->xcreatewindow.x = src->xcreatewindow.x;
            dst->xcreatewindow.y = src->xcreatewindow.y;
            dst->xcreatewindow.width = src->xcreatewindow.width;
            dst->xcreatewindow.height = src->xcreatewindow.height;
            dst->xcreatewindow.border_width = src->xcreatewindow.border_width;
            dst->xcreatewindow.override_redirect = src->xcreatewindow.override_redirect;
            break;
        case XEVT_DestroyNotify:
            dst->xdestroywindow.window = to_ulong(src->xdestroywindow.window);
            break;
        case XEVT_UnmapNotify:
            dst->xunmap.window = to_ulong(src->xunmap.window);
            dst->xunmap.from_configure = src->xunmap.from_configure;
            break;
        case XEVT_MapNotify:
            dst->xmap.window = to_ulong(src->xmap.window);
            dst->xmap.override_redirect = src->xmap.override_redirect;
            break;
        case XEVT_MapRequest:
            dst->xmaprequest.window = to_ulong(src->xmaprequest.window);
            break;
        case XEVT_ReparentNotify:
            dst->xreparent.window = to_ulong(src->xreparent.window);
            dst->xreparent.parent = to_ulong(src->xreparent.parent);
            dst->xreparent.x = src->xreparent.x;
            dst->xreparent.y = src->xreparent.y;
            dst->xreparent.override_redirect = src->xreparent.override_redirect;
            break;
        case XEVT_ConfigureNotify:
            dst->xconfigure.window = to_ulong(src->xconfigure.window);
            dst->xconfigure.x = src->xconfigure.x;
            dst->xconfigure.y = src->xconfigure.y;
            dst->xconfigure.width = src->xconfigure.width;
            dst->xconfigure.height = src->xconfigure.height;
            dst->xconfigure.border_width = src->xconfigure.border_width;
            dst->xconfigure.above = to_ulong(src->xconfigure.above);
            dst->xconfigure.override_redirect = src->xconfigure.override_redirect;
            break;
        case XEVT_ConfigureRequest:
            dst->xconfigurerequest.window = to_ulong(src->xconfigurerequest.window);
            dst->xconfigurerequest.x = src->xconfigurerequest.x;
            dst->xconfigurerequest.y = src->xconfigurerequest.y;
            dst->xconfigurerequest.width = src->xconfigurerequest.width;
            dst->xconfigurerequest.height = src->xconfigurerequest.height;
            dst->xconfigurerequest.border_width = src->xconfigurerequest.border_width;
            dst->xconfigurerequest.above = to_ulong(src->xconfigurerequest.above);
            dst->xconfigurerequest.detail = src->xconfigurerequest.detail;
            dst->xconfigurerequest.value_mask = to_ulong(src->xconfigurerequest.value_mask);
            break;
        case XEVT_GravityNotify:
            dst->xgravity.window = to_ulong(src->xgravity.window);
            dst->xgravity.x = src->xgravity.x;
            dst->xgravity.y = src->xgravity.y;
            break;
        case XEVT_ResizeRequest:
            dst->xresizerequest.width = src->xresizerequest.width;
            dst->xresizerequest.height = src->xresizerequest.height;
            break;
        case XEVT_CirculateNotify:
            dst->xcirculate.window = to_ulong(src->xcirculate.window);
            dst->xcirculate.place = src->xcirculate.place;
            break;
        case XEVT_CirculateRequest:
            dst->xcirculaterequest.window = to_ulong(src->xcirculaterequest.window);
            dst->xcirculaterequest.place = src->xcirculaterequest.place;
            break;
        case XEVT_PropertyNotify:
            dst->xproperty.atom = to_ulong(src->xproperty.atom);
            dst->xproperty.time = to_ulong(src->xproperty.time);
            dst->xproperty.state = src->xproperty.state;
            break;
        case XEVT_SelectionClear:
            dst->xselectionclear.selection = to_ulong(src->xselectionclear.selection);
            dst->xselectionclear.time = to_ulong(src->xselectionclear.time);
            break;
        case XEVT_SelectionRequest:
            dst->xselectionrequest.requestor = to_ulong(src->xselectionrequest.requestor);
            dst->xselectionrequest.selection = to_ulong(src->xselectionrequest.selection);
            dst->xselectionrequest.target = to_ulong(src->xselectionrequest.target);
            dst->xselectionrequest.property = to_ulong(src->xselectionrequest.property);
            dst->xselectionrequest.time = to_ulong(src->xselectionrequest.time);
            break;
        case XEVT_SelectionNotify:
            dst->xselection.selection = to_ulong(src->xselection.selection);
            dst->xselection.target = to_ulong(src->xselection.target);
            dst->xselection.property = to_ulong(src->xselection.property);
            dst->xselection.time = to_ulong(src->xselection.time);
            break;
        case XEVT_ColormapNotify:
            dst->xcolormap.colormap = to_ulong(src->xcolormap.colormap);
            dst->xcolormap.c_new = src->xcolormap.c_new;
            dst->xcolormap.state = src->xcolormap.state;
            break;
        case XEVT_ClientMessage:
            dst->xclient.message_type = to_ulong(src->xclient.message_type);
            dst->xclient.format = src->xclient.format;
            if(src->xclient.format==32)
                for(int i=0; i<5; ++i) {
                    if(((src->xclient.data.l[i]&0xffffffff80000000LL))==0xffffffff80000000LL)
                        dst->xclient.data.l[i] = to_ulong(src->xclient.data.l[i]&0xffffffff);   // negative value...
                    else
                        dst->xclient.data.l[i] = to_ulong(src->xclient.data.l[i]);
                }
            else
                memcpy(dst->xclient.data.b, src->xclient.data.b, 20);
            break;
        case XEVT_MappingNotify:
            dst->xmapping.request = src->xmapping.request;
            dst->xmapping.first_keycode = src->xmapping.first_keycode;
            dst->xmapping.count = src->xmapping.count;
            break;
        case XEVT_GenericEvent:
            dst->xcookie.extension = src->xcookie.extension;
            dst->xcookie.evtype = src->xcookie.evtype;
            dst->xcookie.cookie = src->xcookie.cookie;
            dst->xcookie.data = to_ptrv_silent(src->xcookie.data);  // in case data are not initialized
            break;
        default: {
            register_events_t* head = register_events_head;
            while(head) {
                if(type>=head->start_event && type<=head->end_event) {
                    for(int i=0; i<head->n; ++i)
                        if(type==head->events[i].event) {
                            head->events[i].to32(dst, src);
                            return;
                        }
                }
                head = head->next;
            }
            printf_log(LOG_INFO, "Warning, unsupported 32bits XEvent type=%d\n", type);
        }    
    }
}
void unconvertXEvent(my_XEvent_t* dst, my_XEvent_32_t* src)
{
    if(!src->type) {
        // This is an XErrorEvent, and it's different!
        dst->xerror.type = src->xerror.type;
        dst->xerror.display = getDisplay(from_ptrv(src->xerror.display));
        dst->xerror.resourceid = from_ulong(src->xerror.resourceid);
        dst->xerror.serial = from_ulong(src->xerror.serial);
        dst->xerror.error_code = src->xerror.error_code;
        dst->xerror.request_code = src->xerror.request_code;
        dst->xerror.minor_code = src->xerror.minor_code;
        return;
    }
    // convert the XAnyEvent first, as it's a common set
    int type = src->type;
    dst->type = src->type;
    if(type!=XEVT_GenericEvent)
        dst->xany.window = from_ulong(src->xany.window);
    dst->xany.display = getDisplay(from_ptrv(src->xany.display));
    dst->xany.send_event = src->xany.serial;
    dst->xany.serial = from_ulong(src->xany.serial);
    switch(type) {
        case XEVT_KeyPress:
        case XEVT_KeyRelease:
            dst->xkey.root = from_ulong(src->xkey.root);
            dst->xkey.subwindow = from_ulong(src->xkey.subwindow);
            dst->xkey.time = from_ulong(src->xkey.time);
            dst->xkey.x = src->xkey.x;
            dst->xkey.y = src->xkey.y;
            dst->xkey.x_root = src->xkey.x_root;
            dst->xkey.y_root = src->xkey.y_root;
            dst->xkey.state = src->xkey.state;
            dst->xkey.keycode = src->xkey.keycode;
            dst->xkey.same_screen = src->xkey.same_screen;
            break;
        case XEVT_ButtonPress:
        case XEVT_ButtonRelease:
            dst->xbutton.root = from_ulong(src->xbutton.root);
            dst->xbutton.subwindow = from_ulong(src->xbutton.subwindow);
            dst->xbutton.time = from_ulong(src->xbutton.time);
            dst->xbutton.x = src->xbutton.x;
            dst->xbutton.y = src->xbutton.y;
            dst->xbutton.x_root = src->xbutton.x_root;
            dst->xbutton.y_root = src->xbutton.y_root;
            dst->xbutton.state = src->xbutton.state;
            dst->xbutton.button = src->xbutton.button;
            dst->xbutton.same_screen = src->xbutton.same_screen;
            break;
        case XEVT_MotionNotify:
            dst->xmotion.root = from_ulong(src->xmotion.root);
            dst->xmotion.subwindow = from_ulong(src->xmotion.subwindow);
            dst->xmotion.time = from_ulong(src->xmotion.time);
            dst->xmotion.x = src->xmotion.x;
            dst->xmotion.y = src->xmotion.y;
            dst->xmotion.x_root = src->xmotion.x_root;
            dst->xmotion.y_root = src->xmotion.y_root;
            dst->xmotion.state = src->xmotion.state;
            dst->xmotion.is_hint = src->xmotion.is_hint;
            dst->xmotion.same_screen = src->xmotion.same_screen;
            break;
        case XEVT_EnterNotify:
        case XEVT_LeaveNotify:
            dst->xcrossing.root = from_ulong(src->xcrossing.root);
            dst->xcrossing.subwindow = from_ulong(src->xcrossing.subwindow);
            dst->xcrossing.time = from_ulong(src->xcrossing.time);
            dst->xcrossing.x = src->xcrossing.x;
            dst->xcrossing.y = src->xcrossing.y;
            dst->xcrossing.x_root = src->xcrossing.x_root;
            dst->xcrossing.y_root = src->xcrossing.y_root;
            dst->xcrossing.mode = src->xcrossing.mode;
            dst->xcrossing.detail = src->xcrossing.detail;
            dst->xcrossing.same_screen = src->xcrossing.same_screen;
            dst->xcrossing.focus = src->xcrossing.focus;
            dst->xcrossing.state = src->xcrossing.state;
            break;
        case XEVT_FocusIn:
        case XEVT_FocusOut:
            dst->xfocus.mode = src->xfocus.mode;
            dst->xfocus.detail = src->xfocus.detail;
            break;
        case XEVT_KeymapNotify:
            memcpy(dst->xkeymap.key_vector, src->xkeymap.key_vector, 32);
            break;
        case XEVT_Expose:
            dst->xexpose.x = src->xexpose.x;
            dst->xexpose.y = src->xexpose.y;
            dst->xexpose.width = src->xexpose.width;
            dst->xexpose.height = src->xexpose.height;
            dst->xexpose.count = src->xexpose.count;
            break;
        case XEVT_GraphicsExpose:
            dst->xgraphicsexpose.x = src->xgraphicsexpose.x;
            dst->xgraphicsexpose.y = src->xgraphicsexpose.y;
            dst->xgraphicsexpose.width = src->xgraphicsexpose.width;
            dst->xgraphicsexpose.height = src->xgraphicsexpose.height;
            dst->xgraphicsexpose.count = src->xgraphicsexpose.count;
            dst->xgraphicsexpose.major_code = src->xgraphicsexpose.major_code;
            dst->xgraphicsexpose.minor_code = src->xgraphicsexpose.minor_code;
            break;
        case XEVT_NoExpose:
            dst->xnoexpose.major_code = src->xnoexpose.major_code;
            dst->xnoexpose.minor_code = src->xnoexpose.minor_code;
            break;
        case XEVT_VisibilityNotify:
            dst->xvisibility.state = src->xvisibility.state;
            break;
        case XEVT_CreateNotify:
            dst->xcreatewindow.window = from_ulong(src->xcreatewindow.window);
            dst->xcreatewindow.x = src->xcreatewindow.x;
            dst->xcreatewindow.y = src->xcreatewindow.y;
            dst->xcreatewindow.width = src->xcreatewindow.width;
            dst->xcreatewindow.height = src->xcreatewindow.height;
            dst->xcreatewindow.border_width = src->xcreatewindow.border_width;
            dst->xcreatewindow.override_redirect = src->xcreatewindow.override_redirect;
            break;
        case XEVT_DestroyNotify:
            dst->xdestroywindow.window = from_ulong(src->xdestroywindow.window);
            break;
        case XEVT_UnmapNotify:
            dst->xunmap.window = from_ulong(src->xunmap.window);
            dst->xunmap.from_configure = src->xunmap.from_configure;
            break;
        case XEVT_MapNotify:
            dst->xmap.window = from_ulong(src->xmap.window);
            dst->xmap.override_redirect = src->xmap.override_redirect;
            break;
        case XEVT_MapRequest:
            dst->xmaprequest.window = from_ulong(src->xmaprequest.window);
            break;
        case XEVT_ReparentNotify:
            dst->xreparent.window = from_ulong(src->xreparent.window);
            dst->xreparent.parent = from_ulong(src->xreparent.parent);
            dst->xreparent.x = src->xreparent.x;
            dst->xreparent.y = src->xreparent.y;
            dst->xreparent.override_redirect = src->xreparent.override_redirect;
            break;
        case XEVT_ConfigureNotify:
            dst->xconfigure.window = from_ulong(src->xconfigure.window);
            dst->xconfigure.x = src->xconfigure.x;
            dst->xconfigure.y = src->xconfigure.y;
            dst->xconfigure.width = src->xconfigure.width;
            dst->xconfigure.height = src->xconfigure.height;
            dst->xconfigure.border_width = src->xconfigure.border_width;
            dst->xconfigure.above = from_ulong(src->xconfigure.above);
            dst->xconfigure.override_redirect = src->xconfigure.override_redirect;
            break;
        case XEVT_ConfigureRequest:
            dst->xconfigurerequest.window = from_ulong(src->xconfigurerequest.window);
            dst->xconfigurerequest.x = src->xconfigurerequest.x;
            dst->xconfigurerequest.y = src->xconfigurerequest.y;
            dst->xconfigurerequest.width = src->xconfigurerequest.width;
            dst->xconfigurerequest.height = src->xconfigurerequest.height;
            dst->xconfigurerequest.border_width = src->xconfigurerequest.border_width;
            dst->xconfigurerequest.above = from_ulong(src->xconfigurerequest.above);
            dst->xconfigurerequest.detail = src->xconfigurerequest.detail;
            dst->xconfigurerequest.value_mask = from_ulong(src->xconfigurerequest.value_mask);
            break;
        case XEVT_GravityNotify:
            dst->xgravity.window = from_ulong(src->xgravity.window);
            dst->xgravity.x = src->xgravity.x;
            dst->xgravity.y = src->xgravity.y;
            break;
        case XEVT_ResizeRequest:
            dst->xresizerequest.width = src->xresizerequest.width;
            dst->xresizerequest.height = src->xresizerequest.height;
            break;
        case XEVT_CirculateNotify:
            dst->xcirculate.window = from_ulong(src->xcirculate.window);
            dst->xcirculate.place = src->xcirculate.place;
            break;
        case XEVT_CirculateRequest:
            dst->xcirculaterequest.window = from_ulong(src->xcirculaterequest.window);
            dst->xcirculaterequest.place = src->xcirculaterequest.place;
            break;
        case XEVT_PropertyNotify:
            dst->xproperty.atom = from_ulong(src->xproperty.atom);
            dst->xproperty.time = from_ulong(src->xproperty.time);
            dst->xproperty.state = src->xproperty.state;
            break;
        case XEVT_SelectionClear:
            dst->xselectionclear.selection = from_ulong(src->xselectionclear.selection);
            dst->xselectionclear.time = from_ulong(src->xselectionclear.time);
            break;
        case XEVT_SelectionRequest:
            dst->xselectionrequest.requestor = from_ulong(src->xselectionrequest.requestor);
            dst->xselectionrequest.selection = from_ulong(src->xselectionrequest.selection);
            dst->xselectionrequest.target = from_ulong(src->xselectionrequest.target);
            dst->xselectionrequest.property = from_ulong(src->xselectionrequest.property);
            dst->xselectionrequest.time = from_ulong(src->xselectionrequest.time);
            break;
        case XEVT_SelectionNotify:
            dst->xselection.selection = from_ulong(src->xselection.selection);
            dst->xselection.target = from_ulong(src->xselection.target);
            dst->xselection.property = from_ulong(src->xselection.property);
            dst->xselection.time = from_ulong(src->xselection.time);
            break;
        case XEVT_ColormapNotify:
            dst->xcolormap.colormap = from_ulong(src->xcolormap.colormap);
            dst->xcolormap.c_new = src->xcolormap.c_new;
            dst->xcolormap.state = src->xcolormap.state;
            break;
        case XEVT_ClientMessage:
            dst->xclient.message_type = from_ulong(src->xclient.message_type);
            dst->xclient.format = src->xclient.format;
            if(src->xclient.format==32)
                for(int i=0; i<5; ++i) dst->xclient.data.l[i] = from_ulong(src->xclient.data.l[i]);
            else
                memcpy(dst->xclient.data.b, src->xclient.data.b, 20);
            break;
        case XEVT_MappingNotify:
            dst->xmapping.request = src->xmapping.request;
            dst->xmapping.first_keycode = src->xmapping.first_keycode;
            dst->xmapping.count = src->xmapping.count;
            break;
        case XEVT_GenericEvent:
            dst->xcookie.extension = src->xcookie.extension;
            dst->xcookie.evtype = src->xcookie.evtype;
            dst->xcookie.cookie = src->xcookie.cookie;
            dst->xcookie.data = from_ptrv(src->xcookie.data);
            break;

        default: {
            register_events_t* head = register_events_head;
            while(head) {
                if(type>=head->start_event && type<=head->end_event) {
                    for(int i=0; i<head->n; ++i)
                        if(type==head->events[i].event) {
                            head->events[i].to64(dst, src);
                            return;
                        }
                }
                head = head->next;
            }
            printf_log(LOG_INFO, "Warning, unsupported 32bits (un)XEvent type=%d\n", type);
        }
    }
}

void convert_XErrorEvent_to_32(void* d, void* s)
{
    my_XErrorEvent_t* src = s;
    my_XErrorEvent_32_t* dst = d;
    dst->type = src->type;
    dst->display = to_ptrv(FindDisplay(src->display));
    dst->resourceid = to_ulong(src->resourceid);
    dst->serial = to_ulong(src->serial);
    dst->error_code = src->error_code;
    dst->request_code = src->request_code;
    dst->minor_code = src->minor_code;
}
void convert_XErrorEvent_to_64(void* d, void* s)
{
    my_XErrorEvent_32_t* src = s;
    my_XErrorEvent_t* dst = d;
    dst->minor_code = src->minor_code;
    dst->request_code = src->request_code;
    dst->error_code = src->error_code;
    dst->serial = from_ulong(src->serial);
    dst->resourceid = from_ulong(src->resourceid);
    dst->display = getDisplay(from_ptrv(src->display));
    dst->type = src->type;
}

void convert_XDeviceKeyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XDeviceKeyEvent_t* src = (my_XDeviceKeyEvent_t*)s;
    my_XDeviceKeyEvent_32_t* dst = (my_XDeviceKeyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->deviceid = to_ulong(src->deviceid);
    dst->root = to_ulong(src->root);
    dst->subwindow = to_ulong(src->subwindow);
    dst->time = to_ulong(src->time);
    dst->x = src->x;
    dst->y = src->y;
    dst->x_root = src->x_root;
    dst->y_root = src->y_root;
    dst->state = src->state;
    dst->keycode = src->keycode;
    dst->same_screen = src->same_screen;
    dst->device_state = src->device_state;
    dst->axes_count = src->axes_count;
    dst->first_axis = src->first_axis;
    dst->axis_data[0] = src->axis_data[0];
    dst->axis_data[1] = src->axis_data[1];
    dst->axis_data[2] = src->axis_data[2];
    dst->axis_data[3] = src->axis_data[3];
    dst->axis_data[4] = src->axis_data[4];
    dst->axis_data[5] = src->axis_data[5];
}
void convert_XDeviceKeyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XDeviceKeyEvent_32_t* src = (my_XDeviceKeyEvent_32_t*)s;
    my_XDeviceKeyEvent_t* dst = (my_XDeviceKeyEvent_t*)d;

    dst->axis_data[5] = src->axis_data[5];
    dst->axis_data[4] = src->axis_data[4];
    dst->axis_data[3] = src->axis_data[3];
    dst->axis_data[2] = src->axis_data[2];
    dst->axis_data[1] = src->axis_data[1];
    dst->axis_data[0] = src->axis_data[0];
    dst->first_axis = src->first_axis;
    dst->axes_count = src->axes_count;
    dst->device_state = src->device_state;
    dst->same_screen = src->same_screen;
    dst->keycode = src->keycode;
    dst->state = src->state;
    dst->y_root = src->y_root;
    dst->x_root = src->x_root;
    dst->y = src->y;
    dst->x = src->x;
    dst->time = from_ulong(src->time);
    dst->subwindow = from_ulong(src->subwindow);
    dst->root = from_ulong(src->root);
    dst->deviceid = from_ulong(src->deviceid);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XDeviceMotionEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XDeviceMotionEvent_t* src = (my_XDeviceMotionEvent_t*)s;
    my_XDeviceMotionEvent_32_t* dst = (my_XDeviceMotionEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->deviceid = to_ulong(src->deviceid);
    dst->root = to_ulong(src->root);
    dst->subwindow = to_ulong(src->subwindow);
    dst->time = to_ulong(src->time);
    dst->x = src->x;
    dst->y = src->y;
    dst->x_root = src->x_root;
    dst->y_root = src->y_root;
    dst->state = src->state;
    dst->is_hint = src->is_hint;
    dst->same_screen = src->same_screen;
    dst->device_state = src->device_state;
    dst->axes_count = src->axes_count;
    dst->first_axis = src->first_axis;
    dst->axis_data[0] = src->axis_data[0];
    dst->axis_data[1] = src->axis_data[1];
    dst->axis_data[2] = src->axis_data[2];
    dst->axis_data[3] = src->axis_data[3];
    dst->axis_data[4] = src->axis_data[4];
    dst->axis_data[5] = src->axis_data[5];
}
void convert_XDeviceMotionEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XDeviceMotionEvent_32_t* src = (my_XDeviceMotionEvent_32_t*)s;
    my_XDeviceMotionEvent_t* dst = (my_XDeviceMotionEvent_t*)d;

    dst->axis_data[5] = src->axis_data[5];
    dst->axis_data[4] = src->axis_data[4];
    dst->axis_data[3] = src->axis_data[3];
    dst->axis_data[2] = src->axis_data[2];
    dst->axis_data[1] = src->axis_data[1];
    dst->axis_data[0] = src->axis_data[0];
    dst->first_axis = src->first_axis;
    dst->axes_count = src->axes_count;
    dst->device_state = src->device_state;
    dst->same_screen = src->same_screen;
    dst->is_hint = src->is_hint;
    dst->state = src->state;
    dst->y_root = src->y_root;
    dst->x_root = src->x_root;
    dst->y = src->y;
    dst->x = src->x;
    dst->time = from_ulong(src->time);
    dst->subwindow = from_ulong(src->subwindow);
    dst->root = from_ulong(src->root);
    dst->deviceid = from_ulong(src->deviceid);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XDeviceFocusEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XDeviceFocusChangeEvent_t* src = (my_XDeviceFocusChangeEvent_t*)s;
    my_XDeviceFocusChangeEvent_32_t* dst = (my_XDeviceFocusChangeEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->deviceid = to_ulong(src->deviceid);
    dst->mode = src->mode;
    dst->detail = src->detail;
    dst->time = to_ulong(src->time);
}
void convert_XDeviceFocusEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XDeviceFocusChangeEvent_32_t* src = (my_XDeviceFocusChangeEvent_32_t*)s;
    my_XDeviceFocusChangeEvent_t* dst = (my_XDeviceFocusChangeEvent_t*)d;

    dst->time = from_ulong(src->time);
    dst->detail = src->detail;
    dst->mode = src->mode;
    dst->deviceid = from_ulong(src->deviceid);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XProximityNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XProximityNotifyEvent_t* src = (my_XProximityNotifyEvent_t*)s;
    my_XProximityNotifyEvent_32_t* dst = (my_XProximityNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->deviceid = to_ulong(src->deviceid);
    dst->root = to_ulong(src->root);
    dst->subwindow = to_ulong(src->subwindow);
    dst->time = to_ulong(src->time);
    dst->x = src->x;
    dst->y = src->y;
    dst->x_root = src->x_root;
    dst->y_root = src->y_root;
    dst->state = src->state;
    dst->same_screen = src->same_screen;
    dst->device_state = src->device_state;
    dst->axes_count = src->axes_count;
    dst->first_axis = src->first_axis;
    dst->axis_data[0] = src->axis_data[0];
    dst->axis_data[1] = src->axis_data[1];
    dst->axis_data[2] = src->axis_data[2];
    dst->axis_data[3] = src->axis_data[3];
    dst->axis_data[4] = src->axis_data[4];
    dst->axis_data[5] = src->axis_data[5];
}
void convert_XProximityNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XProximityNotifyEvent_32_t* src = (my_XProximityNotifyEvent_32_t*)s;
    my_XProximityNotifyEvent_t* dst = (my_XProximityNotifyEvent_t*)d;

    dst->axis_data[5] = src->axis_data[5];
    dst->axis_data[4] = src->axis_data[4];
    dst->axis_data[3] = src->axis_data[3];
    dst->axis_data[2] = src->axis_data[2];
    dst->axis_data[1] = src->axis_data[1];
    dst->axis_data[0] = src->axis_data[0];
    dst->first_axis = src->first_axis;
    dst->axes_count = src->axes_count;
    dst->device_state = src->device_state;
    dst->same_screen = src->same_screen;
    dst->state = src->state;
    dst->y_root = src->y_root;
    dst->x_root = src->x_root;
    dst->y = src->y;
    dst->x = src->x;
    dst->time = from_ulong(src->time);
    dst->subwindow = from_ulong(src->subwindow);
    dst->root = from_ulong(src->root);
    dst->deviceid = from_ulong(src->deviceid);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XDeviceStateNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XDeviceStateNotifyEvent_t* src = (my_XDeviceStateNotifyEvent_t*)s;
    my_XDeviceStateNotifyEvent_32_t* dst = (my_XDeviceStateNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->deviceid = to_ulong(src->deviceid);
    dst->time = to_ulong(src->time);
    memmove(dst->data, src->data, 64);
}
void convert_XDeviceStateNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XDeviceStateNotifyEvent_32_t* src = (my_XDeviceStateNotifyEvent_32_t*)s;
    my_XDeviceStateNotifyEvent_t* dst = (my_XDeviceStateNotifyEvent_t*)d;

    memmove(dst->data, src->data, 64);
    dst->time = from_ulong(src->time);
    dst->deviceid = from_ulong(src->deviceid);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XDeviceMappingEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XDeviceMappingEvent_t* src = (my_XDeviceMappingEvent_t*)s;
    my_XDeviceMappingEvent_32_t* dst = (my_XDeviceMappingEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->deviceid = to_ulong(src->deviceid);
    dst->time = to_ulong(src->time);
    dst->request = src->request;
    dst->first_keycode = src->first_keycode;
    dst->count = src->count;
}
void convert_XDeviceMappingEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XDeviceMappingEvent_32_t* src = (my_XDeviceMappingEvent_32_t*)s;
    my_XDeviceMappingEvent_t* dst = (my_XDeviceMappingEvent_t*)d;

    dst->count = src->count;
    dst->first_keycode = src->first_keycode;
    dst->request = src->request;
    dst->time = from_ulong(src->time);
    dst->deviceid = from_ulong(src->deviceid);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XChangeDeviceNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XChangeDeviceNotifyEvent_t* src = (my_XChangeDeviceNotifyEvent_t*)s;
    my_XChangeDeviceNotifyEvent_32_t* dst = (my_XChangeDeviceNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->deviceid = to_ulong(src->deviceid);
    dst->time = to_ulong(src->time);
    dst->request = src->request;
}
void convert_XChangeDeviceNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XChangeDeviceNotifyEvent_32_t* src = (my_XChangeDeviceNotifyEvent_32_t*)s;
    my_XChangeDeviceNotifyEvent_t* dst = (my_XChangeDeviceNotifyEvent_t*)d;

    dst->request = src->request;
    dst->time = from_ulong(src->time);
    dst->deviceid = from_ulong(src->deviceid);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XDevicePresenceNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XDevicePresenceNotifyEvent_t* src = (my_XDevicePresenceNotifyEvent_t*)s;
    my_XDevicePresenceNotifyEvent_32_t* dst = (my_XDevicePresenceNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->time = to_ulong(src->time);
    dst->devchange = src->devchange;
    dst->deviceid = to_ulong(src->deviceid);
    dst->control = to_ulong(src->control);
}
void convert_XDevicePresenceNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XDevicePresenceNotifyEvent_32_t* src = (my_XDevicePresenceNotifyEvent_32_t*)s;
    my_XDevicePresenceNotifyEvent_t* dst = (my_XDevicePresenceNotifyEvent_t*)d;

    dst->control = from_ulong(src->control);
    dst->deviceid = from_ulong(src->deviceid);
    dst->devchange = src->devchange;
    dst->time = from_ulong(src->time);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XDevicePropertyNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XDevicePropertyNotifyEvent_t* src = (my_XDevicePropertyNotifyEvent_t*)s;
    my_XDevicePropertyNotifyEvent_32_t* dst = (my_XDevicePropertyNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->time = to_ulong(src->time);
    dst->deviceid = to_ulong(src->deviceid);
    dst->atom = to_ulong(src->atom);
    dst->state = src->state;
}
void convert_XDevicePropertyNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XDevicePropertyNotifyEvent_32_t* src = (my_XDevicePropertyNotifyEvent_32_t*)s;
    my_XDevicePropertyNotifyEvent_t* dst = (my_XDevicePropertyNotifyEvent_t*)d;

    dst->state = src->state;
    dst->atom = from_ulong(src->atom);
    dst->deviceid = from_ulong(src->deviceid);
    dst->time = from_ulong(src->time);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void register_XDevice_events(my_XDevice_t* a)
{
    if(!a) return;
    // search if device is already in list
    register_events_t* head = register_events_head;
    while(head) {
        if(head->id == a)
            return; // found, nothing to do....
        head = head->next;
    }
    // counts events
    int n=0;
    for(int i=0; i<a->num_classes; ++i)
        switch(a->classes[i].input_class) {
            case 0: n+=2; break; //KeyClass
            case 1: n+=2; break; //ButtonClass
            case 2: n+=1; break; //ValuatorClass
            case 5: n+=2; break; //FocusClass
            case 4: n+=2; break; //ProximityClass
            case 6: n+=4; break; //OtherClass
        }
    // check if there is something to notify
    if(!n) return;
    // create a new event list
    register_events_t* events = box_malloc(sizeof(register_events_t)+n*sizeof(reg_event_t));
    events->id = a;
    events->n = n;
    events->events = (reg_event_t*)(events+1);
    n = 0;
    for(int i=0; i<a->num_classes; ++i) {
        switch(a->classes[i].input_class) {
            case 0: //KeyClass
                events->events[n].event = a->classes[i].event_type_base+0;
                events->events[n].to32 = convert_XDeviceKeyEvent_to_32;
                events->events[n].to64 = convert_XDeviceKeyEvent_to_64;
                ++n;
                events->events[n].event = a->classes[i].event_type_base+1;
                events->events[n].to32 = convert_XDeviceKeyEvent_to_32;
                events->events[n].to64 = convert_XDeviceKeyEvent_to_64;
                ++n;
                break;  
            case 1: //ButtonClass
                events->events[n].event = a->classes[i].event_type_base+0;
                events->events[n].to32 = convert_XDeviceKeyEvent_to_32;
                events->events[n].to64 = convert_XDeviceKeyEvent_to_64;
                ++n;
                events->events[n].event = a->classes[i].event_type_base+1;
                events->events[n].to32 = convert_XDeviceKeyEvent_to_32;
                events->events[n].to64 = convert_XDeviceKeyEvent_to_64;
                ++n;
                break;
            case 2: //ValuatorClass
                events->events[n].event = a->classes[i].event_type_base+0;
                events->events[n].to32 = convert_XDeviceMotionEvent_to_32;
                events->events[n].to64 = convert_XDeviceMotionEvent_to_64;
                ++n;
                break;
            case 5: //FocusClass
                events->events[n].event = a->classes[i].event_type_base+0;
                events->events[n].to32 = convert_XDeviceFocusEvent_to_32;
                events->events[n].to64 = convert_XDeviceFocusEvent_to_64;
                ++n;
                events->events[n].event = a->classes[i].event_type_base+1;
                events->events[n].to32 = convert_XDeviceFocusEvent_to_32;
                events->events[n].to64 = convert_XDeviceFocusEvent_to_64;
                ++n;
                break;
            case 4: //ProximityClass
                events->events[n].event = a->classes[i].event_type_base+0;
                events->events[n].to32 = convert_XProximityNotifyEvent_to_32;
                events->events[n].to64 = convert_XProximityNotifyEvent_to_64;
                ++n;
                events->events[n].event = a->classes[i].event_type_base+1;
                events->events[n].to32 = convert_XProximityNotifyEvent_to_32;
                events->events[n].to64 = convert_XProximityNotifyEvent_to_64;
                ++n;
                break;
            case 6: //OtherClass
                events->events[n].event = a->classes[i].event_type_base+0;
                events->events[n].to32 = convert_XDeviceStateNotifyEvent_to_32;
                events->events[n].to64 = convert_XDeviceStateNotifyEvent_to_64;
                ++n;
                events->events[n].event = a->classes[i].event_type_base+1;
                events->events[n].to32 = convert_XDeviceMappingEvent_to_32;
                events->events[n].to64 = convert_XDeviceMappingEvent_to_64;
                ++n;
                events->events[n].event = a->classes[i].event_type_base+2;
                events->events[n].to32 = convert_XChangeDeviceNotifyEvent_to_32;
                events->events[n].to64 = convert_XChangeDeviceNotifyEvent_to_64;
                ++n;
                //+3 would be DeviceKeyStateNotify
                //+4 wpuld be DeviceButtonStateNotify
                //+5 would be DevicePresenceNotify
                events->events[n].event = a->classes[i].event_type_base+6;
                events->events[n].to32 = convert_XDevicePropertyNotifyEvent_to_32;
                events->events[n].to64 = convert_XDevicePropertyNotifyEvent_to_64;
                ++n;
                break;
        }
    }
    events->start_event = events->end_event = events->events[0].event;
    for(int i=1; i<n; ++i) {
        if(events->start_event>events->events[i].event) events->start_event = events->events[i].event;
        if(events->end_event<events->events[i].event) events->end_event = events->events[i].event;
    }
    events->next = register_events_head;
    register_events_head = events;
}
void unregister_XDevice_events(my_XDevice_t* a)
{
    if(!a) return;
    register_events_t* prev = NULL;
    register_events_t* head = register_events_head;
    while(head) {
        if(head->id == a) {
            if(!prev)
                register_events_head = head->next;
            else
                prev->next = head->next;
            box_free(head);
            return;
        }
        prev = head;
        head = head->next;
    }
}

void convert_XFixesSelectionNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XFixesSelectionNotifyEvent_t* src = (my_XFixesSelectionNotifyEvent_t*)s;
    my_XFixesSelectionNotifyEvent_32_t* dst = (my_XFixesSelectionNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->subtype = src->subtype;
    dst->owner = to_ulong(src->owner);
    dst->selection = to_ulong(src->selection);
    dst->timestamp = to_ulong(src->timestamp);
    dst->selection_timestamp = to_ulong(src->selection_timestamp);
}
void convert_XFixesSelectionNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XFixesSelectionNotifyEvent_32_t* src = (my_XFixesSelectionNotifyEvent_32_t*)s;
    my_XFixesSelectionNotifyEvent_t* dst = (my_XFixesSelectionNotifyEvent_t*)d;

    dst->selection_timestamp = from_ulong(src->selection_timestamp);
    dst->timestamp = from_ulong(src->timestamp);
    dst->selection = from_ulong(src->selection);
    dst->owner = from_ulong(src->owner);
    dst->subtype = src->subtype;
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XFixesCursorNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XFixesCursorNotifyEvent_t* src = (my_XFixesCursorNotifyEvent_t*)s;
    my_XFixesCursorNotifyEvent_32_t* dst = (my_XFixesCursorNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->subtype = src->subtype;
    dst->cursor_serial = to_ulong(src->cursor_serial);
    dst->timestamp = to_ulong(src->timestamp);
    dst->cursor_name = to_ulong(src->cursor_name);
}
void convert_XFixesCursorNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XFixesCursorNotifyEvent_32_t* src = (my_XFixesCursorNotifyEvent_32_t*)s;
    my_XFixesCursorNotifyEvent_t* dst = (my_XFixesCursorNotifyEvent_t*)d;

    dst->cursor_serial = from_ulong(src->cursor_serial);
    dst->timestamp = from_ulong(src->timestamp);
    dst->cursor_name = from_ulong(src->cursor_name);
    dst->subtype = src->subtype;
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}

void register_XFixes_events(int event_base)
{
    void* a = (void*)1LL;
    // search if device is already in list
    register_events_t* head = register_events_head;
    while(head) {
        if(head->id == a)
            return; // found, nothing to do....
        head = head->next;
    }
    int n = 2;  // 2 events to register!
    // create a new event list
    register_events_t* events = box_malloc(sizeof(register_events_t)+n*sizeof(reg_event_t));
    events->id = a;
    events->n = n;
    events->events = (reg_event_t*)(events+1);

    events->events[0].event = event_base+0;
    events->events[0].to32 = convert_XFixesSelectionNotifyEvent_to_32;
    events->events[0].to64 = convert_XFixesSelectionNotifyEvent_to_64;
    events->events[1].event = event_base+1;
    events->events[1].to32 = convert_XFixesCursorNotifyEvent_to_32;
    events->events[1].to64 = convert_XFixesCursorNotifyEvent_to_64;

    events->start_event = events->end_event = events->events[0].event;
    events->next = register_events_head;
    register_events_head = events;
}
void unregister_XFixes_events()
{
    void* a = (void*)1LL;
    register_events_t* prev = NULL;
    register_events_t* head = register_events_head;
    while(head) {
        if(head->id == a) {
            if(!prev)
                register_events_head = head->next;
            else
                prev->next = head->next;
            box_free(head);
            return;
        }
        prev = head;
        head = head->next;
    }
}

void convert_XRRScreenChangeNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XRRScreenChangeNotifyEvent_t* src = (my_XRRScreenChangeNotifyEvent_t*)s;
    my_XRRScreenChangeNotifyEvent_32_t* dst = (my_XRRScreenChangeNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    dst->root = to_ulong(src->root);
    dst->timestamp = to_ulong(src->timestamp);
    dst->config_timestamp = to_ulong(src->config_timestamp);
    dst->size_index = src->size_index;
    dst->subpixel_order = src->subpixel_order;
    dst->rotation = src->rotation;
    dst->width = src->width;
    dst->height = src->height;
    dst->mwidth = src->mwidth;
    dst->mheight = src->mheight;
}
void convert_XRRScreenChangeNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XRRScreenChangeNotifyEvent_32_t* src = (my_XRRScreenChangeNotifyEvent_32_t*)s;
    my_XRRScreenChangeNotifyEvent_t* dst = (my_XRRScreenChangeNotifyEvent_t*)d;

    dst->mheight = src->mheight;
    dst->mwidth = src->mwidth;
    dst->height = src->height;
    dst->width = src->width;
    dst->rotation = src->rotation;
    dst->subpixel_order = src->subpixel_order;
    dst->size_index = src->size_index;
    dst->config_timestamp = from_ulong(src->config_timestamp);
    dst->timestamp = from_ulong(src->timestamp);
    dst->root = from_ulong(src->root);
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}
void convert_XRRNotifyEvent_to_32(my_XEvent_32_t* d, my_XEvent_t* s)
{
    my_XRRNotifyEvent_t* src = (my_XRRNotifyEvent_t*)s;
    my_XRRNotifyEvent_32_t* dst = (my_XRRNotifyEvent_32_t*)d;

    //dst->type = src->type;
    //dst->serial = src->serial;
    //dst->send_event = src->send_event;
    //dst->display = src->display;
    //dst->window = src->window;
    int subtype = src->subtype;
    dst->subtype = src->subtype;
    switch (subtype) {
        case 0: {
            my_XRROutputChangeNotifyEvent_t* src = (my_XRROutputChangeNotifyEvent_t*)s;
            my_XRROutputChangeNotifyEvent_32_t* dst = (my_XRROutputChangeNotifyEvent_32_t*)d;
            dst->output = to_long(src->output);
            dst->crtc = to_long(src->crtc);
            dst->mode = to_long(src->mode);
            dst->rotation = src->rotation;
            dst->connection = src->connection;
            dst->subpixel_order = src->subpixel_order;
        } break;
        case 1: {
            my_XRRCrtcChangeNotifyEvent_t* src = (my_XRRCrtcChangeNotifyEvent_t*)s;
            my_XRRCrtcChangeNotifyEvent_32_t* dst = (my_XRRCrtcChangeNotifyEvent_32_t*)d;
            dst->crtc = to_ulong(src->crtc);
            dst->mode = to_ulong(src->mode);
            dst->rotation = src->rotation;
            dst->x = src->x;
            dst->y = src->y;
            dst->width = src->width;
            dst->height = src->height;
        } break;
        case 2: {
            my_XRROutputPropertyNotifyEvent_t* src = (my_XRROutputPropertyNotifyEvent_t*)s;
            my_XRROutputPropertyNotifyEvent_32_t* dst = (my_XRROutputPropertyNotifyEvent_32_t*)d;
            dst->output = to_ulong(src->output);
            dst->property = to_ulong(src->property);
            dst->timestamp = to_ulong(src->timestamp);
            dst->state = src->state;
        } break;
        case 3: {
            my_XRRProviderChangeNotifyEvent_t* src = (my_XRRProviderChangeNotifyEvent_t*)s;
            my_XRRProviderChangeNotifyEvent_32_t* dst = (my_XRRProviderChangeNotifyEvent_32_t*)d;
            dst->provider = to_ulong(src->provider);
            dst->timestamp = to_ulong(src->timestamp);
            dst->current_role = src->current_role;
        } break;
        case 4: {
            my_XRRProviderPropertyNotifyEvent_t* src = (my_XRRProviderPropertyNotifyEvent_t*)s;
            my_XRRProviderPropertyNotifyEvent_32_t* dst = (my_XRRProviderPropertyNotifyEvent_32_t*)d;
            dst->provider = to_ulong(src->provider);
            dst->property = to_ulong(src->property);
            dst->timestamp = to_ulong(src->timestamp);
            dst->state = src->state;
        } break;
        case 5: {
            my_XRRResourceChangeNotifyEvent_t* src = (my_XRRResourceChangeNotifyEvent_t*)s;
            my_XRRResourceChangeNotifyEvent_32_t* dst = (my_XRRResourceChangeNotifyEvent_32_t*)d;
            dst->timestamp = to_ulong(src->timestamp);
        } break;
    }
}
void convert_XRRNotifyEvent_to_64(my_XEvent_t* d, my_XEvent_32_t* s)
{
    my_XRRNotifyEvent_32_t* src = (my_XRRNotifyEvent_32_t*)s;
    my_XRRNotifyEvent_t* dst = (my_XRRNotifyEvent_t*)d;
    int subtype = src->subtype;
    switch (subtype) {
        case 0: {
            my_XRROutputChangeNotifyEvent_32_t* src = (my_XRROutputChangeNotifyEvent_32_t*)s;
            my_XRROutputChangeNotifyEvent_t* dst = (my_XRROutputChangeNotifyEvent_t*)d;
            dst->output = from_long(src->output);
            dst->crtc = from_long(src->crtc);
            dst->mode = from_long(src->mode);
            dst->rotation = src->rotation;
            dst->connection = src->connection;
            dst->subpixel_order = src->subpixel_order;
        } break;
        case 1: {
            my_XRRCrtcChangeNotifyEvent_32_t* src = (my_XRRCrtcChangeNotifyEvent_32_t*)s;
            my_XRRCrtcChangeNotifyEvent_t* dst = (my_XRRCrtcChangeNotifyEvent_t*)d;
            dst->crtc = from_ulong(src->crtc);
            dst->mode = from_ulong(src->mode);
            dst->rotation = src->rotation;
            dst->x = src->x;
            dst->y = src->y;
            dst->width = src->width;
            dst->height = src->height;
        } break;
        case 2: {
            my_XRROutputPropertyNotifyEvent_32_t* src = (my_XRROutputPropertyNotifyEvent_32_t*)s;
            my_XRROutputPropertyNotifyEvent_t* dst = (my_XRROutputPropertyNotifyEvent_t*)d;
            dst->output = from_ulong(src->output);
            dst->property = from_ulong(src->property);
            dst->timestamp = from_ulong(src->timestamp);
            dst->state = src->state;
        } break;
        case 3: {
            my_XRRProviderChangeNotifyEvent_32_t* src = (my_XRRProviderChangeNotifyEvent_32_t*)s;
            my_XRRProviderChangeNotifyEvent_t* dst = (my_XRRProviderChangeNotifyEvent_t*)d;
            dst->provider = from_ulong(src->provider);
            dst->timestamp = from_ulong(src->timestamp);
            dst->current_role = src->current_role;
        } break;
        case 4: {
            my_XRRProviderPropertyNotifyEvent_32_t* src = (my_XRRProviderPropertyNotifyEvent_32_t*)s;
            my_XRRProviderPropertyNotifyEvent_t* dst = (my_XRRProviderPropertyNotifyEvent_t*)d;
            dst->provider = from_ulong(src->provider);
            dst->property = from_ulong(src->property);
            dst->timestamp = from_ulong(src->timestamp);
            dst->state = src->state;
        } break;
        case 5: {
            my_XRRResourceChangeNotifyEvent_32_t* src = (my_XRRResourceChangeNotifyEvent_32_t*)s;
            my_XRRResourceChangeNotifyEvent_t* dst = (my_XRRResourceChangeNotifyEvent_t*)d;
            dst->timestamp = from_ulong(src->timestamp);
        } break;
    }
    dst->subtype = src->subtype;
    //dst->window = src->window;
    //dst->display = src->display;
    //dst->send_event = src->send_event;
    //dst->serial = src->serial;
    //dst->type = src->type;
}

void register_XRandR_events(int event_base)
{
    void* a = (void*)2LL;
    // search if device is already in list
    register_events_t* head = register_events_head;
    while(head) {
        if(head->id == a)
            return; // found, nothing to do....
        head = head->next;
    }
    int n = 2;  // 2 events to register!, but second one as 6+1 subtypes
    // create a new event list
    register_events_t* events = box_malloc(sizeof(register_events_t)+n*sizeof(reg_event_t));
    events->id = a;
    events->n = n;
    events->events = (reg_event_t*)(events+1);

    events->events[0].event = event_base+0;
    events->events[0].to32 = convert_XRRScreenChangeNotifyEvent_to_32;
    events->events[0].to64 = convert_XRRScreenChangeNotifyEvent_to_64;
    events->events[1].event = event_base+1;
    events->events[1].to32 = convert_XRRNotifyEvent_to_32;
    events->events[1].to64 = convert_XRRNotifyEvent_to_64;

    events->start_event = events->events[0].event;
    events->end_event = events->events[1].event;
    events->next = register_events_head;
    register_events_head = events;
}
void unregister_XRandR_events()
{
    void* a = (void*)2LL;
    register_events_t* prev = NULL;
    register_events_t* head = register_events_head;
    while(head) {
        if(head->id == a) {
            if(!prev)
                register_events_head = head->next;
            else
                prev->next = head->next;
            box_free(head);
            return;
        }
        prev = head;
        head = head->next;
    }
}
