hlfw.ca

x9dev

Download patch

ref: c26e66f3a96dd2a66f46fae46eb960daae553a92
parent: be7ddb52e46325dfc96864d41467e4b7184da895
author: halfwit <michaelmisch1985@gmail.com>
date: Sat Oct 10 04:12:19 PDT 2020

Start shuffling things around, each distinct fd in its own source

--- a/draw.c
+++ /dev/null
@@ -1,484 +1,0 @@
-/*
- * Copyright (c) 2020 Michael Misch <michaelmisch1985@gmail.com> 
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "x9dev.h"
-
-x9devInfo x9di;
-
-extern DeviceIntPtr x9devMouse;
-extern DeviceIntPtr x9devKeybd;
-static int  oldx, oldy, oldbut;
-
-static CARD8 modmap[MAP_LENGTH];
-
-#define x9devSaveScreen (void *) NoopDDA
-#define x9devConstrainCursor    (void *) NoopDDA
-#define x9devDisplayCursor  (void *) NoopDDA
-#define x9devRealizeCursor  (void *) NoopDDA
-#define x9devUnrealizeCursor    (void *) NoopDDA
-#define x9devRecolorCursor  (void *) NoopDDA
-#define x9devSetCursorPosition  (void *) NoopDDA
-
-static int x9read(C9ctx *, x9file *, uint32_t);
-
-#define e    ev.u.u
-#define ek    ev.u.keyButtonPointer
-static void
-x9devSendKeybdEvent(int k, int t)
-{
-    xEvent ev;
-
-    memset(&ev, 0, sizeof(xEvent));
-    e.type = t;
-    e.detail = k + MIN_KEYCODE;
-    ek.time = GetTimeInMillis();
-    mieqEnqueue(x9devKeybd, (InternalEvent *)&ev);
-}
-
-static void
-x9devSendMouseEvent(int x, int y, int b, int t)
-{
-    xEvent ev;
-
-    memset(&ev, 0, sizeof(xEvent));
-    e.type = t;
-    e.detail = b;
-    ek.rootX = x;
-    ek.rootY = y;
-    ek.time = GetTimeInMillis();
-    mieqEnqueue(x9devMouse, (InternalEvent *)&ev);
-}
-#undef ek
-#undef e
-
-static void
-x9devRefreshScreen(int x1, int y1, int x2, int y2)
-{
-    /*
-    Rectangle r;
-    uchar *p;
-    int n;
-
-    p = (uchar *)x9di.fb+(y1*x9di.width+x1)*(x9di.depth/8);
-    r = rectaddpt(Rect(x1, y1, x2, y2), screen->r.min);
-    if (Dx(r) == x9di.width) {
-        if (loadimage(screen, r, p, x9di.bpl * Dy(r)) < 0)
-            FatalError("can't load image");
-        goto End;
-    }
-    n = Dx(r)*(x9di.depth/8);
-    y2 += screen->r.min.y;
-       while(r.min.y < y2) {
-        r.max.y = r.min.y+1;
-        if (loadimage(screen, r, p, n) < 0)
-            FatalError("can't load image");
-        p += x9di.bpl;
-        r.min.y++;
-    }
-
-End:
-    flushimage(display, 1);
-    */
-}
-
-static void
-x9devResize(void)
-{
-    /* 
-    if (getwindow(display, Refnone) < 0)
-        FatalError("can't reattach to window");
-
-    draw(screen, screen->r, display->white, nil, ZP);
-    x9devRefreshScreen(0, 0, x9di.width, x9di.height);
-    */
-}
-
-static int
-x9devMouseRead(int *x, int *y, int *b)
-{
-    int n;
-
-    /* Magic numbers here are the size of a message from /dev/mouse and its offsets */
-    if((n = x9read(x9di.ctx, x9di.mouse, 1 + 4 * 12)) <= 0)
-        return 0;
-
-    if (n != 1 + 4 * 12)
-        FatalError("Bad mouse event");
-
-    if (buf[0] == 'r') {
-        x9devResize();
-        return 0;
-    }
-    *x = atoi(x9di.mouse->rbuf + 1 + 0 * 12) - screen->r.min.x;
-    *y = atoi(x9di.mouse->rbuf + 1 + 1 * 12) - screen->r.min.y;
-    *b = atoi(x9di.mouse->rbuf + 1 + 2 * 12);
-
-    return 1;
-}
-
-static wchar_t
-x9devKeybdRead(void)
-{
-    static char s[3];
-    static int  n = 0;
-    wchar_t rune;
-
-    if (x9read(x9di.ctx, x9di.keydb, 1) != 1)
-        return 0;
-
-    rune = s[0];
-    if (n > 0 || (rune & 0x80) != 0x00) {
-        if (mbtowc(&rune, s, n + 1) == -1) {
-            /* incomplete rune; wait until next char */
-            if (++n == 3)
-                n = 0;
-            return 0;
-        }
-        n = 0;
-    }
-    if (rune == Kdown)
-        rune = 0x99;
-    else if (rune & KF)
-        rune = (rune&~KF) + 0x80;
-
-    return rune;
-}
-
-static void
-x9devInfoInit(void)
-{
-    /* 
-    if(initdraw(NULL, 0, "x9dev") < 0)
-        FatalError("can't open display");
-
-    x9di.depth = screen->depth;
-    x9di.width = Dx(screen->r);
-    x9di.width -= x9di.width&(screen->depth/8);
-    x9di.dpi = 100;
-    x9di.bpl = bytesperline(Rect(0, 0, x9di.width, x9di.height), x9di.depth);
-    x9di.fb = malloc(x9di.bpl * x9di.height);
-    if (x9di.fb == nil)
-        FatalError("couldn't allocate framebuffer");
-
-    snprint(buf, sizeof buf, "%s/mouse", display->devdir);
-    x9di.mouseFd = c9open(buf, O_RDWR | O_NONBLOCK);
-    if(x9di.mouseFd < 0)
-        FatalError("can't open mouse");
-
-    snprint(buf, sizeof buf, "%s/cons", display->devdir);
-    x9di.keybdFd = c9open(buf, O_RDONLY | O_NONBLOCK);
-    if(x9di.keybdFd < 0)
-        FatalError("can't open keyboard");
-
-    snprint(buf, sizeof buf, "%s/consctl", display->devdir);
-    x9di.consctlFd = c9open(buf, O_WRONLY);
-    if(x9di.consctlFd < 0)
-        FatalError("can't open consctl");
-    if(c9write(x9di.consctlFd, "rawon", 5) != 5)
-        FatalError("can't set rawon");
-    */
-}
-
-static int  
-x9devKeybdHandle(void)
-{
-    unsigned char   k, m;
-    int c;
-
-    c = x9devKeybdRead();
-    if (c == 0 || c > sizeof(rune2keycode))
-        return 0;
-
-    k = rune2keycode[c].key;
-    if (k == 0)
-        return 0;
-
-    m = rune2keycode[c].mod;
-    if (m) 
-        x9devSendKeybdEvent(m, KeyPress);
-
-    x9devSendKeybdEvent(k, KeyPress);
-    x9devSendKeybdEvent(k, KeyRelease);
-    if (m) 
-        x9devSendKeybdEvent(m, KeyRelease);
-
-    return 1;
-}
-
-
-static int  
-x9devMouseHandle(void)
-{
-    int x, y, b, but, t;
-
-    if (!x9devMouseRead(&x, &y, &but))
-        return 0;
-
-    t = b = 0;
-    if (x != oldx || y != oldy) {
-        t = MotionNotify;
-        oldx = x, oldy = y;
-    }
-    if (but != oldbut) {
-        b = oldbut ^ but;
-        t = ButtonPress;
-        if (oldbut & b)
-            t = ButtonRelease;
-        if (b == 4)
-            b = 3;
-        if (but & (8 | 16)) {
-            if (b & 8)
-                b = 4;
-            else
-                b = 5;
-            x9devSendMouseEvent(x, y, b, ButtonPress);
-            x9devSendMouseEvent(x, y, b, ButtonRelease);
-            return 1;
-        }
-    }
-    x9devSendMouseEvent(x, y, b, t);
-    oldbut = but;
-
-    return 1;
-}
-
-
-static void
-x9devWakeupHandler(ScreenPtr scr, int result)
-{
-
-    if (result <= 0)
-        return;
-
-    while (x9devMouseHandle())
-        ;
-    while (x9devKeybdHandle())
-        ;
-}
-
-
-static void
-x9devInitModmap(void)
-{
-    KeySym * ks;
-    int i;
-
-    for (i = 0; i < MAP_LENGTH; i++)
-        modmap[i] = NoSymbol;
-
-    for (i = MIN_KEYCODE, ks = map; i < (MIN_KEYCODE + NUM_KEYCODES); i++, ks += MAP_WIDTH)
-        switch (*ks) {
-        case XK_Shift_L:
-        case XK_Shift_R:
-            modmap[i] = ShiftMask;
-            break;
-        case XK_Control_L:
-        case XK_Control_R:
-            modmap[i] = ControlMask;
-            break;
-        case XK_Alt_L:
-        case XK_Alt_R:
-            modmap[i] = Mod1Mask;
-            break;
-        }
-}
-
-int  
-x9devKeybdProc(DeviceIntPtr pDev, int what)
-{
-
-    switch (what) {
-    case DEVICE_INIT:
-        x9devInitModmap();
-        if (!InitKeyboardDeviceStruct(pDev, NULL, 
-            (BellProcPtr)NoopDDA, (KbdCtrlProcPtr)NoopDDA))
-            FatalError("can't init keyboard");
-	pDev->inited = TRUE;
-        break;
-    case DEVICE_ON:
-        pDev->enabled = TRUE;
-        break;
-    case DEVICE_CLOSE:
-	break;
-    case DEVICE_OFF:
-        pDev->enabled = FALSE;
-        break;
-    }
-    return Success;
-}
-
-int  
-x9devMouseProc(DeviceIntPtr pDevice, int what)
-{
-    static unsigned char    map[] = {0, 1, 2, 3, 4, 5};
-    DevicePtr pDev = (DevicePtr)pDevice;
-    Atom btn_labels[3] = {0};
-    Atom axes_labels[2] = {0};
-
-    switch (what) {
-    case DEVICE_INIT:
-        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
-        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
-        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
-
-        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
-        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
-        InitPointerDeviceStruct(pDev, map, 3, btn_labels,
-            (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2, axes_labels);
-        break;
-
-    case DEVICE_ON:
-        pDev->on = TRUE;
-        break;
-
-    case DEVICE_CLOSE:
-    case DEVICE_OFF:
-        pDev->on = FALSE;
-        break;
-    }
-    return Success;
-}
-
-
-static void
-x9devCursorLimits(DeviceIntPtr dptr, ScreenPtr spr, CursorPtr cpr, BoxPtr hot, BoxPtr topleft)
-{
-    *topleft = *hot;
-}
-
-static void
-x9devShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
-{
-    BoxPtr pbox;
-
-    pbox = REGION_EXTENTS(pScreen, &pBuf->pDamage);
-    x9devRefreshScreen(pbox->x1, pbox->y1, pbox->x2, pbox->y2);
-}
-
-
-/* callback dance... */
-static CreateScreenResourcesProcPtr x9devCreateResourcesPtr;
-
-static Bool
-x9devCreateResources(ScreenPtr pScreen)
-{
-    Bool ret = 0;
-
-    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
-    if (pScreen->CreateScreenResources)
-        ret = pScreen->CreateScreenResources(pScreen);
-
-    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
-    if (ret == FALSE)
-        return FALSE;
-
-    shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
-    if (!shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), x9devShadowUpdate, NULL, SHADOW_ROTATE_0, 0))
-        return FALSE;
-
-    return ret;
-}
-
-Bool
-x9devScreenInit(ScreenPtr pScreen, int argc, char *argv[])
-{
-    int v, i;
-    unsigned long   r, g, b;
-    static int  first = 1;
-
-    if (first) {
-        x9devInfoInit();
-        first = 0;
-    }
-
-    for (i = 0; i < NUMFORMATS; i++)
-        fbSetVisualTypes(formats[i].depth, 0, 8);
-
-    switch (x9di.depth) {
-    case 16:
-        r = 0xF800, g = 0x07E0, b = 0x001F;
-        v = 1 << TrueColor;
-        break;
-    case 24:
-    case 32:
-        r = 0xFF0000, g = 0x00FF00, b = 0x0000FF;
-        v = 1 << TrueColor;
-        break;
-    default:
-        r = g = b = 0;
-        v = 1 << PseudoColor;
-    }
-    if (!fbSetVisualTypesAndMasks(x9di.depth, v, 8, r, g, b))
-        return FALSE;
-
-    if (!fbScreenInit(pScreen, x9di.fb, x9di.width, x9di.height,
-        x9di.dpi, x9di.dpi, x9di.width, x9di.depth))
-        return FALSE;
-
-    pScreen->mmWidth = x9di.width * 25.4 / x9di.dpi;
-    pScreen->mmHeight = x9di.height * 25.4 / x9di.dpi;
-
-    /* cursor */
-    pScreen->ConstrainCursor = x9devConstrainCursor;
-    pScreen->CursorLimits = x9devCursorLimits;
-    pScreen->DisplayCursor = x9devDisplayCursor;
-    pScreen->RealizeCursor = x9devRealizeCursor;
-    pScreen->UnrealizeCursor = x9devUnrealizeCursor;
-    pScreen->RecolorCursor = x9devRecolorCursor;
-    pScreen->SetCursorPosition = x9devSetCursorPosition;
-
-    pScreen->SaveScreen = x9devSaveScreen;
-    pScreen->WakeupHandler = x9devWakeupHandler;
-
-#ifdef RENDER
-    if (!fbPictureInit(pScreen, 0, 0))
-        return FALSE;
-#endif
-
-   if (!shadowSetup(pScreen))
-        return FALSE;
-
-    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = x9devCreateResources;
-
-    if (!fbCreateDefColormap(pScreen))
-        return FALSE;
-
-    return TRUE;
-}
-
-Bool
-x9checkmod(unsigned int k, DeviceIntPtr pDev)
-{
-    return modmap[k] != 0;
-}
-
-static int
-x9read(C9ctx *ctx, x9file *file, uint32_t count)
-{
-    return c9read(ctx, &file->tag, 0, file->wroff, count);
-}
\ No newline at end of file
--- /dev/null
+++ b/keyboard.c
@@ -1,0 +1,161 @@
+/*
+ * Copyright (c) 2020 Michael Misch <michaelmisch1985@gmail.com> 
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "x9dev.h"
+#define KF      0xF000
+#define Kdown   0x80
+
+extern x9devInfo x9di;
+extern DeviceIntPtr x9devKeybd;
+static CARD8 modmap[MAP_LENGTH];
+
+#define e    ev.u.u
+#define ek    ev.u.keyButtonPointer
+
+static void
+x9devSendKeybdEvent(int k, int t)
+{
+    xEvent ev;
+
+    memset(&ev, 0, sizeof(xEvent));
+    e.type = t;
+    e.detail = k + MIN_KEYCODE;
+    ek.time = GetTimeInMillis();
+    mieqEnqueue(x9devKeybd, (InternalEvent *)&ev);
+}
+
+#undef ek
+#undef e
+
+static wchar_t
+x9devKeybdRead(void)
+{
+    static char s[3];
+    static int  n = 0;
+    wchar_t rune;
+
+    if (x9read(x9di.ctx, x9di.keybd, 1) != 1)
+        return 0;
+
+    rune = s[0];
+    if (n > 0 || (rune & 0x80) != 0x00) {
+        if (mbtowc(&rune, s, n + 1) == -1) {
+            /* incomplete rune; wait until next char */
+            if (++n == 3)
+                n = 0;
+            return 0;
+        }
+        n = 0;
+    }
+    if (rune == Kdown)
+        rune = 0x99;
+    else if (rune & KF)
+        rune = (rune&~KF) + 0x80;
+
+    return rune;
+}
+
+static int  
+x9devKeybdHandle(void)
+{
+    unsigned char   k, m;
+    int c;
+
+    c = x9devKeybdRead();
+    if (c == 0 || c > sizeof(rune2keycode))
+        return 0;
+
+    k = rune2keycode[c].key;
+    if (k == 0)
+        return 0;
+
+    m = rune2keycode[c].mod;
+    if (m) 
+        x9devSendKeybdEvent(m, KeyPress);
+
+    x9devSendKeybdEvent(k, KeyPress);
+    x9devSendKeybdEvent(k, KeyRelease);
+    if (m) 
+        x9devSendKeybdEvent(m, KeyRelease);
+
+    return 1;
+}
+
+static void
+x9devInitModmap(void)
+{
+    KeySym * ks;
+    int i;
+
+    for (i = 0; i < MAP_LENGTH; i++)
+        modmap[i] = NoSymbol;
+
+    for (i = MIN_KEYCODE, ks = map; i < (MIN_KEYCODE + NUM_KEYCODES); i++, ks += MAP_WIDTH)
+        switch (*ks) {
+        case XK_Shift_L:
+        case XK_Shift_R:
+            modmap[i] = ShiftMask;
+            break;
+        case XK_Control_L:
+        case XK_Control_R:
+            modmap[i] = ControlMask;
+            break;
+        case XK_Alt_L:
+        case XK_Alt_R:
+            modmap[i] = Mod1Mask;
+            break;
+        }
+}
+
+int  
+x9devKeybdProc(DeviceIntPtr pDev, int what)
+{
+
+    switch (what) {
+    case DEVICE_INIT:
+        x9devInitModmap();
+        if (!InitKeyboardDeviceStruct(pDev, NULL, 
+            (BellProcPtr)NoopDDA, (KbdCtrlProcPtr)NoopDDA))
+            FatalError("can't init keyboard");
+	pDev->inited = TRUE;
+        break;
+    case DEVICE_ON:
+        pDev->enabled = TRUE;
+        break;
+    case DEVICE_CLOSE:
+	break;
+    case DEVICE_OFF:
+        pDev->enabled = FALSE;
+        break;
+    }
+    return Success;
+}
+
+Bool
+x9checkmod(unsigned int k, DeviceIntPtr pDev)
+{
+    return modmap[k] != 0;
+}
--- /dev/null
+++ b/libdraw/draw.h
@@ -1,0 +1,527 @@
+typedef struct	Cachefont Cachefont;
+typedef struct	Cacheinfo Cacheinfo;
+typedef struct	Cachesubf Cachesubf;
+typedef struct	Display Display;
+typedef struct	Font Font;
+typedef struct	Fontchar Fontchar;
+typedef struct	Image Image;
+typedef struct	Mouse Mouse;
+typedef struct	Point Point;
+typedef struct	Rectangle Rectangle;
+typedef struct	RGB RGB;
+typedef struct	Screen Screen;
+typedef struct	Subfont Subfont;
+
+typedef unsigned long ulong;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int Rune;
+
+enum
+{
+	UTFmax		= 4,		/* maximum bytes per rune */
+	Runesync	= 0x80,		/* cannot represent part of a UTF sequence (<) */
+	Runeself	= 0x80,		/* rune and UTF sequences are the same (<) */
+	Runeerror	= 0xFFFD,	/* decoding error in UTF */
+	Runemax		= 0x10FFFF,	/* 21 bit rune */
+};
+
+enum
+{
+	DOpaque		= 0xFFFFFFFF,
+	DTransparent	= 0x00000000,		/* only useful for allocimage, memfillcolor */
+	DBlack		= 0x000000FF,
+	DWhite		= 0xFFFFFFFF,
+	DRed		= 0xFF0000FF,
+	DGreen		= 0x00FF00FF,
+	DBlue		= 0x0000FFFF,
+	DCyan		= 0x00FFFFFF,
+	DMagenta		= 0xFF00FFFF,
+	DYellow		= 0xFFFF00FF,
+	DPaleyellow	= 0xFFFFAAFF,
+	DDarkyellow	= 0xEEEE9EFF,
+	DDarkgreen	= 0x448844FF,
+	DPalegreen	= 0xAAFFAAFF,
+	DMedgreen	= 0x88CC88FF,
+	DDarkblue	= 0x000055FF,
+	DPalebluegreen= 0xAAFFFFFF,
+	DPaleblue		= 0x0000BBFF,
+	DBluegreen	= 0x008888FF,
+	DGreygreen	= 0x55AAAAFF,
+	DPalegreygreen	= 0x9EEEEEFF,
+	DYellowgreen	= 0x99994CFF,
+	DMedblue		= 0x000099FF,
+	DGreyblue	= 0x005DBBFF,
+	DPalegreyblue	= 0x4993DDFF,
+	DPurpleblue	= 0x8888CCFF,
+
+	DNotacolor	= 0xFFFFFF00,
+	DNofill		= DNotacolor,
+	
+};
+
+enum
+{
+	Displaybufsize	= 8000,
+	ICOSSCALE	= 1024,
+	Borderwidth =	4,
+};
+
+enum
+{
+	/* refresh methods */
+	Refbackup	= 0,
+	Refnone		= 1,
+	Refmesg		= 2
+};
+#define	NOREFRESH	((void*)-1)
+
+enum
+{
+	/* line ends */
+	Endsquare	= 0,
+	Enddisc		= 1,
+	Endarrow	= 2,
+	Endmask		= 0x1F
+};
+
+#define	ARROW(a, b, c)	(Endarrow|((a)<<5)|((b)<<14)|((c)<<23))
+
+typedef enum
+{
+	/* Porter-Duff compositing operators */
+	Clear	= 0,
+
+	SinD	= 8,
+	DinS	= 4,
+	SoutD	= 2,
+	DoutS	= 1,
+
+	S		= SinD|SoutD,
+	SoverD	= SinD|SoutD|DoutS,
+	SatopD	= SinD|DoutS,
+	SxorD	= SoutD|DoutS,
+
+	D		= DinS|DoutS,
+	DoverS	= DinS|DoutS|SoutD,
+	DatopS	= DinS|SoutD,
+	DxorS	= DoutS|SoutD,	/* == SxorD */
+
+	Ncomp = 12,
+} Drawop;
+
+/*
+ * image channel descriptors 
+ */
+enum {
+	CRed = 0,
+	CGreen,
+	CBlue,
+	CGrey,
+	CAlpha,
+	CMap,
+	CIgnore,
+	NChan,
+};
+
+#define __DC(type, nbits)	((((type)&15)<<4)|((nbits)&15))
+#define CHAN1(a,b)	__DC(a,b)
+#define CHAN2(a,b,c,d)	(CHAN1((a),(b))<<8|__DC((c),(d)))
+#define CHAN3(a,b,c,d,e,f)	(CHAN2((a),(b),(c),(d))<<8|__DC((e),(f)))
+#define CHAN4(a,b,c,d,e,f,g,h)	(CHAN3((a),(b),(c),(d),(e),(f))<<8|__DC((g),(h)))
+
+#define NBITS(c) ((c)&15)
+#define TYPE(c) (((c)>>4)&15)
+
+enum {
+	GREY1	= CHAN1(CGrey, 1),
+	GREY2	= CHAN1(CGrey, 2),
+	GREY4	= CHAN1(CGrey, 4),
+	GREY8	= CHAN1(CGrey, 8),
+	CMAP8	= CHAN1(CMap, 8),
+	RGB15	= CHAN4(CIgnore, 1, CRed, 5, CGreen, 5, CBlue, 5),
+	RGB16	= CHAN3(CRed, 5, CGreen, 6, CBlue, 5),
+	RGB24	= CHAN3(CRed, 8, CGreen, 8, CBlue, 8),
+	RGBA32	= CHAN4(CRed, 8, CGreen, 8, CBlue, 8, CAlpha, 8),
+	ARGB32	= CHAN4(CAlpha, 8, CRed, 8, CGreen, 8, CBlue, 8),	/* stupid VGAs */
+	XRGB32	= CHAN4(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8),
+	BGR24	= CHAN3(CBlue, 8, CGreen, 8, CRed, 8),
+	ABGR32	= CHAN4(CAlpha, 8, CBlue, 8, CGreen, 8, CRed, 8),
+	XBGR32	= CHAN4(CIgnore, 8, CBlue, 8, CGreen, 8, CRed, 8),
+};
+
+extern	char*	chantostr(char*, ulong);
+extern	ulong	strtochan(char*);
+extern	int		chantodepth(ulong);
+
+struct	Point
+{
+	int	x;
+	int	y;
+};
+
+struct Rectangle
+{
+	Point	min;
+	Point	max;
+};
+
+typedef void	(*Reffn)(Image*, Rectangle, void*);
+
+struct Screen
+{
+	Display	*display;	/* display holding data */
+	int	id;		/* id of system-held Screen */
+	Image	*image;		/* unused; for reference only */
+	Image	*fill;		/* color to paint behind windows */
+};
+
+struct Display
+{
+	int		locking;	/*program is using lockdisplay */
+	int		dirno;
+	int		fd;
+	int		reffd;
+	int		ctlfd;
+	int		imageid;
+	int		local;
+	void		(*error)(Display*, char*);
+	char		*devdir;
+	char		*windir;
+	char		oldlabel[64];
+	ulong		dataqid;
+	Image		*white;
+	Image		*black;
+	Image		*opaque;
+	Image		*transparent;
+	Image		*image;
+	uchar		*buf;
+	int		bufsize;
+	uchar		*bufp;
+	Font		*defaultfont;
+	Subfont		*defaultsubfont;
+	Image		*windows;
+	Image		*screenimage;
+	int		_isnewdisplay;
+};
+
+struct Image
+{
+	Display		*display;	/* display holding data */
+	int		id;		/* id of system-held Image */
+	Rectangle	r;		/* rectangle in data area, local coords */
+	Rectangle 	clipr;		/* clipping region */
+	int		depth;		/* number of bits per pixel */
+	ulong		chan;
+	int		repl;		/* flag: data replicates to tile clipr */
+	Screen		*screen;	/* 0 if not a window */
+	Image		*next;	/* next in list of windows */
+};
+
+struct RGB
+{
+	ulong	red;
+	ulong	green;
+	ulong	blue;
+};
+
+/*
+ * Subfonts
+ *
+ * given char c, Subfont *f, Fontchar *i, and Point p, one says
+ *	i = f->info+c;
+ *	draw(b, Rect(p.x+i->left, p.y+i->top,
+ *		p.x+i->left+((i+1)->x-i->x), p.y+i->bottom),
+ *		color, f->bits, Pt(i->x, i->top));
+ *	p.x += i->width;
+ * to draw characters in the specified color (itself an Image) in Image b.
+ */
+
+struct	Fontchar
+{
+	int		x;		/* left edge of bits */
+	uchar		top;		/* first non-zero scan-line */
+	uchar		bottom;		/* last non-zero scan-line + 1 */
+	char		left;		/* offset of baseline */
+	uchar		width;		/* width of baseline */
+};
+
+struct	Subfont
+{
+	char		*name;
+	short		n;		/* number of chars in font */
+	uchar		height;		/* height of image */
+	char		ascent;		/* top of image to baseline */
+	Fontchar 	*info;		/* n+1 character descriptors */
+	Image		*bits;		/* of font */
+	int		ref;
+};
+
+enum
+{
+	/* starting values */
+	LOG2NFCACHE =	6,
+	NFCACHE =	(1<<LOG2NFCACHE),	/* #chars cached */
+	NFLOOK =	5,			/* #chars to scan in cache */
+	NFSUBF =	2,			/* #subfonts to cache */
+	/* max value */
+	MAXFCACHE =	1024+NFLOOK,		/* upper limit */
+	MAXSUBF =	50,			/* generous upper limit */
+	/* deltas */
+	DSUBF = 	4,
+	/* expiry ages */
+	SUBFAGE	=	10000,
+	CACHEAGE =	10000
+};
+
+struct Cachefont
+{
+	Rune		min;	/* lowest rune value to be taken from subfont */
+	Rune		max;	/* highest rune value+1 to be taken from subfont */
+	int		offset;	/* position in subfont of character at min */
+	char		*name;			/* stored in font */
+	char		*subfontname;		/* to access subfont */
+};
+
+struct Cacheinfo
+{
+	ushort		x;		/* left edge of bits */
+	uchar		width;		/* width of baseline */
+	char		left;		/* offset of baseline */
+	Rune		value;	/* value of character at this slot in cache */
+	ushort		age;
+};
+
+struct Cachesubf
+{
+	ulong		age;	/* for replacement */
+	Cachefont	*cf;	/* font info that owns us */
+	Subfont		*f;	/* attached subfont */
+};
+
+struct Font
+{
+	char		*name;
+	Display		*display;
+	short		height;	/* max height of image, interline spacing */
+	short		ascent;	/* top of image to baseline */
+	short		width;	/* widest so far; used in caching only */	
+	short		nsub;	/* number of subfonts */
+	ulong		age;	/* increasing counter; used for LRU */
+	int		maxdepth;	/* maximum depth of all loaded subfonts */
+	int		ncache;	/* size of cache */
+	int		nsubf;	/* size of subfont list */
+	Cacheinfo	*cache;
+	Cachesubf	*subf;
+	Cachefont	**sub;	/* as read from file */
+	Image		*cacheimage;
+};
+
+#define	Dx(r)	((r).max.x-(r).min.x)
+#define	Dy(r)	((r).max.y-(r).min.y)
+
+/*
+ * One of a kind
+ */
+extern int		mousescrollsize(int);
+
+/*
+ * Image management
+ */
+extern Image*	_allocimage(Image*, Display*, Rectangle, ulong, int, ulong, int, int);
+extern Image*	allocimage(Display*, Rectangle, ulong, int, ulong);
+extern uchar*	bufimage(Display*, int);
+extern int	bytesperline(Rectangle, int);
+extern void	closedisplay(Display*);
+extern void	drawerror(Display*, char*);
+extern int	flushimage(Display*, int);
+extern int	freeimage(Image*);
+extern int	_freeimage1(Image*);
+extern int	geninitdraw(char*, void(*)(Display*, char*), char*, char*, char*, int);
+extern int	initdraw(void(*)(Display*, char*), char*, char*);
+extern int	newwindow(char*);
+extern Display*	initdisplay(char*, char*, void(*)(Display*, char*));
+extern int	loadimage(Image*, Rectangle, uchar*, int);
+extern int	cloadimage(Image*, Rectangle, uchar*, int);
+extern int	getwindow(Display*, int);
+extern int	gengetwindow(Display*, char*, Image**, Screen**, int);
+extern Image* readimage(Display*, int, int);
+extern Image* creadimage(Display*, int, int);
+extern int	unloadimage(Image*, Rectangle, uchar*, int);
+extern int	wordsperline(Rectangle, int);
+extern int	writeimage(int, Image*, int);
+extern Image*	namedimage(Display*, char*);
+extern int	nameimage(Image*, char*, int);
+extern Image* allocimagemix(Display*, ulong, ulong);
+
+/*
+ * Colors
+ */
+extern	void	readcolmap(Display*, RGB*);
+extern	void	writecolmap(Display*, RGB*);
+extern	ulong	setalpha(ulong, uchar);
+
+/*
+ * Windows
+ */
+extern Screen*	allocscreen(Image*, Image*, int);
+extern Image*	_allocwindow(Image*, Screen*, Rectangle, int, ulong);
+extern Image*	allocwindow(Screen*, Rectangle, int, ulong);
+extern void	bottomnwindows(Image**, int);
+extern void	bottomwindow(Image*);
+extern int	freescreen(Screen*);
+extern Screen*	publicscreen(Display*, int, ulong);
+extern void	topnwindows(Image**, int);
+extern void	topwindow(Image*);
+extern int	originwindow(Image*, Point, Point);
+
+/*
+ * Geometry
+ */
+extern Point		Pt(int, int);
+extern Rectangle	Rect(int, int, int, int);
+extern Rectangle	Rpt(Point, Point);
+extern Point		addpt(Point, Point);
+extern Point		subpt(Point, Point);
+extern Point		divpt(Point, int);
+extern Point		mulpt(Point, int);
+extern int		eqpt(Point, Point);
+extern int		eqrect(Rectangle, Rectangle);
+extern Rectangle	insetrect(Rectangle, int);
+extern Rectangle	rectaddpt(Rectangle, Point);
+extern Rectangle	rectsubpt(Rectangle, Point);
+extern Rectangle	canonrect(Rectangle);
+extern int		rectXrect(Rectangle, Rectangle);
+extern int		rectinrect(Rectangle, Rectangle);
+extern void		combinerect(Rectangle*, Rectangle);
+extern int		rectclip(Rectangle*, Rectangle);
+extern int		ptinrect(Point, Rectangle);
+extern void		replclipr(Image*, int, Rectangle);
+extern int		drawreplxy(int, int, int);	/* used to be drawsetxy */
+extern Point	drawrepl(Rectangle, Point);
+extern int		rgb2cmap(int, int, int);
+extern int		cmap2rgb(int);
+extern int		cmap2rgba(int);
+extern void		icossin(int, int*, int*);
+extern void		icossin2(int, int, int*, int*);
+extern int		badrect(Rectangle);
+
+/*
+ * Graphics
+ */
+extern void	draw(Image*, Rectangle, Image*, Image*, Point);
+extern void	drawop(Image*, Rectangle, Image*, Image*, Point, Drawop);
+extern void	gendraw(Image*, Rectangle, Image*, Point, Image*, Point);
+extern void	gendrawop(Image*, Rectangle, Image*, Point, Image*, Point, Drawop);
+extern void	line(Image*, Point, Point, int, int, int, Image*, Point);
+extern void	lineop(Image*, Point, Point, int, int, int, Image*, Point, Drawop);
+extern void	poly(Image*, Point*, int, int, int, int, Image*, Point);
+extern void	polyop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
+extern void	fillpoly(Image*, Point*, int, int, Image*, Point);
+extern void	fillpolyop(Image*, Point*, int, int, Image*, Point, Drawop);
+extern Point	string(Image*, Point, Image*, Point, Font*, char*);
+extern Point	stringop(Image*, Point, Image*, Point, Font*, char*, Drawop);
+extern Point	stringn(Image*, Point, Image*, Point, Font*, char*, int);
+extern Point	stringnop(Image*, Point, Image*, Point, Font*, char*, int, Drawop);
+extern Point	runestring(Image*, Point, Image*, Point, Font*, Rune*);
+extern Point	runestringop(Image*, Point, Image*, Point, Font*, Rune*, Drawop);
+extern Point	runestringn(Image*, Point, Image*, Point, Font*, Rune*, int);
+extern Point	runestringnop(Image*, Point, Image*, Point, Font*, Rune*, int, Drawop);
+extern Point	stringbg(Image*, Point, Image*, Point, Font*, char*, Image*, Point);
+extern Point	stringbgop(Image*, Point, Image*, Point, Font*, char*, Image*, Point, Drawop);
+extern Point	stringnbg(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point);
+extern Point	stringnbgop(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point, Drawop);
+extern Point	runestringbg(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point);
+extern Point	runestringbgop(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point, Drawop);
+extern Point	runestringnbg(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point);
+extern Point	runestringnbgop(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point, Drawop);
+extern Point	_string(Image*, Point, Image*, Point, Font*, char*, Rune*, int, Rectangle, Image*, Point, Drawop);
+extern Point	stringsubfont(Image*, Point, Image*, Subfont*, char*);
+extern int		bezier(Image*, Point, Point, Point, Point, int, int, int, Image*, Point);
+extern int		bezierop(Image*, Point, Point, Point, Point, int, int, int, Image*, Point, Drawop);
+extern int		bezspline(Image*, Point*, int, int, int, int, Image*, Point);
+extern int		bezsplineop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
+extern int		bezsplinepts(Point*, int, Point**);
+extern int		fillbezier(Image*, Point, Point, Point, Point, int, Image*, Point);
+extern int		fillbezierop(Image*, Point, Point, Point, Point, int, Image*, Point, Drawop);
+extern int		fillbezspline(Image*, Point*, int, int, Image*, Point);
+extern int		fillbezsplineop(Image*, Point*, int, int, Image*, Point, Drawop);
+extern void	ellipse(Image*, Point, int, int, int, Image*, Point);
+extern void	ellipseop(Image*, Point, int, int, int, Image*, Point, Drawop);
+extern void	fillellipse(Image*, Point, int, int, Image*, Point);
+extern void	fillellipseop(Image*, Point, int, int, Image*, Point, Drawop);
+extern void	arc(Image*, Point, int, int, int, Image*, Point, int, int);
+extern void	arcop(Image*, Point, int, int, int, Image*, Point, int, int, Drawop);
+extern void	fillarc(Image*, Point, int, int, Image*, Point, int, int);
+extern void	fillarcop(Image*, Point, int, int, Image*, Point, int, int, Drawop);
+extern void	border(Image*, Rectangle, int, Image*, Point);
+extern void	borderop(Image*, Rectangle, int, Image*, Point, Drawop);
+
+/*
+ * Font management
+ */
+extern Font*	openfont(Display*, char*);
+extern Font*	buildfont(Display*, char*, char*);
+extern void	freefont(Font*);
+extern Font*	mkfont(Subfont*, Rune);
+extern int	cachechars(Font*, char**, Rune**, ushort*, int, int*, char**);
+extern void	agefont(Font*);
+extern Subfont*	allocsubfont(char*, int, int, int, Fontchar*, Image*);
+extern Subfont*	lookupsubfont(Display*, char*);
+extern void	installsubfont(char*, Subfont*);
+extern void	uninstallsubfont(Subfont*);
+extern void	freesubfont(Subfont*);
+extern Subfont*	readsubfont(Display*, char*, int, int);
+extern Subfont*	readsubfonti(Display*, char*, int, Image*, int);
+extern int	writesubfont(int, Subfont*);
+extern void	_unpackinfo(Fontchar*, uchar*, int);
+extern Point	stringsize(Font*, char*);
+extern int	stringwidth(Font*, char*);
+extern int	stringnwidth(Font*, char*, int);
+extern Point	runestringsize(Font*, Rune*);
+extern int	runestringwidth(Font*, Rune*);
+extern int	runestringnwidth(Font*, Rune*, int);
+extern Point	strsubfontwidth(Subfont*, char*);
+extern int	loadchar(Font*, Rune, Cacheinfo*, int, int, char**);
+extern char*	subfontname(char*, char*, int);
+extern Subfont*	_getsubfont(Display*, char*);
+extern Subfont*	getdefont(Display*);
+extern void		lockdisplay(Display*);
+extern void	unlockdisplay(Display*);
+
+/*
+ * Predefined 
+ */
+extern	uchar	defontdata[];
+extern	int		sizeofdefont;
+extern	Point		ZP;
+extern	Rectangle	ZR;
+
+/*
+ * Set up by initdraw()
+ */
+extern	Display	*display;
+extern	Font		*font;
+extern	Image	*screen;
+extern	Screen	*_screen;
+extern	int	_cursorfd;
+extern	void	_setdrawop(Display*, Drawop);
+
+#define	BGSHORT(p)	((p)[0]|((p)[1]<<8))
+#define	BGLONG(p)	((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24))
+#define BPSHORT(p,v)	do{ushort _v_=(v);(p)[0]=_v_;(p)[1]=_v_>>8;}while(0)
+#define BPLONG(p,v)	do{ulong _v_=(v);(p)[0]=_v_;(p)[1]=_v_>>8;(p)[2]=_v_>>16;(p)[3]=_v_>>24;}while(0)
+
+/*
+ * Compressed image file parameters and helper routines
+ */
+#define	NMATCH	3		/* shortest match possible */
+#define	NRUN	(NMATCH+31)	/* longest match possible */
+#define	NMEM	1024		/* window size */
+#define	NDUMP	128		/* maximum length of dump */
+#define	NCBLOCK	6000		/* size of compressed blocks */
+extern	void	_twiddlecompressed(uchar*, int);
+extern	int	_compblocksize(Rectangle, int);
+
+extern	ulong	drawld2chan[];
+extern	void	drawsetdebug(int);
--- a/meson.build
+++ b/meson.build
@@ -1,8 +1,8 @@
 srcs = [
     'x9dev.c',
-    'draw.c',
-    'c9/c9.c',
-    'c9/c9.h',
+    'keyboard.c',
+    'mouse.c',
+    'screen.c',
     '../../mi/miinitext.c',
     '../../mi/mi.h',
     'x9dev.h',
@@ -18,8 +18,9 @@
     srcs,
     include_directories: inc, 
     dependencies: common_dep,
-    object: '/usr/local/plan9/lib/libdraw.a',
     link_with: [
+        c9,
+        libdraw,
         libxserver_main,
         libxserver_fb,
         libxserver,
--- /dev/null
+++ b/mouse.c
@@ -1,0 +1,141 @@
+/*
+ * Copyright (c) 2020 Michael Misch <michaelmisch1985@gmail.com> 
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "x9dev.h"
+
+extern DeviceIntPtr x9devMouse;
+
+#define e    ev.u.u
+#define ek    ev.u.keyButtonPointer
+static void
+x9devSendMouseEvent(int x, int y, int b, int t)
+{
+    xEvent ev;
+
+    memset(&ev, 0, sizeof(xEvent));
+    e.type = t;
+    e.detail = b;
+    ek.rootX = x;
+    ek.rootY = y;
+    ek.time = GetTimeInMillis();
+    mieqEnqueue(x9devMouse, (InternalEvent *)&ev);
+}
+#undef ek
+#undef e
+
+static int
+x9devMouseRead(int *x, int *y, int *b)
+{
+    int n;
+
+    /* Magic numbers here are the size of a message from /dev/mouse and its offsets */
+    if((n = x9read(x9di.ctx, x9di.mouse, 1 + 4 * 12)) <= 0)
+        return 0;
+
+    if (n != 1 + 4 * 12)
+        FatalError("Bad mouse event");
+
+    if (buf[0] == 'r') {
+        x9devResize();
+        return 0;
+    }
+
+    *x = atoi(x9di.mouse->rdbuf + 1 + 0 * 12) - x9di.screen->r.x;
+    *y = atoi(x9di.mouse->rdbuf + 1 + 1 * 12) - x9di.screen->r.y;
+    *b = atoi(x9di.mouse->rdbuf + 1 + 2 * 12);
+
+    return 1;
+}
+
+
+static int  
+x9devMouseHandle(void)
+{
+    int x, y, b, but, t;
+
+    if (!x9devMouseRead(&x, &y, &but))
+        return 0;
+
+    t = b = 0;
+    if (x != oldx || y != oldy) {
+        t = MotionNotify;
+        oldx = x, oldy = y;
+    }
+    if (but != oldbut) {
+        b = oldbut ^ but;
+        t = ButtonPress;
+        if (oldbut & b)
+            t = ButtonRelease;
+        if (b == 4)
+            b = 3;
+        if (but & (8 | 16)) {
+            if (b & 8)
+                b = 4;
+            else
+                b = 5;
+            x9devSendMouseEvent(x, y, b, ButtonPress);
+            x9devSendMouseEvent(x, y, b, ButtonRelease);
+            return 1;
+        }
+    }
+    x9devSendMouseEvent(x, y, b, t);
+    oldbut = but;
+
+    return 1;
+}
+
+
+int  
+x9devMouseProc(DeviceIntPtr pDevice, int what)
+{
+    static unsigned char    map[] = {0, 1, 2, 3, 4, 5};
+    DevicePtr pDev = (DevicePtr)pDevice;
+    Atom btn_labels[3] = {0};
+    Atom axes_labels[2] = {0};
+
+    switch (what) {
+    case DEVICE_INIT:
+        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+
+        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+        InitPointerDeviceStruct(pDev, map, 3, btn_labels,
+            (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2, axes_labels);
+        break;
+
+    case DEVICE_ON:
+        pDev->on = TRUE;
+        break;
+
+    case DEVICE_CLOSE:
+    case DEVICE_OFF:
+        pDev->on = FALSE;
+        break;
+    }
+    return Success;
+}
\ No newline at end of file
--- /dev/null
+++ b/screen.c
@@ -1,0 +1,191 @@
+/*
+ * Copyright (c) 2020 Michael Misch <michaelmisch1985@gmail.com> 
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "x9dev.h"
+
+static void
+x9devRefreshScreen(int x1, int y1, int x2, int y2)
+{
+    /*
+    Rectangle r;
+    uchar *p;
+    int n;
+
+    p = (uchar *)x9di.fb+(y1*x9di.width+x1)*(x9di.depth/8);
+    r = rectaddpt(Rect(x1, y1, x2, y2), screen->r.min);
+    if (Dx(r) == x9di.width) {
+        if (loadimage(screen, r, p, x9di.bpl * Dy(r)) < 0)
+            FatalError("can't load image");
+        goto End;
+    }
+    n = Dx(r)*(x9di.depth/8);
+    y2 += screen->r.min.y;
+       while(r.min.y < y2) {
+        r.max.y = r.min.y+1;
+        if (loadimage(screen, r, p, n) < 0)
+            FatalError("can't load image");
+        p += x9di.bpl;
+        r.min.y++;
+    }
+
+End:
+    flushimage(display, 1);
+    */
+}
+
+
+static void
+x9devResize(void)
+{
+    /* 
+    if (getwindow(display, Refnone) < 0)
+        FatalError("can't reattach to window");
+
+    draw(screen, screen->r, display->white, nil, ZP);
+    x9devRefreshScreen(0, 0, x9di.width, x9di.height);
+    */
+}
+
+static void
+x9devWakeupHandler(ScreenPtr scr, int result)
+{
+    if (result <= 0)
+        return;
+
+    while (x9devMouseHandle())
+        ;
+    while (x9devKeybdHandle())
+        ;
+}
+
+static void
+x9devShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
+{
+    BoxPtr pbox;
+
+    pbox = REGION_EXTENTS(pScreen, &pBuf->pDamage);
+    x9devRefreshScreen(pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+}
+
+
+static void
+x9devCursorLimits(DeviceIntPtr dptr, ScreenPtr spr, CursorPtr cpr, BoxPtr hot, BoxPtr topleft)
+{
+    *topleft = *hot;
+}
+
+
+/* callback dance... */
+static CreateScreenResourcesProcPtr x9devCreateResourcesPtr;
+
+static Bool
+x9devCreateResources(ScreenPtr pScreen)
+{
+    Bool ret = 0;
+
+    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
+    if (pScreen->CreateScreenResources)
+        ret = pScreen->CreateScreenResources(pScreen);
+
+    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
+    if (ret == FALSE)
+        return FALSE;
+
+    shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
+    if (!shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), x9devShadowUpdate, NULL, SHADOW_ROTATE_0, 0))
+        return FALSE;
+
+    return ret;
+}
+
+Bool
+x9devScreenInit(ScreenPtr pScreen, int argc, char *argv[])
+{
+    int v, i;
+    unsigned long   r, g, b;
+    static int  first = 1;
+
+    if (first) {
+        x9devInfoInit();
+        first = 0;
+    }
+
+    for (i = 0; i < NUMFORMATS; i++)
+        fbSetVisualTypes(formats[i].depth, 0, 8);
+
+    switch (x9di.depth) {
+    case 16:
+        r = 0xF800, g = 0x07E0, b = 0x001F;
+        v = 1 << TrueColor;
+        break;
+    case 24:
+    case 32:
+        r = 0xFF0000, g = 0x00FF00, b = 0x0000FF;
+        v = 1 << TrueColor;
+        break;
+    default:
+        r = g = b = 0;
+        v = 1 << PseudoColor;
+    }
+    if (!fbSetVisualTypesAndMasks(x9di.depth, v, 8, r, g, b))
+        return FALSE;
+
+    if (!fbScreenInit(pScreen, x9di.fb, x9di.width, x9di.height,
+        x9di.dpi, x9di.dpi, x9di.width, x9di.depth))
+        return FALSE;
+
+    pScreen->mmWidth = x9di.width * 25.4 / x9di.dpi;
+    pScreen->mmHeight = x9di.height * 25.4 / x9di.dpi;
+
+    /* cursor */
+    pScreen->ConstrainCursor = x9devConstrainCursor;
+    pScreen->CursorLimits = x9devCursorLimits;
+    pScreen->DisplayCursor = x9devDisplayCursor;
+    pScreen->RealizeCursor = x9devRealizeCursor;
+    pScreen->UnrealizeCursor = x9devUnrealizeCursor;
+    pScreen->RecolorCursor = x9devRecolorCursor;
+    pScreen->SetCursorPosition = x9devSetCursorPosition;
+
+    pScreen->SaveScreen = x9devSaveScreen;
+    pScreen->WakeupHandler = x9devWakeupHandler;
+
+#ifdef RENDER
+    if (!fbPictureInit(pScreen, 0, 0))
+        return FALSE;
+#endif
+
+   if (!shadowSetup(pScreen))
+        return FALSE;
+
+    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = x9devCreateResources;
+
+    if (!fbCreateDefColormap(pScreen))
+        return FALSE;
+
+    return TRUE;
+}
--- a/x9dev.c
+++ b/x9dev.c
@@ -26,6 +26,42 @@
 #endif
 #include "x9dev.h"
 
