/[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

Annotation of /trunk/src/console/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 8 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 dpavlin 44 /*
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