diff options
author | Joel Bosveld <Joel.Bosveld@gmail.com> | 2009-07-08 23:40:30 +0800 |
---|---|---|
committer | Joel Bosveld <Joel.Bosveld@gmail.com> | 2009-07-08 23:40:30 +0800 |
commit | 0e58db56833035717f5b664cf050ee06d7c576c1 (patch) | |
tree | b7606119cfdfca121800abfc519e986e5d6d3cd4 | |
parent | b590fe744332747def13e89dae9169bfbda24092 (diff) |
red: add a test for redirection
-rw-r--r-- | red/Makefile | 15 | ||||
-rw-r--r-- | red/red.c | 190 |
2 files changed, 205 insertions, 0 deletions
diff --git a/red/Makefile b/red/Makefile new file mode 100644 index 0000000..3a82a6b --- /dev/null +++ b/red/Makefile @@ -0,0 +1,15 @@ +PROJECT = red +OBJ = red.o + +C99 = gcc --std=gnu99 +CFLAGS = -Wall -g `pkg-config --cflags --libs x11 xcomposite xdamage cairo-xlib` + +$(PROJECT) : $(OBJ) + $(C99) $(CFLAGS) -o $(PROJECT) $(OBJ) + +%.o : %.c + $(C99) $(CFLAGS) -c $< -o $@ + +clean : + rm -f $(OBJ) + diff --git a/red/red.c b/red/red.c new file mode 100644 index 0000000..8cb0911 --- /dev/null +++ b/red/red.c @@ -0,0 +1,190 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xcomposite.h> +#include <X11/extensions/Xdamage.h> +#include <cairo-xlib.h> + +typedef struct +{ + Window id; + Window red; + int width, height; + cairo_surface_t *s; + int x,y; + Damage d; +} SubWindow; + +Display *d; +Window w; +SubWindow *sub; +int N_SUB; +Visual *v; + +static void +drawSubWindow (cairo_t *cr, SubWindow *s) +{ + cairo_set_source_surface (cr, s->s, s->x, s->y); + cairo_paint (cr); +} + +static void +drawWindow (cairo_t *cr) +{ + cairo_save (cr); + cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_restore (cr); + for (int i = 0; i < N_SUB; i++) + drawSubWindow (cr, &sub[i]); +} + +static Visual +*findArgbVisual () +{ + int screen = DefaultScreen (d); + XVisualInfo *xvi; + XVisualInfo temp; + int nvi; + int i; + XRenderPictFormat *format; + Visual *visual; + + temp.screen = screen; + temp.depth = 32; + temp.class = TrueColor; + + xvi = XGetVisualInfo (d, + VisualScreenMask | + VisualDepthMask | + VisualClassMask, + &temp, + &nvi); + if (!xvi) + return 0; + + visual = 0; + for (i = 0; i < nvi; i++) + { + format = XRenderFindVisualFormat (d, xvi[i].visual); + if (format->type == PictTypeDirect && format->direct.alphaMask) + { + visual = xvi[i].visual; + break; + } + } + + XFree (xvi); + + return visual; +} + +static SubWindow +*findSubWindow (Window id) +{ + for (int i = 0; i < N_SUB; i++) + if (sub[i].id == id || sub[i].red == id) + return &sub[i]; + return NULL; +} + +static void +setupWindow (Window win, cairo_t **cr, cairo_surface_t **s, int width, int height) +{ + if (cr) + if (*cr) cairo_destroy (*cr); + if (*s) cairo_surface_destroy (*s); + *s = cairo_xlib_surface_create (d, win, v, width, height); + if (cr) *cr = cairo_create (*s); +} + +int +main (int argc, char **argv) +{ + d = XOpenDisplay(NULL); + if(!d) return 1; + + int damageEvent, damageError; + if (!XDamageQueryExtension (d, &damageEvent, &damageError)) + { + fprintf (stderr,"No damage extension\n"); + return 1; + } + + N_SUB = argc - 1; + sub = malloc (sizeof (SubWindow) * N_SUB); + if(!sub) + { + fprintf (stderr,"Alloc failed\n"); + return 1; + } + + v = findArgbVisual (); + if(!v) abort (); + XSetWindowAttributes attr = {}; + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap (d, RootWindow(d, 0), + v, AllocNone); + + w = XCreateWindow(d, RootWindow(d, 0), 0, 0, 1024, 768, 0, + 32, InputOutput, v, CWBackPixel | CWBorderPixel | CWColormap, &attr); + XSelectInput (d, w, ButtonPressMask | StructureNotifyMask); + + for (int i = 0; i < N_SUB; i++) + { + XWindowAttributes wa; + sub[i].red = atoi (argv[i+1]); + XGetWindowAttributes(d, sub[i].red, &wa); + sub[i].width = wa.width; + sub[i].height = wa.height; + sub[i].x = sub[i].y = 64 * i; + + sub[i].id = XCreateWindow(d, w, sub[i].x, sub[i].y, sub[i].width, sub[i].height, + 0, 0, InputOnly, 0, 0, 0); + XMapWindow (d, sub[i].id); + XSelectInput (d, sub[i].red, StructureNotifyMask); + XCompositeRedirectWindowInput (d, sub[i].id, sub[i].red); + sub[i].d = XDamageCreate (d, sub[i].red, XDamageReportRawRectangles); + } + + XMapWindow (d, w); + + for (int i = 0; i < N_SUB; i++) + sub[i].s = cairo_xlib_surface_create (d, sub[i].red, v, 64, 64); + + cairo_surface_t *surface = NULL; + cairo_t *cr = NULL; + + setupWindow (w, &cr, &surface, 1024, 768); + + while(1) + { + drawWindow (cr); + XEvent ev; + XNextEvent(d, &ev); + + switch (ev.type) { + case ConfigureNotify: + { + if ( ev.xany.window == w ) + setupWindow (w, &cr, &surface, ev.xconfigure.width, ev.xconfigure.height); + else + { + SubWindow *s = findSubWindow ( ev.xany.window ); + setupWindow (s->red, NULL, &s->s, ev.xconfigure.width, ev.xconfigure.height); + XResizeWindow (d, s->id, ev.xconfigure.width, ev.xconfigure.height); + } + } + default: + if (ev.type == damageEvent + XDamageNotify) + drawWindow (cr); + break; + XFlush (d); + XSync (d, w); + } + } + return 0; +} |