boxes, attractors and everything
This commit is contained in:
88
initcairo.c
88
initcairo.c
@@ -12,8 +12,28 @@ static Bool alwaysTruePredicate(Display *display, XEvent *event, XPointer arg)
|
||||
return true;
|
||||
}
|
||||
|
||||
int initCairo(int screen, int mask, int width, int height, const char *name, GraphicsInfo *info)
|
||||
void updateDimensions(DrawingContext *ctx)
|
||||
{
|
||||
double det = ctx->matrix.xx * ctx->matrix.yy - ctx->matrix.xy * ctx->matrix.yx;
|
||||
double cx = (double)ctx->width/2;
|
||||
double cy = (double)ctx->height/2;
|
||||
double r = 2*sqrt((cx*cx + cy*cy)/det); // this is not safe anymore if we have non-uniform scaling
|
||||
|
||||
// don't use cairo_device_to_user() since the matrix might not be our CTM yet
|
||||
cx -= ctx->matrix.x0;
|
||||
cy -= ctx->matrix.y0;
|
||||
ctx->center_x = ( ctx->matrix.yy * cx - ctx->matrix.xy * cy) / det;
|
||||
ctx->center_y = (- ctx->matrix.yx * cx + ctx->matrix.xx * cy) / det;
|
||||
ctx->radius = r;
|
||||
ctx->scalefactor = sqrt(det);
|
||||
}
|
||||
|
||||
GraphicsInfo *initCairo(int screen, int mask, int width, int height, const char *name)
|
||||
{
|
||||
GraphicsInfo *info = malloc(sizeof(GraphicsInfo));
|
||||
DrawingContext *ctx = malloc(sizeof(DrawingContext));
|
||||
info->context = ctx;
|
||||
|
||||
mask |= StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | PointerMotionMask;
|
||||
|
||||
info->display = XOpenDisplay(NULL);
|
||||
@@ -34,17 +54,18 @@ int initCairo(int screen, int mask, int width, int height, const char *name, Gra
|
||||
|
||||
XMapWindow(info->display, info->win);
|
||||
|
||||
info->sfc = cairo_xlib_surface_create(info->display, info->win, visual, width, height);
|
||||
cairo_xlib_surface_set_size(info->sfc, width, height);
|
||||
info->ctx = cairo_create(info->sfc);
|
||||
cairo_matrix_init_identity(&info->matrix);
|
||||
info->scalefactor = 1.0;
|
||||
info->surface = cairo_xlib_surface_create(info->display, info->win, visual, width, height);
|
||||
cairo_xlib_surface_set_size(info->surface, width, height);
|
||||
info->context->cairo = cairo_create(info->surface);
|
||||
cairo_matrix_init_identity(&info->context->matrix);
|
||||
info->context->width = width;
|
||||
info->context->height = height;
|
||||
|
||||
info->wm_delete_window = XInternAtom(info->display, "WM_DELETE_WINDOW", 0);
|
||||
info->wm_protocols = XInternAtom(info->display, "WM_PROTOCOLS", 0);
|
||||
XSetWMProtocols(info->display, info->win, &info->wm_delete_window, 1);
|
||||
|
||||
return 1;
|
||||
return info;
|
||||
}
|
||||
|
||||
void destroyCairo(GraphicsInfo *info)
|
||||
@@ -52,6 +73,8 @@ void destroyCairo(GraphicsInfo *info)
|
||||
XDestroyWindow(info->display, info->win);
|
||||
XFreeColormap(info->display, info->cmap);
|
||||
XCloseDisplay(info->display);
|
||||
free(info->context);
|
||||
free(info);
|
||||
}
|
||||
|
||||
void startTimer(GraphicsInfo *info)
|
||||
@@ -80,7 +103,7 @@ void waitUpdateTimer(GraphicsInfo *info)
|
||||
info->frames++;
|
||||
}
|
||||
|
||||
int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *, void*), void *data)
|
||||
int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(DrawingContext *))
|
||||
{
|
||||
int state;
|
||||
static int last_x, last_y;
|
||||
@@ -88,14 +111,15 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
|
||||
switch(ev->type) {
|
||||
|
||||
case Expose:
|
||||
draw(info->ctx, data);
|
||||
draw(info->context);
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
printf("ConfigureNotify Event, new dimensions: %d %d %d %d\n", ev->xconfigure.x, ev->xconfigure.y, ev->xconfigure.width, ev->xconfigure.height);
|
||||
info->width = ev->xconfigure.width;
|
||||
info->height = ev->xconfigure.height;
|
||||
cairo_xlib_surface_set_size(info->sfc, info->width, info->height);
|
||||
info->context->width = ev->xconfigure.width;
|
||||
info->context->height = ev->xconfigure.height;
|
||||
cairo_xlib_surface_set_size(info->surface, ev->xconfigure.width, ev->xconfigure.height);
|
||||
draw(info->context);
|
||||
break;
|
||||
|
||||
case KeyPress:
|
||||
@@ -111,20 +135,19 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
|
||||
cairo_matrix_translate(&transform, ev->xbutton.x, ev->xbutton.y);
|
||||
cairo_matrix_scale(&transform, 5.0/4.0, 5.0/4.0);
|
||||
cairo_matrix_translate(&transform, -ev->xbutton.x, -ev->xbutton.y);
|
||||
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
|
||||
info->scalefactor *= 5.0/4.0;
|
||||
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
|
||||
draw(info->context);
|
||||
} else if(ev->xbutton.button == 5) {
|
||||
cairo_matrix_t transform;
|
||||
cairo_matrix_init_identity(&transform);
|
||||
cairo_matrix_translate(&transform, ev->xbutton.x, ev->xbutton.y);
|
||||
cairo_matrix_scale(&transform, 4.0/5.0, 4.0/5.0);
|
||||
cairo_matrix_translate(&transform, -ev->xbutton.x, -ev->xbutton.y);
|
||||
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
|
||||
info->scalefactor *= 4.0/5.0;
|
||||
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
|
||||
draw(info->context);
|
||||
}
|
||||
last_x = ev->xbutton.x;
|
||||
last_y = ev->xbutton.y;
|
||||
draw(info->ctx, data);
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
@@ -135,26 +158,23 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
|
||||
cairo_matrix_t transform;
|
||||
cairo_matrix_init_identity(&transform);
|
||||
cairo_matrix_translate(&transform, dx, dy);
|
||||
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
|
||||
|
||||
printf("Button1Motion Event, dx: %d, dy: %d\n", dx, dy);
|
||||
|
||||
draw(info->ctx, data);
|
||||
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
|
||||
draw(info->context);
|
||||
} else if(ev->xmotion.state & Button1Mask && ev->xmotion.state & ShiftMask) {
|
||||
double width = (double) cairo_xlib_surface_get_width(info->surface);
|
||||
double height = (double) cairo_xlib_surface_get_height(info->surface);
|
||||
|
||||
double angle =
|
||||
atan2((double)ev->xmotion.y - (double)info->height/2, (double)ev->xmotion.x - (double)info->width/2)-
|
||||
atan2((double)last_y - (double)info->height/2, (double)last_x - (double)info->width/2);
|
||||
atan2((double)ev->xmotion.y - height/2, (double)ev->xmotion.x - width/2)-
|
||||
atan2((double)last_y - height/2, (double)last_x - width/2);
|
||||
|
||||
cairo_matrix_t transform;
|
||||
cairo_matrix_init_identity(&transform);
|
||||
cairo_matrix_translate(&transform, (double)info->width/2, (double)info->height/2);
|
||||
cairo_matrix_translate(&transform, width/2, height/2);
|
||||
cairo_matrix_rotate(&transform, angle);
|
||||
cairo_matrix_translate(&transform, -(double)info->width/2, -(double)info->height/2);
|
||||
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
|
||||
|
||||
printf("Button1Motion Event, angle: %f\n", angle);
|
||||
|
||||
draw(info->ctx, data);
|
||||
cairo_matrix_translate(&transform, -width/2, -height/2);
|
||||
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
|
||||
draw(info->context);
|
||||
}
|
||||
last_x = ev->xmotion.x;
|
||||
last_y = ev->xmotion.y;
|
||||
@@ -172,7 +192,7 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
|
||||
|
||||
}
|
||||
|
||||
int checkEvents(GraphicsInfo *info, int (*process)(GraphicsInfo*, XEvent*, void*), void (*draw)(cairo_t *, void*), void *data) // get any events from the queue and the server, process them if neccessary, quit if wanted
|
||||
int checkEvents(GraphicsInfo *info, int (*process)(GraphicsInfo*, XEvent*), void (*draw)(DrawingContext*)) // get any events from the queue and the server, process them if neccessary, quit if wanted
|
||||
{
|
||||
XEvent ev;
|
||||
|
||||
@@ -193,10 +213,10 @@ int checkEvents(GraphicsInfo *info, int (*process)(GraphicsInfo*, XEvent*, void*
|
||||
}
|
||||
} */
|
||||
|
||||
if(processStandardEvent(info, &ev, draw, data))
|
||||
if(processStandardEvent(info, &ev, draw))
|
||||
return 1;
|
||||
|
||||
if(process(info, &ev, data))
|
||||
if(process(info, &ev))
|
||||
return 1; // quit event queue and application
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user