commit 4eb513ebff25ba37f57510f06bce12d93619311f
parent 52d8d3065033ce837d7d346dd6236d6ffe7fec56
Author: pancake <pancake@nopcode.org>
Date: Thu, 1 Jul 2010 21:53:23 +0200
initial import of the x11 backend
Diffstat:
Makefile | | | 12 | ++++++++++++ |
gi_x11.c | | | 263 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 275 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -10,13 +10,25 @@ CFLAGS+=-I.
# graphic backend
GI?=sdl
+ifeq (${GI},sdl)
GI_LIBS=-lSDL -lSDL_ttf -lSDL_image
+else
+ifeq (${GI},x11)
+GI_LIBS=-lX11
+endif
+endif
GI_OBJS=gi_${GI}.o
GI_SRCS=gi_${GI}.c
all: static shared t
+x:
+ make clean ; make GI=x11 && cd t ; ./test
+
+s:
+ make clean ; make GI=sdl && cd t ; ./test
+
t:
cd t && ${MAKE} all
diff --git a/gi_x11.c b/gi_x11.c
@@ -0,0 +1,263 @@
+/* See LICENSE file for copyright and license details. */
+#define _BSD_SOURCE // strdup
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <locale.h>
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "swk.h"
+#define SWK
+#include "config.h"
+
+#define FONTNAME "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*"
+#define FONTFACTOR 2 /* XXX */
+
+static Drawable drawable;
+static GC gc;
+static int fs = FONTSIZE; // TODO: we need fsW and fsH
+static Window window;
+static XFontSet set;
+static int screen;
+static Display *display = NULL;
+static int has_event = 0;
+static XEvent lastev;
+static int first = 1;
+#define EVENTMASK PointerMotionMask | ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask
+
+int
+swk_gi_fontsize(int sz) {
+ fs += sz*2;
+ /* TODO */
+ return 1;
+}
+
+int
+swk_gi_init(SwkWindow *w) {
+ if(first) {
+ first = 0;
+ display = XOpenDisplay(NULL);
+ if (display == NULL) {
+ fprintf(stderr, "Cannot open display\n");
+ return 0;
+ }
+ screen = DefaultScreen(display);
+ window = XCreateSimpleWindow(display,
+ RootWindow(display, screen),
+ 10, 10, w->r.w, w->r.h, 1,
+ BlackPixel(display, screen),
+ WhitePixel(display, screen));
+ gc = XCreateGC(display, window, 0, NULL);
+ drawable = XCreatePixmap(display, window, w->r.w, w->r.h, DefaultDepth(display, screen));
+ XSelectInput(display, window, EVENTMASK);
+ XMapWindow(display, window);
+ }
+ return swk_gi_fontsize(0);
+}
+
+int
+swk_gi_update(SwkWindow *w) {
+ XWindowAttributes wa;
+ XGetWindowAttributes(display, window, &wa);
+ w->r.w = (wa.width / fs)-1;
+ w->r.h = (wa.height / fs)-1;
+ return 1;
+}
+
+void
+swk_gi_exit() {
+ XCloseDisplay(display);
+}
+
+int
+swk_gi_has_event(SwkWindow *w) {
+ if(!has_event)
+ has_event = XNextEvent(display, &lastev); // XXX This must be nonblocking
+ return has_event;
+}
+
+SwkEvent *
+swk_gi_event(SwkWindow *w, int dowait) {
+ static int mousedowny, mousedownx, mousedown = 0;
+ static int mousemoved = 0;
+ KeySym ksym;
+ XEvent event;
+ SwkEvent *ret = &w->_e;
+
+ if(has_event) event = lastev;
+ else has_event = !XNextEvent(display, &event);
+
+ if(has_event);
+ switch(event.type) {
+ default: ret = NULL; break;
+ case Expose:
+ ret->type = EExpose;
+ ret->data.expose.x = ret->data.expose.y = \
+ ret->data.expose.w = ret->data.expose.h = 0;
+ break;
+ case VisibilityNotify:
+ printf("visi\n");
+ break;
+ case MotionNotify:
+ // TODO: move this stuff into swk.c.. shoudlnt be backend dependent
+// fprintf(stderr, "event: motion (%d,%d)\n", event.motion.x,event.motion.y);
+ if(mousedown) {
+ // touchscreen spaguetti trick
+ if(mousedowny==-1) mousedowny = event.xmotion.y; else mousemoved = 1;
+ if(mousedownx==-1) mousedownx = event.xmotion.x; else mousemoved = 1;
+ if(event.xmotion.y>mousedowny+fs) {
+ mousedowny = event.xmotion.y;
+ swk_scroll_up(w);
+ } else
+ if(event.xmotion.y<mousedowny-fs) {
+ mousedowny = event.xmotion.y;
+ swk_scroll_down(w);
+ }
+ if(event.xmotion.x>mousedownx+fs) {
+ mousedownx = event.xmotion.x;
+ swk_column_move_right();
+ swk_column_move_right();
+ } else
+ if(event.xmotion.x<mousedownx-fs) {
+ mousedownx = event.xmotion.x;
+ swk_column_move_left();
+ swk_column_move_left();
+ }
+ ret->type = EExpose;
+ ret->data.expose.x = ret->data.expose.y = \
+ ret->data.expose.w = ret->data.expose.h = 0;
+ } else {
+ ret->type = EMotion;
+ ret->data.motion.x = event.xmotion.x / fs;
+ ret->data.motion.y = event.xmotion.y / fs;
+ }
+ break;
+ case ButtonRelease:
+ //fprintf(stderr, "event: up %d (%d,%d)\n", event.button.button,event.button.x,event.button.y);
+ mousedown = 0;
+ if(!mousemoved) {
+ ret->type = EClick;
+ ret->data.click.button = event.xbutton.state;
+ ret->data.click.point.x = event.xbutton.x / fs;
+ ret->data.click.point.y = event.xbutton.y / fs;
+ }
+ break;
+ case ButtonPress:
+ //fprintf(stderr, "event: down %d (%d,%d)\n", event.button.button,event.button.x,event.button.y);
+ mousemoved = 0;
+ mousedown = 1;
+ mousedowny = event.xbutton.y;
+ break;
+ case KeyPress:
+ printf ("KEY PRESSED\n");
+ ret->data.key.modmask = 0;
+ ret->type = EKey;
+ //num = XLookupString(&event, buf, sizeof buf, &ksym, NULL);
+ XLookupString(&event, NULL, 0, &ksym, NULL);
+printf("ksym=%d\n", ksym);
+ ret->data.key.keycode = ksym;
+ if(event.xkey.state&ShiftMask)
+ ret->data.key.modmask |= Shift;
+ if(event.xkey.state&Mod1Mask)
+ ret->data.key.modmask |= Alt;
+ if(event.xkey.state&ControlMask)
+ ret->data.key.modmask |= Ctrl;
+ fprintf(stderr, "event: key %d %d\n",
+ ret->data.key.modmask, ret->data.key.keycode);
+ break;
+ case 0://SDL_QUIT:
+ ret->type = EQuit;
+ break;
+ }
+ has_event = 0;
+ return ret;
+}
+
+void
+swk_gi_clear() {
+ XClearWindow(display, window);
+}
+
+void
+swk_gi_flip() {
+#if 0
+ XWindowAttributes wa;
+ XGetWindowAttributes(display, window, &wa);
+ XCopyArea(display, drawable, window, gc, 0, 0, wa.width, wa.height, 0, 0);
+ XFlush(display);
+#endif
+}
+
+/* -- drawing primitives -- */
+void
+swk_gi_line(int x1, int y1, int x2, int y2, int color) {
+ Rect r = { x1, y1, x2, y2 };
+ if(!x2 || !y2)
+ swk_gi_fill(r, color, 0);
+ // TODO: add support for diagonal lines?
+}
+
+void
+swk_gi_fill(Rect r, int color, int lil) {
+ XRectangle area = { r.x*fs, r.y*fs, r.w*fs, r.h*fs };
+ if(lil) {
+ const int s = fs/4;
+ area.x += s;
+ area.y += s;
+ area.width -= (s*2);
+ area.height -= (s*2);
+ }
+ if(!area.width) area.width = 1;
+ if(!area.height) area.height = 1;
+ XFillRectangles(display, window, DefaultGC(display, screen), &area, 1);
+}
+
+void
+swk_gi_rect(Rect r, int color) {
+ swk_gi_line(r.x, r.y, r.w, 0, color);
+ swk_gi_line(r.x, r.y+r.h, r.w, 0, color);
+ swk_gi_line(r.x, r.y, 0, r.h, color);
+ swk_gi_line(r.x+r.w, r.y, 0, r.h, color);
+}
+
+void
+swk_gi_text(Rect r, const char *text) {
+ if(!text||!*text)
+ return;
+ XDrawString(display, window, DefaultGC(display, screen), r.x*fs, (1+r.y)*fs, text, strlen (text));
+}
+
+void
+swk_gi_img(Rect r, void *img) {
+ /* TODO */
+}
+
+/* image api */
+void*
+swk_gi_img_new(int w, int h, int color) {
+ /* TODO */
+ return NULL;
+}
+
+void*
+swk_gi_img_load(const char *str) {
+ /* TODO */
+ return NULL;
+}
+
+void
+swk_gi_img_free(void *s) {
+ /* TODO */
+}
+
+void
+swk_gi_img_set(void *img, int x, int y, int color) {
+ /* TODO */
+}
+
+int
+swk_gi_img_get(void *img, int x, int y) {
+ /* TODO */
+ return 0;
+}