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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 7 months ago) by dpavlin
Original Path: trunk/src/x11.c
File MIME type: text/plain
File size: 25781 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 dpavlin 2 /*
2 dpavlin 34 * Copyright (C) 2003-2007 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 34 * $Id: x11.c,v 1.63 2006/12/30 13:30:53 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