+
+static void
+x9devInfoInit(void)
+{
+    /* 
+    if(initdraw(NULL, 0, "x9dev") < 0)
+        FatalError("can't open display");
+
+    x9di.depth = screen->depth;
+    x9di.width = Dx(screen->r);
+    x9di.width -= x9di.width&(screen->depth/8);
+    x9di.dpi = 100;
+    x9di.bpl = bytesperline(Rect(0, 0, x9di.width, x9di.height), x9di.depth);
+    x9di.fb = malloc(x9di.bpl * x9di.height);
+    if (x9di.fb == nil)
+        FatalError("couldn't allocate framebuffer");
+
+    snprint(buf, sizeof buf, "%s/mouse", display->devdir);
+    x9di.mouseFd = c9open(buf, O_RDWR | O_NONBLOCK);
+    if(x9di.mouseFd < 0)
+        FatalError("can't open mouse");
+
+    snprint(buf, sizeof buf, "%s/cons", display->devdir);
+    x9di.keybdFd = c9open(buf, O_RDONLY | O_NONBLOCK);
+    if(x9di.keybdFd < 0)
+        FatalError("can't open keyboard");
+
+    snprint(buf, sizeof buf, "%s/consctl", display->devdir);
+    x9di.consctlFd = c9open(buf, O_WRONLY);
+    if(x9di.consctlFd < 0)
+        FatalError("can't open consctl");
+    if(c9write(x9di.consctlFd, "rawon", 5) != 5)
+        FatalError("can't set rawon");
+    */
+}
+
 void
 InitOutput(ScreenInfo *si, int argc, char *argv[])
 {
--- a/x9dev.h
+++ b/x9dev.h
@@ -56,10 +56,18 @@
 #include "c9/c9.h"
 
 #define Msize 8192
-#define KF      0xF000
-#define Kdown   0x80
 #define NUMFORMATS (sizeof(formats)/sizeof((formats)[0]))
 
+/* NOOPs for now */
+#define x9devSaveScreen (void *) NoopDDA
+#define x9devConstrainCursor    (void *) NoopDDA
+#define x9devDisplayCursor  (void *) NoopDDA
+#define x9devRealizeCursor  (void *) NoopDDA
+#define x9devUnrealizeCursor    (void *) NoopDDA
+#define x9devRecolorCursor  (void *) NoopDDA
+#define x9devSetCursorPosition  (void *) NoopDDA
+
+
 typedef struct x9file x9file;
 struct x9file {
 	uint8_t     rdbuf[Msize];
@@ -96,6 +104,7 @@
 
 DeviceIntPtr x9devMouse;
 DeviceIntPtr x9devKeybd;
+x9devInfo x9di;
 
 Bool x9checkmod(unsigned int, DeviceIntPtr);
 Bool x9devScreenInit(ScreenPtr, int, char **);