/[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 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25781 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26