summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Bosveld <Joel.Bosveld@gmail.com>2009-07-08 23:40:30 +0800
committerJoel Bosveld <Joel.Bosveld@gmail.com>2009-07-08 23:40:30 +0800
commit0e58db56833035717f5b664cf050ee06d7c576c1 (patch)
treeb7606119cfdfca121800abfc519e986e5d6d3cd4
parentb590fe744332747def13e89dae9169bfbda24092 (diff)
red: add a test for redirection
-rw-r--r--red/Makefile15
-rw-r--r--red/red.c190
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;
+}