]> mj.ucw.cz Git - osdd.git/blob - test.c
676a1e5c35e6e5d16193c0db43f5ed2db8f539b9
[osdd.git] / test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <poll.h>
6 #include <getopt.h>
7 #include <X11/Xlib.h>
8 #include <X11/Xatom.h>
9 #include <X11/extensions/shape.h>
10 #include <X11/extensions/render.h>
11 #include <X11/Xft/Xft.h>
12
13 #define DEBUG
14 #include "osd.h"
15
16 struct osd_state {
17   Display *dpy;
18   int screen;
19   Visual *visual;
20   Colormap cmap;
21   int depth;
22   int screen_width;
23   int screen_height;
24   Window win;
25   Pixmap mask_bitmap;
26   Pixmap image_pixmap;
27   GC gc;
28   GC mask_gc;
29
30   // Xft stuff
31   XftFont *font;
32   XftDraw *xft_draw;
33 };
34
35 int
36 main(int argc, char **argv)
37 {
38   XInitThreads();
39
40   struct osd_state osd_static;
41   bzero(&osd_static, sizeof(osd_static));
42   struct osd_state *osd = &osd_static;
43
44   osd->dpy = XOpenDisplay(NULL);
45   if (!osd->dpy)
46     die("Cannot open display");
47
48   int event_basep, error_basep;
49   if (!XShapeQueryExtension(osd->dpy, &event_basep, &error_basep))
50     die("XShape extension not supported by X server, giving up");
51
52   osd->screen = XDefaultScreen(osd->dpy);
53   osd->visual = XDefaultVisual(osd->dpy, osd->screen);
54   osd->depth = XDefaultDepth(osd->dpy, osd->screen);
55   osd->cmap = DefaultColormap(osd->dpy, osd->screen);
56
57   // These can change. And what about Xinerama?
58   osd->screen_width = XDisplayWidth(osd->dpy, osd->screen);
59   osd->screen_height = XDisplayHeight(osd->dpy, osd->screen);
60
61   XSetWindowAttributes win_attr = {
62     .override_redirect = 0,             // FIXME: 1
63   };
64   osd->win = XCreateWindow(osd->dpy,
65         XRootWindow(osd->dpy, osd->screen),
66         0, 0,
67         osd->screen_width, osd->screen_height,
68         0,
69         osd->depth,
70         CopyFromParent,
71         osd->visual,
72         CWOverrideRedirect,
73         &win_attr);
74   XStoreName(osd->dpy, osd->win, "OSD");
75
76   // FIXME: Size
77   osd->mask_bitmap = XCreatePixmap(osd->dpy, osd->win, osd->screen_width, osd->screen_height, 1);
78   osd->image_pixmap = XCreatePixmap(osd->dpy, osd->win, osd->screen_width, osd->screen_height, osd->depth);
79   DBG("depth = %d\n", osd->depth);
80
81   XGCValues gcv = {
82     .graphics_exposures = 0,
83   };
84   osd->gc = XCreateGC(osd->dpy, osd->win, GCGraphicsExposures, &gcv);
85   osd->mask_gc = XCreateGC(osd->dpy, osd->mask_bitmap, GCGraphicsExposures, &gcv);
86
87   XSetBackground(osd->dpy, osd->gc, BlackPixel(osd->dpy, osd->screen));
88   XSetForeground(osd->dpy, osd->gc, BlackPixel(osd->dpy, osd->screen));
89
90   XSetBackground(osd->dpy, osd->mask_gc, WhitePixel(osd->dpy, osd->screen));
91   XSetForeground(osd->dpy, osd->mask_gc, BlackPixel(osd->dpy, osd->screen));
92
93   // FIXME: Stay on top
94
95   XFillRectangle(osd->dpy, osd->image_pixmap, osd->gc, 0, 0, osd->screen_width, osd->screen_height);
96
97   osd->font = XftFontOpenName(osd->dpy, osd->screen, "times-64");
98   if (!osd->font)
99     die("Cannot open font");
100
101   osd->xft_draw = XftDrawCreate(osd->dpy, osd->image_pixmap, osd->visual, osd->cmap);
102   if (!osd->xft_draw)
103     die("Cannot create XftDraw");
104
105   XRenderColor xrc = { .red = 0, .green = 0xffff, .blue = 0, .alpha = 0xffff };
106   XftColor xfc;
107   if (!XftColorAllocValue(osd->dpy, osd->visual, osd->cmap, &xrc, &xfc))
108     die("XftColorAllocValue failed");
109   const unsigned char str[] = "Žluťoučká vlkodlačice";
110   XftDrawStringUtf8(osd->xft_draw, &xfc, osd->font, 100, 100, str, strlen((char *) str));
111
112   XGlyphInfo gi;
113   XftTextExtentsUtf8(osd->dpy, osd->font, str, strlen((char *) str), &gi);
114   DBG("Glyph info: (%d,%d)+(%d,%d) off (%d,%d)\n", gi.x, gi.y, gi.width, gi.height, gi.xOff, gi.yOff);
115   XftDrawRect(osd->xft_draw, &xfc, 100 + gi.x, 100 - gi.y, gi.width, gi.height);
116
117   XftDrawRect(osd->xft_draw, &xfc, 30, 30, 50, 50);
118
119   XSelectInput(osd->dpy, osd->win, ExposureMask);
120   XMapRaised(osd->dpy, osd->win);
121   XFlush(osd->dpy);
122
123   struct pollfd pfd = {
124     .fd = ConnectionNumber(osd->dpy),
125     .events = POLLIN,
126   };
127
128   for (;;)
129     {
130       timestamp_t now = get_current_time();
131       timestamp_t wait_until = now - 1;
132
133       DBG("... waiting for %d ms\n", (int)(wait_until - now));
134       poll(&pfd, 1, wait_until - now);
135       if (pfd.revents & POLLIN)
136         {
137           while (XPending(osd->dpy))
138             {
139               XEvent ev;
140               XNextEvent(osd->dpy, &ev);
141               switch (ev.type)
142                 {
143                 case Expose:
144                   {
145                     XExposeEvent *ex = &ev.xexpose;
146                     DBG("Expose cnt=%d (%d,%d)+(%d,%d)\n", ex->count, ex->x, ex->y, ex->width, ex->height);
147                     XCopyArea(osd->dpy, osd->image_pixmap, osd->win, osd->gc, ex->x, ex->y, ex->width, ex->height, ex->x, ex->y);
148                     break;
149                   }
150                 default:
151                   DBG("Event %d\n", ev.type);
152                 }
153             }
154         }
155     }
156
157   // FIXME: Cleanup
158 }