/[gxemul]/trunk/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

Annotation of /trunk/src/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25615 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26