8 #include <linux/input.h>
12 #include <X11/Xutil.h>
13 #include <X11/keysym.h>
14 #include <X11/extensions/XShm.h>
19 /* --------------------------------------------------------------------------- */
29 /* framebuffer -- x11 */
31 unsigned char *xidata;
32 XShmSegmentInfo shminfo;
34 /* framebuffer -- kernel */
35 struct fb_fix_screeninfo fix;
36 struct fb_var_screeninfo var;
39 /* --------------------------------------------------------------------------- */
42 * map X11 keycodes to linux keycodes
44 * WARNING: X11 keycodes are not portable, this likely breaks as soon
45 * as one uses a X-Server not running on a linux machine as display.
47 * Using portable keysyms instead creates some strange and hard to
48 * handle keymapping effects through. That happens because both host
49 * and uml machine are mapping keys then ...
51 static int x11_keymap[] = {
65 [ 22 ] = KEY_BACKSPACE,
78 [ 34 ] = KEY_LEFTBRACE,
79 [ 35 ] = KEY_RIGHTBRACE,
82 [ 37 ] = KEY_LEFTCTRL,
92 [ 47 ] = KEY_SEMICOLON,
93 [ 48 ] = KEY_APOSTROPHE,
96 [ 50 ] = KEY_LEFTSHIFT,
97 [ 51 ] = KEY_BACKSLASH,
108 [ 62 ] = KEY_RIGHTSHIFT,
110 [ 63 ] = KEY_KPASTERISK,
111 [ 64 ] = KEY_LEFTALT,
113 [ 66 ] = KEY_CAPSLOCK,
125 [ 77 ] = KEY_NUMLOCK,
126 [ 78 ] = KEY_SCROLLLOCK,
131 [ 82 ] = KEY_KPMINUS,
142 // [ 92 ] = KEY_Print,
143 // [ 93 ] = KEY_Mode_switch,
155 [ 105 ] = KEY_PAGEDOWN,
156 [ 106 ] = KEY_INSERT,
157 [ 107 ] = KEY_DELETE,
159 // [ 108 ] = KEY_KP_Enter,
160 [ 109 ] = KEY_RIGHTCTRL,
161 // [ 110 ] = KEY_Pause,
162 // [ 111 ] = KEY_Print,
163 // [ 112 ] = KEY_KP_Divide,
164 [ 113 ] = KEY_RIGHTALT,
165 // [ 114 ] = KEY_Pause,
166 // [ 115 ] = KEY_Super_L,
167 // [ 116 ] = KEY_Super_R,
169 // [ 124 ] = KEY_ISO_Level3_Shift,
170 // [ 126 ] = KEY_KP_Equal,
173 static void x11_kbd(struct x11_window *win, struct x11_kerndata *kd, XEvent *e)
175 int key = KEY_RESERVED;
177 if (e->xkey.keycode < sizeof(x11_keymap)/sizeof(x11_keymap[0]))
178 key = x11_keymap[e->xkey.keycode];
179 if (KEY_RESERVED != key) {
180 x11_kbd_input(kd, key, e->type == KeyPress);
182 x11_kbd_input(kd, KEY_MAX + e->xkey.keycode, e->type == KeyPress);
186 /* --------------------------------------------------------------------------- */
188 static int mitshm_err;
191 catch_no_mitshm(Display * dpy, XErrorEvent * event)
197 static void init_color(int32_t mask, struct fb_bitfield *bf)
201 memset(bf, 0, sizeof(*bf));
202 for (i = 0; i < 32; i++) {
203 if (mask & ((int32_t)1 << i))
205 else if (!bf->length)
210 struct x11_window *x11_open(int width, int height)
212 char *title = "user mode linux framebuffer";
213 struct x11_window *win;
216 XVisualInfo *info, template;
220 win = malloc(sizeof(*win));
224 win->dpy = XOpenDisplay(NULL);
225 if (NULL == win->dpy)
228 /* get visual info */
229 template.screen = XDefaultScreen(win->dpy);
230 template.depth = DefaultDepth(win->dpy, DefaultScreen(win->dpy));
231 info = XGetVisualInfo(win->dpy, VisualScreenMask | VisualDepthMask,
236 bytes_pp = (win->vi.depth+7)/8;
238 if (win->vi.class != TrueColor && win->vi.class != DirectColor)
243 old_handler = XSetErrorHandler(catch_no_mitshm);
244 win->ximage = XShmCreateImage(win->dpy,win->vi.visual,win->vi.depth,
245 ZPixmap, NULL, &win->shminfo,
247 if (NULL == win->ximage)
249 win->shminfo.shmid = shmget(IPC_PRIVATE,
250 win->ximage->bytes_per_line * win->ximage->height,
252 if (-1 == win->shminfo.shmid)
254 win->shminfo.shmaddr = (char *) shmat(win->shminfo.shmid, 0, 0);
255 if ((void *)-1 == win->shminfo.shmaddr)
258 win->ximage->data = win->shminfo.shmaddr;
259 win->shminfo.readOnly = False;
260 XShmAttach(win->dpy, &win->shminfo);
261 XSync(win->dpy, False);
264 shmctl(win->shminfo.shmid, IPC_RMID, 0);
265 XSetErrorHandler(old_handler);
269 /* can't use shared memory -- cleanup and try without */
271 XDestroyImage(win->ximage);
274 if ((void *)-1 != win->shminfo.shmaddr && NULL != win->shminfo.shmaddr)
275 shmdt(win->shminfo.shmaddr);
276 XSetErrorHandler(old_handler);
278 memset(&win->shminfo,0,sizeof(win->shminfo));
279 if (NULL == (win->xidata = malloc(width * height * bytes_pp)))
282 win->ximage = XCreateImage(win->dpy, win->vi.visual, win->vi.depth,
283 ZPixmap, 0, win->xidata,
284 width, height, 8, 0);
288 win->var.xres = width;
289 win->var.xres_virtual = width;
290 win->var.yres = height;
291 win->var.yres_virtual = height;
292 win->var.bits_per_pixel = bytes_pp * 8;
293 win->var.pixclock = 10000000 / win->var.xres * 1000 / win->var.yres;
294 win->var.left_margin = (win->var.xres / 8) & 0xf8;
295 win->var.hsync_len = (win->var.xres / 8) & 0xf8;
297 init_color(win->vi.red_mask, &win->var.red);
298 init_color(win->vi.green_mask, &win->var.green);
299 init_color(win->vi.blue_mask, &win->var.blue);
301 win->var.activate = FB_ACTIVATE_NOW;
302 win->var.height = -1;
304 win->var.right_margin = 32;
305 win->var.upper_margin = 16;
306 win->var.lower_margin = 4;
307 win->var.vsync_len = 4;
308 win->var.vmode = FB_VMODE_NONINTERLACED;
311 win->fix.smem_start = ;
312 win->fix.smem_len = ;
314 win->fix.line_length = win->ximage->bytes_per_line;
315 win->fix.visual = FB_VISUAL_TRUECOLOR;
317 strcpy(win->fix.id,"x11");
318 win->fix.type = FB_TYPE_PACKED_PIXELS;
319 win->fix.accel = FB_ACCEL_NONE;
321 /* create + init window */
322 hints.flags = PMinSize | PMaxSize;
323 hints.min_width = width;
324 hints.min_height = height;
325 hints.max_width = width;
326 hints.max_height = height;
327 XStringListToTextProperty(&title,1,&prop);
329 win->root = RootWindow(win->dpy, DefaultScreen(win->dpy));
330 win->win = XCreateSimpleWindow(win->dpy, win->root,
332 CopyFromParent, CopyFromParent,
333 BlackPixel(win->dpy, DefaultScreen(win->dpy)));
334 win->gc = XCreateGC(win->dpy, win->win, 0, NULL);
335 XSelectInput(win->dpy, win->win,
336 KeyPressMask | KeyReleaseMask | /* virtual keyboard */
337 ButtonPressMask | ButtonReleaseMask | /* mouse (touchscreen?) */
338 PointerMotionMask | ExposureMask | StructureNotifyMask |
340 XMapWindow(win->dpy,win->win);
341 XSetWMNormalHints(win->dpy,win->win,&hints);
342 XSetWMName(win->dpy,win->win,&prop);
343 win->delete_window = XInternAtom(win->dpy, "WM_DELETE_WINDOW", False);
344 XSetWMProtocols(win->dpy, win->win, &win->delete_window, 1);
355 int x11_get_fd(struct x11_window *win)
357 return ConnectionNumber(win->dpy);
360 struct fb_fix_screeninfo* x11_get_fix(struct x11_window *win)
365 struct fb_var_screeninfo* x11_get_var(struct x11_window *win)
370 void* x11_get_fbmem(struct x11_window *win)
372 return win->ximage->data;
375 int x11_blit_fb(struct x11_window *win, int x1, int y1, int x2, int y2)
377 if (win->shminfo.shmid)
378 XShmPutImage(win->dpy, win->win, win->gc, win->ximage,
379 x1,y1,x1,y1, x2-x1,y2-y1, True);
381 XPutImage(win->dpy, win->win, win->gc, win->ximage,
382 x1,y1,x1,y1, x2-x1,y2-y1);
387 int x11_has_data(struct x11_window *win, struct x11_kerndata *kd)
392 while (True == XCheckMaskEvent(win->dpy, ~0, &e)) {
397 x11_kbd(win, kd, &e);
401 x11_mouse_input(kd, e.xbutton.state, e.xbutton.x, e.xbutton.y);
404 x11_mouse_input(kd, e.xmotion.state, e.xmotion.x, e.xmotion.y);
407 if (0 == e.xexpose.count)
408 x11_blit_fb(win, 0,0, win->var.xres, win->var.yres);
411 /* hmm, don't get client messages ... */
412 if (e.xclient.data.l[0] == win->delete_window)