/[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 6 - (hide annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 25589 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


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 6 * $Id: x11.c,v 1.58 2005/05/20 22:35:59 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     strcpy(bg, "Black");
460     strcpy(fg, "White");
461    
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