]> mj.ucw.cz Git - osdd.git/commitdiff
Experiments with Xft rendering
authorMartin Mares <mj@ucw.cz>
Tue, 8 Oct 2013 16:34:35 +0000 (18:34 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 8 Oct 2013 16:34:35 +0000 (18:34 +0200)
Makefile
test.c [new file with mode: 0644]

index 0434fa36b2dd5631d10ff7f63d39feaf097f4c2a..31eeafbb92aca633f1b1fe85ea5b34c6cb1b17af 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,8 @@ ARCHIVE=osdd-$(VERSION).tar.gz
 
 CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -std=gnu99
 
-all: osdd osdc osd-batt osd-alsa
+# all: osdd osdc osd-batt osd-alsa
+all: test
 
 osdd: osdd.o util.o
 osdc: osdc.o util.o client.o
@@ -19,6 +20,10 @@ osd-batt: LDLIBS+=-lX11
 osd-alsa.o: CFLAGS+=$(shell pkg-config --cflags alsa)
 osd-alsa: LDLIBS+=$(shell pkg-config --libs alsa) -lX11
 
+test.o: CFLAGS+=$(shell pkg-config --cflags xft)
+test: LDFLAGS+=$(shell pkg-config --libs xft) -l Xext
+test: test.o util.o
+
 clean:
        rm -f *~ *.o TAGS core osdd osdc osd-batt osd-alsa
 
diff --git a/test.c b/test.c
new file mode 100644 (file)
index 0000000..676a1e5
--- /dev/null
+++ b/test.c
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <poll.h>
+#include <getopt.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+#include <X11/extensions/render.h>
+#include <X11/Xft/Xft.h>
+
+#define DEBUG
+#include "osd.h"
+
+struct osd_state {
+  Display *dpy;
+  int screen;
+  Visual *visual;
+  Colormap cmap;
+  int depth;
+  int screen_width;
+  int screen_height;
+  Window win;
+  Pixmap mask_bitmap;
+  Pixmap image_pixmap;
+  GC gc;
+  GC mask_gc;
+
+  // Xft stuff
+  XftFont *font;
+  XftDraw *xft_draw;
+};
+
+int
+main(int argc, char **argv)
+{
+  XInitThreads();
+
+  struct osd_state osd_static;
+  bzero(&osd_static, sizeof(osd_static));
+  struct osd_state *osd = &osd_static;
+
+  osd->dpy = XOpenDisplay(NULL);
+  if (!osd->dpy)
+    die("Cannot open display");
+
+  int event_basep, error_basep;
+  if (!XShapeQueryExtension(osd->dpy, &event_basep, &error_basep))
+    die("XShape extension not supported by X server, giving up");
+
+  osd->screen = XDefaultScreen(osd->dpy);
+  osd->visual = XDefaultVisual(osd->dpy, osd->screen);
+  osd->depth = XDefaultDepth(osd->dpy, osd->screen);
+  osd->cmap = DefaultColormap(osd->dpy, osd->screen);
+
+  // These can change. And what about Xinerama?
+  osd->screen_width = XDisplayWidth(osd->dpy, osd->screen);
+  osd->screen_height = XDisplayHeight(osd->dpy, osd->screen);
+
+  XSetWindowAttributes win_attr = {
+    .override_redirect = 0,            // FIXME: 1
+  };
+  osd->win = XCreateWindow(osd->dpy,
+       XRootWindow(osd->dpy, osd->screen),
+       0, 0,
+       osd->screen_width, osd->screen_height,
+       0,
+       osd->depth,
+       CopyFromParent,
+       osd->visual,
+       CWOverrideRedirect,
+       &win_attr);
+  XStoreName(osd->dpy, osd->win, "OSD");
+
+  // FIXME: Size
+  osd->mask_bitmap = XCreatePixmap(osd->dpy, osd->win, osd->screen_width, osd->screen_height, 1);
+  osd->image_pixmap = XCreatePixmap(osd->dpy, osd->win, osd->screen_width, osd->screen_height, osd->depth);
+  DBG("depth = %d\n", osd->depth);
+
+  XGCValues gcv = {
+    .graphics_exposures = 0,
+  };
+  osd->gc = XCreateGC(osd->dpy, osd->win, GCGraphicsExposures, &gcv);
+  osd->mask_gc = XCreateGC(osd->dpy, osd->mask_bitmap, GCGraphicsExposures, &gcv);
+
+  XSetBackground(osd->dpy, osd->gc, BlackPixel(osd->dpy, osd->screen));
+  XSetForeground(osd->dpy, osd->gc, BlackPixel(osd->dpy, osd->screen));
+
+  XSetBackground(osd->dpy, osd->mask_gc, WhitePixel(osd->dpy, osd->screen));
+  XSetForeground(osd->dpy, osd->mask_gc, BlackPixel(osd->dpy, osd->screen));
+
+  // FIXME: Stay on top
+
+  XFillRectangle(osd->dpy, osd->image_pixmap, osd->gc, 0, 0, osd->screen_width, osd->screen_height);
+
+  osd->font = XftFontOpenName(osd->dpy, osd->screen, "times-64");
+  if (!osd->font)
+    die("Cannot open font");
+
+  osd->xft_draw = XftDrawCreate(osd->dpy, osd->image_pixmap, osd->visual, osd->cmap);
+  if (!osd->xft_draw)
+    die("Cannot create XftDraw");
+
+  XRenderColor xrc = { .red = 0, .green = 0xffff, .blue = 0, .alpha = 0xffff };
+  XftColor xfc;
+  if (!XftColorAllocValue(osd->dpy, osd->visual, osd->cmap, &xrc, &xfc))
+    die("XftColorAllocValue failed");
+  const unsigned char str[] = "Žluťoučká vlkodlačice";
+  XftDrawStringUtf8(osd->xft_draw, &xfc, osd->font, 100, 100, str, strlen((char *) str));
+
+  XGlyphInfo gi;
+  XftTextExtentsUtf8(osd->dpy, osd->font, str, strlen((char *) str), &gi);
+  DBG("Glyph info: (%d,%d)+(%d,%d) off (%d,%d)\n", gi.x, gi.y, gi.width, gi.height, gi.xOff, gi.yOff);
+  XftDrawRect(osd->xft_draw, &xfc, 100 + gi.x, 100 - gi.y, gi.width, gi.height);
+
+  XftDrawRect(osd->xft_draw, &xfc, 30, 30, 50, 50);
+
+  XSelectInput(osd->dpy, osd->win, ExposureMask);
+  XMapRaised(osd->dpy, osd->win);
+  XFlush(osd->dpy);
+
+  struct pollfd pfd = {
+    .fd = ConnectionNumber(osd->dpy),
+    .events = POLLIN,
+  };
+
+  for (;;)
+    {
+      timestamp_t now = get_current_time();
+      timestamp_t wait_until = now - 1;
+
+      DBG("... waiting for %d ms\n", (int)(wait_until - now));
+      poll(&pfd, 1, wait_until - now);
+      if (pfd.revents & POLLIN)
+       {
+         while (XPending(osd->dpy))
+           {
+             XEvent ev;
+             XNextEvent(osd->dpy, &ev);
+             switch (ev.type)
+               {
+               case Expose:
+                 {
+                   XExposeEvent *ex = &ev.xexpose;
+                   DBG("Expose cnt=%d (%d,%d)+(%d,%d)\n", ex->count, ex->x, ex->y, ex->width, ex->height);
+                   XCopyArea(osd->dpy, osd->image_pixmap, osd->win, osd->gc, ex->x, ex->y, ex->width, ex->height, ex->x, ex->y);
+                   break;
+                 }
+               default:
+                 DBG("Event %d\n", ev.type);
+               }
+           }
+       }
+    }
+
+  // FIXME: Cleanup
+}