/[gxemul]/trunk/src/console/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 /trunk/src/console/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 23021 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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.3 2007/06/28 14:58: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 *emul) { }
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, "GXemul "VERSION,
380 None, NULL, 0, NULL);
381 }
382
383
384 /*
385 * x11_fb_init():
386 *
387 * Initialize a framebuffer window.
388 */
389 struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
390 int scaledown, struct machine *m)
391 {
392 Display *x11_display;
393 int x, y, fb_number = 0;
394 size_t alloclen, alloc_depth;
395 XColor tmpcolor;
396 struct fb_window *fbwin;
397 int i;
398 char fg[80], bg[80];
399 char *display_name;
400
401 fb_number = m->x11_md.n_fb_windows;
402
403 CHECK_ALLOCATION(m->x11_md.fb_windows = realloc(m->x11_md.fb_windows,
404 sizeof(struct fb_window *) * (m->x11_md.n_fb_windows + 1)));
405 CHECK_ALLOCATION(fbwin = m->x11_md.fb_windows[fb_number] =
406 malloc(sizeof(struct fb_window)));
407
408 m->x11_md.n_fb_windows ++;
409
410 memset(fbwin, 0, sizeof(struct fb_window));
411
412 fbwin->x11_fb_winxsize = xsize;
413 fbwin->x11_fb_winysize = ysize;
414
415 /* Which display name? */
416 display_name = NULL;
417 if (m->x11_md.n_display_names > 0) {
418 display_name = m->x11_md.display_names[
419 m->x11_md.current_display_name_nr];
420 m->x11_md.current_display_name_nr ++;
421 m->x11_md.current_display_name_nr %= m->x11_md.n_display_names;
422 }
423
424 if (display_name != NULL)
425 debug("[ x11_fb_init(): framebuffer window %i, %ix%i, DISPLAY"
426 "=%s ]\n", fb_number, xsize, ysize, display_name);
427
428 x11_display = XOpenDisplay(display_name);
429
430 if (x11_display == NULL) {
431 fatal("x11_fb_init(\"%s\"): couldn't open display\n", name);
432 if (display_name != NULL)
433 fatal("display_name = '%s'\n", display_name);
434 exit(1);
435 }
436
437 fbwin->x11_screen =
438 DefaultScreen(x11_display);
439 fbwin->x11_screen_depth =
440 DefaultDepth(x11_display,
441 fbwin->x11_screen);
442
443 if (fbwin->x11_screen_depth != 8 &&
444 fbwin->x11_screen_depth != 15 &&
445 fbwin->x11_screen_depth != 16 &&
446 fbwin->x11_screen_depth != 24) {
447 fatal("\n***\n*** WARNING! Your X server is running %i-bit "
448 "color mode. This is not really\n",
449 fbwin->x11_screen_depth);
450 fatal("*** supported yet. 8, 15, 16, and 24 bits should "
451 "work.\n*** 24-bit server gives color. Any other bit "
452 "depth gives undefined result!\n***\n\n");
453 }
454
455 if (fbwin->x11_screen_depth <= 8)
456 debug("WARNING! X11 screen depth is not enough for color; "
457 "using only 16 grayscales instead\n");
458
459 strlcpy(bg, "Black", sizeof(bg));
460 strlcpy(fg, "White", sizeof(fg));
461
462 XParseColor(x11_display, DefaultColormap(x11_display,
463 fbwin->x11_screen), fg, &tmpcolor);
464 XAllocColor(x11_display, DefaultColormap(x11_display,
465 fbwin->x11_screen), &tmpcolor);
466 fbwin->fg_color = tmpcolor.pixel;
467 XParseColor(x11_display, DefaultColormap(x11_display,
468 fbwin->x11_screen), bg, &tmpcolor);
469 XAllocColor(x11_display, DefaultColormap(x11_display,
470 fbwin->x11_screen), &tmpcolor);
471 fbwin->bg_color = tmpcolor.pixel;
472
473 for (i=0; i<N_GRAYCOLORS; i++) {
474 char cname[8];
475 cname[0] = '#';
476 cname[1] = cname[2] = cname[3] =
477 cname[4] = cname[5] = cname[6] =
478 "0123456789ABCDEF"[i];
479 cname[7] = '\0';
480 XParseColor(x11_display, DefaultColormap(x11_display,
481 fbwin->x11_screen), cname,
482 &fbwin->x11_graycolor[i]);
483 XAllocColor(x11_display, DefaultColormap(x11_display,
484 fbwin->x11_screen),
485 &fbwin->x11_graycolor[i]);
486 }
487
488 XFlush(x11_display);
489
490 alloc_depth = fbwin->x11_screen_depth;
491
492 if (alloc_depth == 24)
493 alloc_depth = 32;
494 if (alloc_depth == 15)
495 alloc_depth = 16;
496
497 fbwin->x11_fb_window = XCreateWindow(
498 x11_display, DefaultRootWindow(x11_display),
499 0, 0, fbwin->x11_fb_winxsize,
500 fbwin->x11_fb_winysize,
501 0, CopyFromParent, InputOutput, CopyFromParent, 0,0);
502
503 fbwin->x11_display = x11_display;
504
505 x11_set_standard_properties(fbwin, name);
506
507 XSelectInput(x11_display,
508 fbwin->x11_fb_window,
509 StructureNotifyMask | ExposureMask | ButtonPressMask |
510 ButtonReleaseMask | PointerMotionMask | KeyPressMask);
511 fbwin->x11_fb_gc = XCreateGC(x11_display,
512 fbwin->x11_fb_window, 0,0);
513
514 /* Make sure the window is mapped: */
515 XMapRaised(x11_display, fbwin->x11_fb_window);
516
517 XSetBackground(x11_display, fbwin->x11_fb_gc, fbwin->bg_color);
518 XSetForeground(x11_display, fbwin->x11_fb_gc, fbwin->bg_color);
519 XFillRectangle(x11_display, fbwin->x11_fb_window, fbwin->x11_fb_gc, 0,0,
520 fbwin->x11_fb_winxsize, fbwin->x11_fb_winysize);
521
522 fbwin->scaledown = scaledown;
523
524 fbwin->fb_number = fb_number;
525
526 alloclen = xsize * ysize * alloc_depth / 8;
527 CHECK_ALLOCATION(fbwin->ximage_data = malloc(alloclen));
528
529 fbwin->fb_ximage = XCreateImage(fbwin->x11_display, CopyFromParent,
530 fbwin->x11_screen_depth, ZPixmap, 0, (char *)fbwin->ximage_data,
531 xsize, ysize, 8, xsize * alloc_depth / 8);
532 CHECK_ALLOCATION(fbwin->fb_ximage);
533
534 /* Fill the ximage with black pixels: */
535 if (fbwin->x11_screen_depth > 8)
536 memset(fbwin->ximage_data, 0, alloclen);
537 else {
538 debug("x11_fb_init(): clearing the XImage\n");
539 for (y=0; y<ysize; y++)
540 for (x=0; x<xsize; x++)
541 XPutPixel(fbwin->fb_ximage, x, y,
542 fbwin->x11_graycolor[0].pixel);
543 }
544
545 x11_putimage_fb(m, fb_number);
546
547 /* Fill the 64x64 "hardware" cursor with white pixels: */
548 xsize = ysize = 64;
549
550 /* Fill the cursor ximage with white pixels: */
551 for (y=0; y<ysize; y++)
552 for (x=0; x<xsize; x++)
553 fbwin->cursor_pixels[y][x] = N_GRAYCOLORS-1;
554
555 return fbwin;
556 }
557
558
559 /*
560 * x11_check_events_machine():
561 *
562 * Check for X11 events on a specific machine.
563 *
564 * TODO: Yuck! This has to be rewritten. Each display should be checked,
565 * and _then_ only those windows that are actually exposed should
566 * be redrawn!
567 */
568 static void x11_check_events_machine(struct emul *emul, struct machine *m)
569 {
570 int fb_nr;
571
572 for (fb_nr = 0; fb_nr < m->x11_md.n_fb_windows; fb_nr ++) {
573 struct fb_window *fbwin = m->x11_md.fb_windows[fb_nr];
574 XEvent event;
575 int need_redraw = 0, found, i, j;
576
577 while (XPending(fbwin->x11_display)) {
578 XNextEvent(fbwin->x11_display, &event);
579
580 if (event.type==ConfigureNotify) {
581 need_redraw = 1;
582 }
583
584 if (event.type==Expose && event.xexpose.count==0) {
585 /*
586 * TODO: the xexpose struct has x,y,width,
587 * height. Those could be used to only redraw
588 * the part of the framebuffer that was
589 * exposed. Note that the (mouse) cursor must
590 * be redrawn too.
591 */
592 /* x11_winxsize = event.xexpose.width;
593 x11_winysize = event.xexpose.height; */
594 need_redraw = 1;
595 }
596
597 if (event.type == MotionNotify) {
598 /* debug("[ X11 MotionNotify: %i,%i ]\n",
599 event.xmotion.x, event.xmotion.y); */
600
601 /* Which window in which machine in
602 which emulation? */
603 found = -1;
604 for (j=0; j<emul->n_machines; j++) {
605 struct machine *m2 = emul->machines[j];
606 for (i=0; i<m2->x11_md.
607 n_fb_windows; i++)
608 if (m->x11_md.
609 fb_windows[fb_nr]->
610 x11_display == m2->
611 x11_md.
612 fb_windows[i]->
613 x11_display &&
614 event.xmotion.
615 window == m2->
616 x11_md.
617 fb_windows[i]->
618 x11_fb_window)
619 found = i;
620 }
621 if (found < 0) {
622 printf("Internal error in x11.c.\n");
623 exit(1);
624 }
625 console_mouse_coordinates(event.xmotion.x *
626 m->x11_md.fb_windows[found]->scaledown,
627 event.xmotion.y * m->x11_md.fb_windows[
628 found]->scaledown, found);
629 }
630
631 if (event.type == ButtonPress) {
632 debug("[ X11 ButtonPress: %i ]\n",
633 event.xbutton.button);
634 /* button = 1,2,3 = left,middle,right */
635
636 console_mouse_button(event.xbutton.button, 1);
637 }
638
639 if (event.type == ButtonRelease) {
640 debug("[ X11 ButtonRelease: %i ]\n",
641 event.xbutton.button);
642 /* button = 1,2,3 = left,middle,right */
643
644 console_mouse_button(event.xbutton.button, 0);
645 }
646
647 if (event.type==KeyPress) {
648 char text[15];
649 KeySym key;
650 XKeyPressedEvent *ke = &event.xkey;
651
652 memset(text, 0, sizeof(text));
653
654 if (XLookupString(&event.xkey, text,
655 sizeof(text), &key, 0) == 1) {
656 console_makeavail(
657 m->main_console_handle, text[0]);
658 } else {
659 int x = ke->keycode;
660 /*
661 * Special key codes:
662 *
663 * NOTE/TODO: I'm hardcoding these to
664 * work with my key map. Maybe they
665 * should be read from some file...
666 *
667 * Important TODO 2: It would be MUCH
668 * better if these were converted into
669 * 'native scancodes', for example for
670 * the DECstation's keyboard or the
671 * PC-style 8042 controller.
672 */
673 switch (x) {
674 case 9: /* Escape */
675 console_makeavail(m->
676 main_console_handle, 27);
677 break;
678 #if 0
679 /* TODO */
680
681 /* The numeric keypad: */
682 90=Ins('0') 91=Del(',')
683
684 /* Above the cursor keys: */
685 106=Ins 107=Del
686 #endif
687 /* F1..F4: */
688 case 67: /* F1 */
689 case 68: /* F2 */
690 case 69: /* F3 */
691 case 70: /* F4 */
692 console_makeavail(m->
693 main_console_handle, 27);
694 console_makeavail(m->
695 main_console_handle, '[');
696 console_makeavail(m->
697 main_console_handle, 'O');
698 console_makeavail(m->
699 main_console_handle, 'P' +
700 x - 67);
701 break;
702 case 71: /* F5 */
703 console_makeavail(m->
704 main_console_handle, 27);
705 console_makeavail(m->
706 main_console_handle, '[');
707 console_makeavail(m->
708 main_console_handle, '1');
709 console_makeavail(m->
710 main_console_handle, '5');
711 break;
712 case 72: /* F6 */
713 case 73: /* F7 */
714 case 74: /* F8 */
715 console_makeavail(m->
716 main_console_handle, 27);
717 console_makeavail(m->
718 main_console_handle, '[');
719 console_makeavail(m->
720 main_console_handle, '1');
721 console_makeavail(m->
722 main_console_handle, '7' +
723 x - 72);
724 break;
725 case 75: /* F9 */
726 case 76: /* F10 */
727 console_makeavail(m->
728 main_console_handle, 27);
729 console_makeavail(m->
730 main_console_handle, '[');
731 console_makeavail(m->
732 main_console_handle, '2');
733 console_makeavail(m->
734 main_console_handle, '1' +
735 x - 68);
736 break;
737 case 95: /* F11 */
738 case 96: /* F12 */
739 console_makeavail(m->
740 main_console_handle, 27);
741 console_makeavail(m->
742 main_console_handle, '[');
743 console_makeavail(m->
744 main_console_handle, '2');
745 console_makeavail(m->
746 main_console_handle, '3' +
747 x - 95);
748 break;
749 /* Cursor keys: */
750 case 98: /* Up */
751 case 104: /* Down */
752 case 100: /* Left */
753 case 102: /* Right */
754 console_makeavail(m->
755 main_console_handle, 27);
756 console_makeavail(m->
757 main_console_handle, '[');
758 console_makeavail(m->
759 main_console_handle,
760 x == 98? 'A' : (
761 x == 104? 'B' : (
762 x == 102? 'C' : (
763 'D'))));
764 break;
765 /* Numeric keys: */
766 case 80: /* Up */
767 case 88: /* Down */
768 case 83: /* Left */
769 case 85: /* Right */
770 console_makeavail(m->
771 main_console_handle, 27);
772 console_makeavail(m->
773 main_console_handle, '[');
774 console_makeavail(m->
775 main_console_handle,
776 x == 80? 'A' : (
777 x == 88? 'B' : (
778 x == 85? 'C' : (
779 'D'))));
780 break;
781 case 97: /* Cursor Home */
782 case 79: /* Numeric Home */
783 console_makeavail(m->
784 main_console_handle, 27);
785 console_makeavail(m->
786 main_console_handle, '[');
787 console_makeavail(m->
788 main_console_handle, 'H');
789 break;
790 case 103: /* Cursor End */
791 case 87: /* Numeric End */
792 console_makeavail(m->
793 main_console_handle, 27);
794 console_makeavail(m->
795 main_console_handle, '[');
796 console_makeavail(m->
797 main_console_handle, 'F');
798 break;
799 case 99: /* Cursor PgUp */
800 case 81: /* Numeric PgUp */
801 console_makeavail(m->
802 main_console_handle, 27);
803 console_makeavail(m->
804 main_console_handle, '[');
805 console_makeavail(m->
806 main_console_handle, '5');
807 console_makeavail(m->
808 main_console_handle, '~');
809 break;
810 case 105: /* Cursor PgUp */
811 case 89: /* Numeric PgDn */
812 console_makeavail(m->
813 main_console_handle, 27);
814 console_makeavail(m->
815 main_console_handle, '[');
816 console_makeavail(m->
817 main_console_handle, '6');
818 console_makeavail(m->
819 main_console_handle, '~');
820 break;
821 default:
822 debug("[ unimplemented X11 "
823 "keycode %i ]\n", x);
824 }
825 }
826 }
827 }
828
829 if (need_redraw)
830 x11_redraw(m, fb_nr);
831 }
832 }
833
834
835 /*
836 * x11_check_event():
837 *
838 * Check for X11 events.
839 */
840 void x11_check_event(struct emul *emul)
841 {
842 int i;
843
844 for (i=0; i<emul->n_machines; i++)
845 x11_check_events_machine(emul, emul->machines[i]);
846 }
847
848 #endif /* WITH_X11 */

  ViewVC Help
Powered by ViewVC 1.1.26