/** 
 * @defgroup x11 x11
 * routines to handle X11 stuff
 * @{
 */

#include <stdio.h>
#include <string.h>
#include "include/prefs.h"
#include "include/util.h"
#include "include/x11.h"

static struct X11
{
    XWindowAttributes x_attr;
    Display *x_display;
    Window x_root;
    int x_screen, x_mousedown;
    /* amount of frames that passed since last x_keyPress() call */
    unsigned int last_key_down;          
}x11;

/************************** Module **************************/
/**
 * initialize X11-stuff
 */
int x_init()
{
    Window x_fromroot, x_tmpwin;
    int m_x, m_y, t_x, t_y;
    
    
    _VERBOSE1 printf("%s()\n", __func__);
    
    memset(&x11, 0, sizeof(struct X11));
        
    if((x11.x_display = XOpenDisplay(NULL)) == NULL) {
        _ERROR printf("Cannot open X-Display...\n");
        return -1;
    }

    x11.x_root = DefaultRootWindow(x11.x_display);
    
    XQueryPointer(x11.x_display, x11.x_root, &x_fromroot, &x_tmpwin,
                  &m_x, &m_y, &t_x, &t_y,
                  (unsigned int *) &t_x);
    
    XGetWindowAttributes(x11.x_display, x_fromroot, &(x11.x_attr));
    
    x11.x_screen = XScreenNumberOfScreen(x11.x_attr.screen);
    
    
    return 0;
}
 
/**
 * flush X
 */
void x_flush()
{
    XFlush(x11.x_display);    
}

/**
 * simulate keypress
 */
void x_keyPress(KeySym key)
{
    _VERBOSE3 printf("%s(): %d\n", __func__, (int) key);
    
    
    XTestFakeKeyEvent(x11.x_display, XKeysymToKeycode(x11.x_display, key),
                    True, CurrentTime);

    x_flush();
    
    XTestFakeKeyEvent(x11.x_display, XKeysymToKeycode(x11.x_display, key),
                    False, CurrentTime);
    
    x_flush();
}


/**
 * move mousepointer to position
 * @note don't forget to XFlush()
 */
void x_warp(int x, int y)
{
    XWarpPointer(x11.x_display, None,
         x11.x_root, 0, 0, 0, 0, x, y);    
    
}

/**
 * virtually press or release mouse-button...
 * @param pressed = 0 -> release; 1 = pressed;
 * @param buttonmask X11 buttonmask
 */
void x_click(int pressed, int buttonmask)
{
    XEvent event;

    memset(&event, 0, sizeof(event));

    /* check if button is already pressed/released */
    if(pressed != x11.x_mousedown) {
        
        event.xbutton.button = buttonmask;
        
        /* get button-mask */
        /*switch(button) {
            case 1:
                event.xbutton.button |= Button1Mask;
                break;
            
            case 2:
                event.xbutton.button |= Button2Mask;
                break;
            
            case 3:
                event.xbutton.button |= Button3Mask;
                break;
            
            case 4:
                event.xbutton.button |= Button4Mask;
                break;
            
            case 5:
                event.xbutton.button |= Button5Mask;
                break;
            
            default:
                printf("click(): Invalid mousebutton: %d\n", button);
                return;
        }*/
        
        event.xbutton.same_screen = True;
        event.type = ButtonPress;

        XQueryPointer(x11.x_display, RootWindow(x11.x_display,
                                         DefaultScreen(x11.x_display)),
                      &event.xbutton.root, &event.xbutton.window,
                      &event.xbutton.x_root, &event.xbutton.y_root,
                      &event.xbutton.x, &event.xbutton.y,
                      &event.xbutton.state);

        event.xbutton.subwindow = event.xbutton.window;

        while (event.xbutton.subwindow) {
            event.xbutton.window = event.xbutton.subwindow;
            XQueryPointer(x11.x_display,
                          event.xbutton.window,
                          &event.xbutton.root,
                          &event.xbutton.subwindow,
                          &event.xbutton.x_root,
                          &event.xbutton.y_root,
                          &event.xbutton.x, &event.xbutton.y,
                          &event.xbutton.state);
        }

        
        /*
         * press mousebutton 
         */
        if(pressed) {
            event.type = ButtonPress;
            _VERBOSE3 printf("%s(): mouse-down\n", __func__);
            x11.x_mousedown = 2;
        }
        /*
         * release mousebutton 
         */
        else {
            x11.x_mousedown--;
            if(x11.x_mousedown == 0) {
                event.type = ButtonRelease;
                event.xbutton.state = 0x100;
                _VERBOSE3 printf("%s(): mouse-up\n", __func__);
            }
            else {
                event.type = ButtonPress;
                _VERBOSE3 printf("%s(): mouse still down\n", __func__);
            }
        }

        XSendEvent(x11.x_display, PointerWindow, True, 0xfff, &event);
    }
    
    x_flush();
}





/** 
 * @} 
 */
