Skip to content

Instantly share code, notes, and snippets.

@FloooD
Created August 19, 2012 07:55
Show Gist options
  • Save FloooD/3393459 to your computer and use it in GitHub Desktop.
Save FloooD/3393459 to your computer and use it in GitHub Desktop.
drag/drop something that follows the X cursor perfectly
#include <GL/glx.h>
#include <stdio.h>
#include <stdlib.h>
struct asdf {
Display *dpy;
Window win, root;
GLXFBConfig *fbc;
XVisualInfo *vi;
XSetWindowAttributes swa;
XWindowAttributes gwa;
GLXContext gc;
int w, h;
int bw, bh, bx, by, px, py;
int drag;
};
void resize(struct asdf *a, int w, int h)
{
glViewport(0, 0, w, h);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, w, 0.0, h, -1.0, 1.0);
a->by += h - a->h;
a->py += h - a->h;
a->w = w;
a->h = h;
}
void init(struct asdf *a, int w, int h)
{
a->dpy = XOpenDisplay(NULL);
if (a->dpy == NULL) {
printf("Could not open display");
exit(1);
}
int att[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
None
};
int n;
a->fbc = glXChooseFBConfig(a->dpy, DefaultScreen(a->dpy), att, &n);
a->vi = glXGetVisualFromFBConfig(a->dpy, a->fbc[0]);
a->root = DefaultRootWindow(a->dpy);
a->swa.colormap =
XCreateColormap(a->dpy, a->root, a->vi->visual, AllocNone);
a->swa.event_mask = ExposureMask | ButtonPressMask | Button1MotionMask;
a->win =
XCreateWindow(a->dpy, a->root, 0, 0, w, h, 0, a->vi->depth,
InputOutput, a->vi->visual, CWColormap | CWEventMask,
&(a->swa));
XMapWindow(a->dpy, a->win);
a->gc = glXCreateContext(a->dpy, a->vi, NULL, GL_TRUE);
glXMakeCurrent(a->dpy, a->win, a->gc);
glClearColor(0.0, 0.0, 0.0, 0.0);
resize(a, w, h);
a->bw = 40, a->bh = 40;
a->bx = 400, a->by = 300;
a->px = a->bx, a->py = a->by;
a->drag = 0;
}
void quit(struct asdf *a)
{
glXMakeCurrent(a->dpy, None, NULL);
glXDestroyContext(a->dpy, a->gc);
XDestroyWindow(a->dpy, a->win);
XCloseDisplay(a->dpy);
exit(0);
}
void ev_handle(struct asdf *a)
{
XEvent e;
while (XPending(a->dpy)) {
XNextEvent(a->dpy, &e);
switch (e.type) {
case Expose:
XGetWindowAttributes(a->dpy, a->win, &(a->gwa));
if (a->w != a->gwa.width || a->h != a->gwa.height)
resize(a, a->gwa.width, a->gwa.height);
break;
case MotionNotify:
if (!a->drag)
break;
if (e.xmotion.x < 0)
e.xmotion.x = 0;
else if (e.xmotion.x > a->w - 1)
e.xmotion.x = a->w - 1;
if (e.xmotion.y < 0)
e.xmotion.y = 0;
else if (e.xmotion.y > a->h - 1)
e.xmotion.y = a->h - 1;
a->bx += e.xmotion.x - a->px;
a->by -= e.xmotion.y - a->py;
a->px = e.xmotion.x;
a->py = e.xmotion.y;
break;
case ButtonPress:
if (e.xbutton.button != 1)
quit(a);
if (e.xbutton.x - a->bx <= a->bw
&& e.xbutton.x - a->bx >= 0
&& a->h - e.xbutton.y - a->by <= a->bh
&& a->h - e.xbutton.y - a->by >= 0) {
a->px = e.xbutton.x;
a->py = e.xbutton.y;
a->drag = 1;
} else {
a->drag = 0;
}
break;
default:
break;
}
}
}
void draw(struct asdf *a)
{
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINE_LOOP);
glVertex3f(a->bx + 0.5, a->by - 0.5, 0.0);
glVertex3f(a->bx + a->bw + 0.5, a->by - 0.5, 0.0);
glVertex3f(a->bx + a->bw + 0.5, a->by + a->bh - 0.5, 0.0);
glVertex3f(a->bx + 0.5, a->by + a->bh - 0.5, 0.0);
glEnd();
glFlush();
glClear(GL_COLOR_BUFFER_BIT);
}
int main(void)
{
struct asdf a;
init(&a, 800, 600);
#define get_t PFNGLXGETVIDEOSYNCSGIPROC
#define wait_t PFNGLXWAITVIDEOSYNCSGIPROC
get_t get_vsync = (get_t) glXGetProcAddress((const GLubyte *)"glXGetVideoSyncSGI");
wait_t wait_vsync = (wait_t) glXGetProcAddress((const GLubyte *)"glXWaitVideoSyncSGI");
unsigned vsc;
while (1) {
ev_handle(&a);
draw(&a);
get_vsync(&vsc);
wait_vsync(2, (vsc + 1) % 2, &vsc);
}
}
all:
gcc -O3 asdf.c -o asdf -lGL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment