* VMGL Project */
/*
* Copyright (c) 2006-2007 H. Andres Lagar-Cavilla <andreslc@cs.toronto.edu>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
*   1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*   2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*   3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <X11/Xlib.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xvlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdarg.h>

/* Pointer to the wrapped functions */
Display *(*orig_XOpenDisplay)(_Xconst char *) = NULL;
Window (*orig_XCreateWindow)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, 
			     int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*) = NULL;

static inline void *fetchFunc(const char *name, const char *library) {
    void *handle, *ret;
    
    fprintf(stderr,"Finding %s on %s\n", name, library);
    handle = dlopen(library, RTLD_LAZY);
    if (handle == NULL) {
        fprintf(stderr,"Couldn't get handle for library when interposing on %s\n", name);
        exit(-1);
    }
    dlerror();
    ret = dlsym(handle, name);
    if (dlerror() != NULL)  {
        fprintf(stderr,"Couldn't get %s symbol when interposing\n", name);
        exit(-1);
    }
    fprintf(stderr,"Found orig %s at %p\n", name, ret);
    /* This only works because the dl has been already loaded by the app and remains
       in the same chunk of memory */
    dlclose(handle);
    return ret;
}

Display *XOpenDisplay(_Xconst char *display_name) {
    struct DisplayNode *dpyNode;
    Display *dpy;

    if (!orig_XOpenDisplay) {
	*(void **) (&orig_XOpenDisplay) = fetchFunc("XOpenDisplay", "libX11.so");
	*(void **) (&orig_XCreateWindow) = fetchFunc("XCreateWindow", "libX11.so");
    }

    if (!(dpy = (*orig_XOpenDisplay)(display_name)))
	return NULL;
	
    return dpy;
}

Window XCreateWindow(Display *dpy, Window parent, int x, int y, unsigned int width, unsigned int height,
		     unsigned int border_width, int depth, unsigned int class, Visual *visual,
		     unsigned long valuemask, XSetWindowAttributes *attributes) {
    Window ret;
    ret = (*orig_XCreateWindow)(dpy, parent, x, y, width, height, border_width, depth, class, 
				visual, valuemask, attributes);
    
    fprintf(stderr, "XCreateWindow obtained XID %d\n", ret);
    return ret;
}
