/[gxemul]/upstream/0.4.6/src/x11.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.6/src/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 23243 byte(s)
0.4.6
1 /*
2 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: x11.c,v 1.65 2007/06/15 17:02:38 debug Exp $
29 *
30 * X11-related functions.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "console.h"
38 #include "emul.h"
39 #include "machine.h"
40 #include "misc.h"
41 #include "x11.h"
42
43
44 #ifndef WITH_X11
45
46
47 /* Dummy functions: */
48 void x11_redraw_cursor(struct machine *m, int i) { }
49 void x11_redraw(struct machine *m, int x) { }
50 void x11_putpixel_fb(struct machine *m, int fb, int x, int y, int color) { }
51 void x11_init(struct machine *machine) { }
52 struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
53 int scaledown, struct machine *machine)
54 { return NULL; }
55 void x11_check_event(struct emul **emuls, int n_emuls) { }
56
57
58 #else /* WITH_X11 */
59
60
61 #include <X11/Xlib.h>
62 #include <X11/Xutil.h>
63 #include <X11/cursorfont.h>
64
65
66 /*
67 * x11_redraw_cursor():
68 *
69 * Redraw a framebuffer's X11 cursor.
70 *
71 * NOTE: It is up to the caller to call XFlush.
72 */
73 void x11_redraw_cursor(struct machine *m, int i)
74 {
75 int last_color_used = 0;
76 int n_colors_used = 0;
77 struct fb_window *fbwin = m->x11_md.fb_windows[i];
78
79 /* Remove old cursor, if any: */
80 if (fbwin->x11_display != NULL && fbwin->OLD_cursor_on) {
81 XPutImage(fbwin->x11_display, fbwin->x11_fb_window,
82 fbwin->x11_fb_gc, fbwin->fb_ximage,
83 fbwin->OLD_cursor_x/fbwin->scaledown,
84 fbwin->OLD_cursor_y/fbwin->scaledown,
85 fbwin->OLD_cursor_x/fbwin->scaledown,
86 fbwin->OLD_cursor_y/fbwin->scaledown,
87 fbwin->OLD_cursor_xsize/fbwin->scaledown + 1,
88 fbwin->OLD_cursor_ysize/fbwin->scaledown + 1);
89 }
90
91 if (fbwin->x11_display != NULL && fbwin->cursor_on) {
92 int x, y, subx, suby;
93 XImage *xtmp;
94
95 CHECK_ALLOCATION(xtmp = XSubImage(fbwin->fb_ximage,
96 fbwin->cursor_x/fbwin->scaledown,
97 fbwin->cursor_y/fbwin->scaledown,
98 fbwin->cursor_xsize/fbwin->scaledown + 1,
99 fbwin->cursor_ysize/fbwin->scaledown + 1));
100
101 for (y=0; y<fbwin->cursor_ysize;
102 y+=fbwin->scaledown)
103 for (x=0; x<fbwin->cursor_xsize;
104 x+=fbwin->scaledown) {
105 int px = x/fbwin->scaledown;
106 int py = y/fbwin->scaledown;
107 int p = 0, n = 0, c = 0;
108 unsigned long oldcol;
109
110 for (suby=0; suby<fbwin->scaledown;
111 suby++)
112 for (subx=0; subx<fbwin->
113 scaledown; subx++) {
114 c = fbwin->
115 cursor_pixels[y+suby]
116 [x+subx];
117 if (c >= 0) {
118 p += c;
119 n++;
120 }
121 }
122 if (n > 0)
123 p /= n;
124 else
125 p = c;
126
127 if (n_colors_used == 0) {
128 last_color_used = p;
129 n_colors_used = 1;
130 } else
131 if (p != last_color_used)
132 n_colors_used = 2;
133
134 switch (p) {
135 case CURSOR_COLOR_TRANSPARENT:
136 break;
137 case CURSOR_COLOR_INVERT:
138 oldcol = XGetPixel(xtmp, px, py);
139 if (oldcol != fbwin->
140 x11_graycolor[N_GRAYCOLORS-1].pixel)
141 oldcol = fbwin->
142 x11_graycolor[N_GRAYCOLORS
143 -1].pixel;
144 else
145 oldcol = fbwin->
146 x11_graycolor[0].pixel;
147 XPutPixel(xtmp, px, py, oldcol);
148 break;
149 default: /* Normal grayscale: */
150 XPutPixel(xtmp, px, py, fbwin->
151 x11_graycolor[p].pixel);
152 }
153 }
154
155 XPutImage(fbwin->x11_display,
156 fbwin->x11_fb_window,
157 fbwin->x11_fb_gc,
158 xtmp, 0, 0,
159 fbwin->cursor_x/fbwin->scaledown,
160 fbwin->cursor_y/fbwin->scaledown,
161 fbwin->cursor_xsize/fbwin->scaledown,
162 fbwin->cursor_ysize/fbwin->scaledown);
163
164 XDestroyImage(xtmp);
165
166 fbwin->OLD_cursor_on = fbwin->cursor_on;
167 fbwin->OLD_cursor_x = fbwin->cursor_x;
168 fbwin->OLD_cursor_y = fbwin->cursor_y;
169 fbwin->OLD_cursor_xsize =
170 fbwin->cursor_xsize;
171 fbwin->OLD_cursor_ysize =
172 fbwin->cursor_ysize;
173 }
174
175 /* printf("n_colors_used = %i\n", n_colors_used); */
176
177 if (fbwin->host_cursor != 0 && n_colors_used < 2) {
178 /* Remove the old X11 host cursor: */
179 XUndefineCursor(fbwin->x11_display,
180 fbwin->x11_fb_window);
181 XFreeCursor(fbwin->x11_display,
182 fbwin->host_cursor);
183 fbwin->host_cursor = 0;
184 }
185
186 if (n_colors_used >= 2 && fbwin->host_cursor == 0) {
187 GC tmpgc;
188
189 /* Create a new X11 host cursor: */
190 /* cursor = XCreateFontCursor(fbwin->x11_display,
191 XC_coffee_mug); :-) */
192 if (fbwin->host_cursor_pixmap != 0) {
193 XFreePixmap(fbwin->x11_display,
194 fbwin->host_cursor_pixmap);
195 fbwin->host_cursor_pixmap = 0;
196 }
197 fbwin->host_cursor_pixmap =
198 XCreatePixmap(fbwin->x11_display,
199 fbwin->x11_fb_window, 1, 1, 1);
200 XSetForeground(fbwin->x11_display,
201 fbwin->x11_fb_gc,
202 fbwin->x11_graycolor[0].pixel);
203
204 tmpgc = XCreateGC(fbwin->x11_display,
205 fbwin->host_cursor_pixmap, 0,0);
206
207 XDrawPoint(fbwin->x11_display,
208 fbwin->host_cursor_pixmap,
209 tmpgc, 0, 0);
210
211 XFreeGC(fbwin->x11_display, tmpgc);
212
213 fbwin->host_cursor =
214 XCreatePixmapCursor(fbwin->x11_display,
215 fbwin->host_cursor_pixmap,
216 fbwin->host_cursor_pixmap,
217 &fbwin->x11_graycolor[N_GRAYCOLORS-1],
218 &fbwin->x11_graycolor[N_GRAYCOLORS-1],
219 0, 0);
220 if (fbwin->host_cursor != 0) {
221 XDefineCursor(fbwin->x11_display,
222 fbwin->x11_fb_window,
223 fbwin->host_cursor);
224 }
225 }
226 }
227
228
229 /*
230 * x11_redraw():
231 *
232 * Redraw X11 windows.
233 */
234 void x11_redraw(struct machine *m, int i)
235 {
236 if (i < 0 || i >= m->x11_md.n_fb_windows ||
237 m->x11_md.fb_windows[i]->x11_fb_winxsize <= 0)
238 return;
239
240 x11_putimage_fb(m, i);
241 x11_redraw_cursor(m, i);
242 XFlush(m->x11_md.fb_windows[i]->x11_display);
243 }
244
245
246 /*
247 * x11_putpixel_fb():
248 *
249 * Output a framebuffer pixel. i is the framebuffer number.
250 */
251 void x11_putpixel_fb(struct machine *m, int i, int x, int y, int color)
252 {
253 struct fb_window *fbwin;
254 if (i < 0 || i >= m->x11_md.n_fb_windows)
255 return;
256
257 fbwin = m->x11_md.fb_windows[i];
258
259 if (fbwin->x11_fb_winxsize <= 0)
260 return;
261
262 if (color)
263 XSetForeground(fbwin->x11_display,
264 fbwin->x11_fb_gc, fbwin->fg_color);
265 else
266 XSetForeground(fbwin->x11_display,
267 fbwin->x11_fb_gc, fbwin->bg_color);
268
269 XDrawPoint(fbwin->x11_display,
270 fbwin->x11_fb_window, fbwin->x11_fb_gc, x, y);
271
272 XFlush(fbwin->x11_display);
273 }
274
275
276 /*
277 * x11_putimage_fb():
278 *
279 * Output an entire XImage to a framebuffer window. i is the
280 * framebuffer number.
281 */
282 void x11_putimage_fb(struct machine *m, int i)
283 {
284 struct fb_window *fbwin;
285 if (i < 0 || i >= m->x11_md.n_fb_windows)
286 return;
287
288 fbwin = m->x11_md.fb_windows[i];
289
290 if (fbwin->x11_fb_winxsize <= 0)
291 return;
292
293 XPutImage(fbwin->x11_display,
294 fbwin->x11_fb_window,
295 fbwin->x11_fb_gc, fbwin->fb_ximage, 0,0, 0,0,
296 fbwin->x11_fb_winxsize,
297 fbwin->x11_fb_winysize);
298 XFlush(fbwin->x11_display);
299 }
300
301
302 /*
303 * x11_init():
304 *
305 * Initialize X11 stuff (but doesn't create any windows).
306 *
307 * It is then up to individual drivers, for example framebuffer devices,
308 * to initialize their own windows.
309 */
310 void x11_init(struct machine *m)
311 {
312 m->x11_md.n_fb_windows = 0;
313
314 if (m->x11_md.n_display_names > 0) {
315 int i;
316 for (i=0; i<m->x11_md.n_display_names; i++)
317 fatal("Using X11 display: %s\n",
318 m->x11_md.display_names[i]);
319 }
320
321 m->x11_md.current_display_name_nr = 0;
322 }
323
324
325 /*
326 * x11_fb_resize():
327 *
328 * Set a new size for an X11 framebuffer window. (NOTE: I didn't think of
329 * this kind of functionality during the initial design, so it is probably
330 * buggy. It also needs some refactoring.)
331 */
332 void x11_fb_resize(struct fb_window *win, int new_xsize, int new_ysize)
333 {
334 int alloc_depth;
335
336 if (win == NULL) {
337 fatal("x11_fb_resize(): win == NULL\n");
338 return;
339 }
340
341 win->x11_fb_winxsize = new_xsize;
342 win->x11_fb_winysize = new_ysize;
343
344 alloc_depth = win->x11_screen_depth;
345 if (alloc_depth == 24)
346 alloc_depth = 32;
347 if (alloc_depth == 15)
348 alloc_depth = 16;
349
350 /* Note: ximage_data seems to be freed by XDestroyImage below. */
351 /* if (win->ximage_data != NULL)
352 free(win->ximage_data); */
353 CHECK_ALLOCATION(win->ximage_data = malloc(
354 new_xsize * new_ysize * alloc_depth / 8));
355
356 /* TODO: clear for non-truecolor modes */
357 memset(win->ximage_data, 0, new_xsize * new_ysize * alloc_depth / 8);
358
359 if (win->fb_ximage != NULL)
360 XDestroyImage(win->fb_ximage);
361 win->fb_ximage = XCreateImage(win->x11_display, CopyFromParent,
362 win->x11_screen_depth, ZPixmap, 0, (char *)win->ximage_data,
363 new_xsize, new_ysize, 8, new_xsize * alloc_depth / 8);
364 CHECK_ALLOCATION(win->fb_ximage);
365
366 XResizeWindow(win->x11_display, win->x11_fb_window,
367 new_xsize, new_ysize);
368 }
369
370
371 /*
372 * x11_set_standard_properties():
373 *
374 * Right now, this only sets the title of a window.
375 */
376 void x11_set_standard_properties(struct fb_window *fb_window, char *name)
377 {
378 XSetStandardProperties(fb_window->x11_display,
379 fb_window->x11_fb_window, name,
380 #ifdef VERSION
381 "GXemul-" VERSION,
382 #else
383 "GXemul",
384 #endif
385 None, NULL, 0, NULL);
386 }
387
388
389 /*
390 * x11_fb_init():
391 *
392 * Initialize a framebuffer window.
393 */
394 struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
395 int scaledown, struct machine *m)
396 {
397 Display *x11_display;
398 int x, y, fb_number = 0;
399 size_t alloclen, alloc_depth;
400 XColor tmpcolor;
401 struct fb_window *fbwin;
402 int i;
403 char fg[80], bg[80];
404 char *display_name;
405
406 fb_number = m->x11_md.n_fb_windows;
407
408 CHECK_ALLOCATION(m->x11_md.fb_windows = realloc(m->x11_md.fb_windows,
409 sizeof(struct fb_window *) * (m->x11_md.n_fb_windows + 1)));
410 CHECK_ALLOCATION(fbwin = m->x11_md.fb_windows[fb_number] =
411 malloc(sizeof(struct fb_window)));
412
413 m->x11_md.n_fb_windows ++;
414
415 memset(fbwin, 0, sizeof(struct fb_window));
416
417 fbwin->x11_fb_winxsize = xsize;
418 fbwin->x11_fb_winysize = ysize;
419
420 /* Which display name? */
421 display_name = NULL;
422 if (m->x11_md.n_display_names > 0) {
423 display_name = m->x11_md.display_names[
424 m->x11_md.current_display_name_nr];
425 m->x11_md.current_display_name_nr ++;
426 m->x11_md.current_display_name_nr %= m->x11_md.n_display_names;
427 }
428
429 if (display_name != NULL)
430 debug("[ x11_fb_init(): framebuffer window %i, %ix%i, DISPLAY"
431 "=%s ]\n", fb_number, xsize, ysize, display_name);
432
433 x11_display = XOpenDisplay(display_name);
434
435 if (x11_display == NULL) {
436 fatal("x11_fb_init(\"%s\"): couldn't open display\n", name);
437 if (display_name != NULL)
438 fatal("display_name = '%s'\n", display_name);
439 exit(1);
440 }
441
442 fbwin->x11_screen =
443 DefaultScreen(x11_display);
444 fbwin->x11_screen_depth =
445 DefaultDepth(x11_display,
446 fbwin->x11_screen);
447
448 if (fbwin->x11_screen_depth != 8 &&
449 fbwin->x11_screen_depth != 15 &&
450 fbwin->x11_screen_depth != 16 &&
451 fbwin->x11_screen_depth != 24) {
452 fatal("\n***\n*** WARNING! Your X server is running %i-bit "
453 "color mode. This is not really\n",
454 fbwin->x11_screen_depth);
455 fatal("*** supported yet. 8, 15, 16, and 24 bits should "
456 "work.\n*** 24-bit server gives color. Any other bit "
457 "depth gives undefined result!\n***\n\n");
458 }
459
460 if (fbwin->x11_screen_depth <= 8)
461 debug("WARNING! X11 screen depth is not enough for color; "
462 "using only 16 grayscales instead\n");
463
464 strlcpy(bg, "Black", sizeof(bg));
465 strlcpy(fg, "White", sizeof(fg));
466
467 XParseColor(x11_display, DefaultColormap(x11_display,
468 fbwin->x11_screen), fg, &tmpcolor);
469 XAllocColor(x11_display, DefaultColormap(x11_display,
470 fbwin->x11_screen), &tmpcolor);
471 fbwin->fg_color = tmpcolor.pixel;
472 XParseColor(x11_display, DefaultColormap(x11_display,
473 fbwin->x11_screen), bg, &tmpcolor);
474 XAllocColor(x11_display, DefaultColormap(x11_display,
475 fbwin->x11_screen), &tmpcolor);
476 fbwin->bg_color = tmpcolor.pixel;
477
478 for (i=0; i<N_GRAYCOLORS; i++) {
479 char cname[8];
480 cname[0] = '#';
481 cname[1] = cname[2] = cname[3] =
482 cname[4] = cname[5] = cname[6] =
483 "0123456789ABCDEF"[i];
484 cname[7] = '\0';
485 XParseColor(x11_display, DefaultColormap(x11_display,
486 fbwin->x11_screen), cname,
487 &fbwin->x11_graycolor[i]);
488 XAllocColor(x11_display, DefaultColormap(x11_display,
489 fbwin->x11_screen),
490 &fbwin->x11_graycolor[i]);
491 }
492
493 XFlush(x11_display);
494
495 alloc_depth = fbwin->x11_screen_depth;
496
497 if (alloc_depth == 24)
498 alloc_depth = 32;
499 if (alloc_depth == 15)
500 alloc_depth = 16;
501
502 fbwin->x11_fb_window = XCreateWindow(
503 x11_display, DefaultRootWindow(x11_display),
504 0, 0, fbwin->x11_fb_winxsize,
505 fbwin->x11_fb_winysize,
506 0, CopyFromParent, InputOutput, CopyFromParent, 0,0);
507
508 fbwin->x11_display = x11_display;
509
510 x11_set_standard_properties(fbwin, name);
511
512 XSelectInput(x11_display,
513 fbwin->x11_fb_window,
514 StructureNotifyMask | ExposureMask | ButtonPressMask |
515 ButtonReleaseMask | PointerMotionMask | KeyPressMask);
516 fbwin->x11_fb_gc = XCreateGC(x11_display,
517 fbwin->x11_fb_window, 0,0);
518
519 /* Make sure the window is mapped: */
520 XMapRaised(x11_display, fbwin->x11_fb_window);
521
522 XSetBackground(x11_display, fbwin->x11_fb_gc, fbwin->bg_color);
523 XSetForeground(x11_display, fbwin->x11_fb_gc, fbwin->bg_color);
524 XFillRectangle(x11_display, fbwin->x11_fb_window, fbwin->x11_fb_gc, 0,0,
525 fbwin->x11_fb_winxsize, fbwin->x11_fb_winysize);
526
527 fbwin->scaledown = scaledown;
528
529 fbwin->fb_number = fb_number;
530
531 alloclen = xsize * ysize * alloc_depth / 8;
532 CHECK_ALLOCATION(fbwin->ximage_data = malloc(alloclen));
533
534 fbwin->fb_ximage = XCreateImage(fbwin->x11_display, CopyFromParent,
535 fbwin->x11_screen_depth, ZPixmap, 0, (char *)fbwin->ximage_data,
536 xsize, ysize, 8, xsize * alloc_depth / 8);
537 CHECK_ALLOCATION(fbwin->fb_ximage);
538
539 /* Fill the ximage with black pixels: */
540 if (fbwin->x11_screen_depth > 8)
541 memset(fbwin->ximage_data, 0, alloclen);
542 else {
543 debug("x11_fb_init(): clearing the XImage\n");
544 for (y=0; y<ysize; y++)
545 for (x=0; x<xsize; x++)
546 XPutPixel(fbwin->fb_ximage, x, y,
547 fbwin->x11_graycolor[0].pixel);
548 }
549
550 x11_putimage_fb(m, fb_number);
551
552 /* Fill the 64x64 "hardware" cursor with white pixels: */
553 xsize = ysize = 64;
554
555 /* Fill the cursor ximage with white pixels: */
556 for (y=0; y<ysize; y++)
557 for (x=0; x<xsize; x++)
558 fbwin->cursor_pixels[y][x] = N_GRAYCOLORS-1;
559
560 return fbwin;
561 }
562
563
564 /*
565 * x11_check_events_machine():
566 *
567 * Check for X11 events on a specific machine.
568 *
569 * TODO: Yuck! This has to be rewritten. Each display should be checked,
570 * and _then_ only those windows that are actually exposed should
571 * be redrawn!
572 */
573 static void x11_check_events_machine(struct emul **emuls, int n_emuls,
574 struct machine *m)
575 {
576 int fb_nr;
577
578 for (fb_nr = 0; fb_nr < m->x11_md.n_fb_windows; fb_nr ++) {
579 struct fb_window *fbwin = m->x11_md.fb_windows[fb_nr];
580 XEvent event;
581 int need_redraw = 0, found, i, j, k;
582
583 while (XPending(fbwin->x11_display)) {
584 XNextEvent(fbwin->x11_display, &event);
585
586 if (event.type==ConfigureNotify) {
587 need_redraw = 1;
588 }
589
590 if (event.type==Expose && event.xexpose.count==0) {
591 /*
592 * TODO: the xexpose struct has x,y,width,
593 * height. Those could be used to only redraw
594 * the part of the framebuffer that was
595 * exposed. Note that the (mouse) cursor must
596 * be redrawn too.
597 */
598 /* x11_winxsize = event.xexpose.width;
599 x11_winysize = event.xexpose.height; */
600 need_redraw = 1;
601 }
602
603 if (event.type == MotionNotify) {
604 /* debug("[ X11 MotionNotify: %i,%i ]\n",
605 event.xmotion.x, event.xmotion.y); */
606
607 /* Which window in which machine in
608 which emulation? */
609 found = -1;
610 for (k=0; k<n_emuls; k++)
611 for (j=0; j<emuls[k]->n_machines; j++) {
612 struct machine *m2 = emuls[k]->
613 machines[j];
614 for (i=0; i<m2->x11_md.
615 n_fb_windows; i++)
616 if (m->x11_md.
617 fb_windows[fb_nr]->
618 x11_display == m2->
619 x11_md.
620 fb_windows[i]->
621 x11_display &&
622 event.xmotion.
623 window == m2->
624 x11_md.
625 fb_windows[i]->
626 x11_fb_window)
627 found = i;
628 }
629 if (found < 0) {
630 printf("Internal error in x11.c.\n");
631 exit(1);
632 }
633 console_mouse_coordinates(event.xmotion.x *
634 m->x11_md.fb_windows[found]->scaledown,
635 event.xmotion.y * m->x11_md.fb_windows[
636 found]->scaledown, found);
637 }
638
639 if (event.type == ButtonPress) {
640 debug("[ X11 ButtonPress: %i ]\n",
641 event.xbutton.button);
642 /* button = 1,2,3 = left,middle,right */
643
644 console_mouse_button(event.xbutton.button, 1);
645 }
646
647 if (event.type == ButtonRelease) {
648 debug("[ X11 ButtonRelease: %i ]\n",
649 event.xbutton.button);
650 /* button = 1,2,3 = left,middle,right */
651
652 console_mouse_button(event.xbutton.button, 0);
653 }
654
655 if (event.type==KeyPress) {
656 char text[15];
657 KeySym key;
658 XKeyPressedEvent *ke = &event.xkey;
659
660 memset(text, 0, sizeof(text));
661
662 if (XLookupString(&event.xkey, text,
663 sizeof(text), &key, 0) == 1) {
664 console_makeavail(
665 m->main_console_handle, text[0]);
666 } else {
667 int x = ke->keycode;
668 /*
669 * Special key codes:
670 *
671 * NOTE/TODO: I'm hardcoding these to
672 * work with my key map. Maybe they
673 * should be read from some file...
674 *
675 * Important TODO 2: It would be MUCH
676 * better if these were converted into
677 * 'native scancodes', for example for
678 * the DECstation's keyboard or the
679 * PC-style 8042 controller.
680 */
681 switch (x) {
682 case 9: /* Escape */
683 console_makeavail(m->
684 main_console_handle, 27);
685 break;
686 #if 0
687 /* TODO */
688
689 /* The numeric keypad: */
690 90=Ins('0') 91=Del(',')
691
692 /* Above the cursor keys: */
693 106=Ins 107=Del
694 #endif
695 /* F1..F4: */
696 case 67: /* F1 */
697 case 68: /* F2 */
698 case 69: /* F3 */
699 case 70: /* F4 */
700 console_makeavail(m->
701 main_console_handle, 27);
702 console_makeavail(m->
703 main_console_handle, '[');
704 console_makeavail(m->
705 main_console_handle, 'O');
706 console_makeavail(m->
707 main_console_handle, 'P' +
708 x - 67);
709 break;
710 case 71: /* F5 */
711 console_makeavail(m->
712 main_console_handle, 27);
713 console_makeavail(m->
714 main_console_handle, '[');
715 console_makeavail(m->
716 main_console_handle, '1');
717 console_makeavail(m->
718 main_console_handle, '5');
719 break;
720 case 72: /* F6 */
721 case 73: /* F7 */
722 case 74: /* F8 */
723 console_makeavail(m->
724 main_console_handle, 27);
725 console_makeavail(m->
726 main_console_handle, '[');
727 console_makeavail(m->
728 main_console_handle, '1');
729 console_makeavail(m->
730 main_console_handle, '7' +
731 x - 72);
732 break;
733 case 75: /* F9 */
734 case 76: /* F10 */
735 console_makeavail(m->
736 main_console_handle, 27);
737 console_makeavail(m->
738 main_console_handle, '[');
739 console_makeavail(m->
740 main_console_handle, '2');
741 console_makeavail(m->
742 main_console_handle, '1' +
743 x - 68);
744 break;
745 case 95: /* F11 */
746 case 96: /* F12 */
747 console_makeavail(m->
748 main_console_handle, 27);
749 console_makeavail(m->
750 main_console_handle, '[');
751 console_makeavail(m->
752 main_console_handle, '2');
753 console_makeavail(m->
754 main_console_handle, '3' +
755 x - 95);
756 break;
757 /* Cursor keys: */
758 case 98: /* Up */
759 case 104: /* Down */
760 case 100: /* Left */
761 case 102: /* Right */
762 console_makeavail(m->
763 main_console_handle, 27);
764 console_makeavail(m->
765 main_console_handle, '[');
766 console_makeavail(m->
767 main_console_handle,
768 x == 98? 'A' : (
769 x == 104? 'B' : (
770 x == 102? 'C' : (
771 'D'))));
772 break;
773 /* Numeric keys: */
774 case 80: /* Up */
775 case 88: /* Down */
776 case 83: /* Left */
777 case 85: /* Right */
778 console_makeavail(m->
779 main_console_handle, 27);
780 console_makeavail(m->
781 main_console_handle, '[');
782 console_makeavail(m->
783 main_console_handle,
784 x == 80? 'A' : (
785 x == 88? 'B' : (
786 x == 85? 'C' : (
787 'D'))));
788 break;
789 case 97: /* Cursor Home */
790 case 79: /* Numeric Home */
791 console_makeavail(m->
792 main_console_handle, 27);
793 console_makeavail(m->
794 main_console_handle, '[');
795 console_makeavail(m->
796 main_console_handle, 'H');
797 break;
798 case 103: /* Cursor End */
799 case 87: /* Numeric End */
800 console_makeavail(m->
801 main_console_handle, 27);
802 console_makeavail(m->
803 main_console_handle, '[');
804 console_makeavail(m->
805 main_console_handle, 'F');
806 break;
807 case 99: /* Cursor PgUp */
808 case 81: /* Numeric PgUp */
809 console_makeavail(m->
810 main_console_handle, 27);
811 console_makeavail(m->
812 main_console_handle, '[');
813 console_makeavail(m->
814 main_console_handle, '5');
815 console_makeavail(m->
816 main_console_handle, '~');
817 break;
818 case 105: /* Cursor PgUp */
819 case 89: /* Numeric PgDn */
820 console_makeavail(m->
821 main_console_handle, 27);
822 console_makeavail(m->
823 main_console_handle, '[');
824 console_makeavail(m->
825 main_console_handle, '6');
826 console_makeavail(m->
827 main_console_handle, '~');
828 break;
829 default:
830 debug("[ unimplemented X11 "
831 "keycode %i ]\n", x);
832 }
833 }
834 }
835 }
836
837 if (need_redraw)
838 x11_redraw(m, fb_nr);
839 }
840 }
841
842
843 /*
844 * x11_check_event():
845 *
846 * Check for X11 events.
847 */
848 void x11_check_event(struct emul **emuls, int n_emuls)
849 {
850 int i, j;
851
852 for (i=0; i<n_emuls; i++)
853 for (j=0; j<emuls[i]->n_machines; j++)
854 x11_check_events_machine(emuls, n_emuls,
855 emuls[i]->machines[j]);
856 }
857
858 #endif /* WITH_X11 */

  ViewVC Help
Powered by ViewVC 1.1.26