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

Contents of /trunk/src/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25543 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


1 /*
2 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: x11.c,v 1.61 2006/01/14 12:51:59 debug Exp $
29 *
30 * X11-related functions.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "console.h"
38 #include "emul.h"
39 #include "machine.h"
40 #include "misc.h"
41 #include "x11.h"
42
43
44 #ifndef WITH_X11
45
46
47 /* Dummy functions: */
48 void x11_redraw_cursor(struct machine *m, int i) { }
49 void x11_redraw(struct machine *m, int x) { }
50 void x11_putpixel_fb(struct machine *m, int fb, int x, int y, int color) { }
51 void x11_init(struct machine *machine) { }
52 struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
53 int scaledown, struct machine *machine)
54 { return NULL; }
55 void x11_check_event(struct emul **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 * NOTE: It is up to the caller to call XFlush.
72 */
73 void x11_redraw_cursor(struct machine *m, int i)
74 {
75 int last_color_used = 0;
76 int n_colors_used = 0;
77
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 * 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 * x11_fb_init():
381 *
382 * Initialize a framebuffer window.
383 */
384 struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
385 int scaledown, struct machine *m)
386 {
387 Display *x11_display;
388 int x, y, fb_number = 0;
389 size_t alloclen, alloc_depth;
390 XColor tmpcolor;
391 int i;
392 char fg[80], bg[80];
393 char *display_name;
394
395 fb_number = m->n_fb_windows;
396
397 m->fb_windows = realloc(m->fb_windows,
398 sizeof(struct fb_window *) * (m->n_fb_windows + 1));
399 if (m->fb_windows == NULL) {
400 fprintf(stderr, "x11_fb_init(): out of memory\n");
401 exit(1);
402 }
403 m->fb_windows[fb_number] = malloc(sizeof(struct fb_window));
404 if (m->fb_windows[fb_number] == NULL) {
405 fprintf(stderr, "x11_fb_init(): out of memory\n");
406 exit(1);
407 }
408
409 m->n_fb_windows ++;
410
411 memset(m->fb_windows[fb_number], 0, sizeof(struct fb_window));
412
413 m->fb_windows[fb_number]->x11_fb_winxsize = xsize;
414 m->fb_windows[fb_number]->x11_fb_winysize = ysize;
415
416 /* Which display name? */
417 display_name = NULL;
418 if (m->x11_n_display_names > 0) {
419 display_name = m->x11_display_names[
420 m->x11_current_display_name_nr];
421 m->x11_current_display_name_nr ++;
422 m->x11_current_display_name_nr %= m->x11_n_display_names;
423 }
424
425 if (display_name != NULL)
426 debug("[ x11_fb_init(): framebuffer window %i, %ix%i, DISPLAY"
427 "=%s ]\n", fb_number, xsize, ysize, display_name);
428
429 x11_display = XOpenDisplay(display_name);
430
431 if (x11_display == NULL) {
432 fatal("x11_fb_init(\"%s\"): couldn't open display\n", name);
433 if (display_name != NULL)
434 fatal("display_name = '%s'\n", display_name);
435 exit(1);
436 }
437
438 m->fb_windows[fb_number]->x11_screen = DefaultScreen(x11_display);
439 m->fb_windows[fb_number]->x11_screen_depth = DefaultDepth(x11_display,
440 m->fb_windows[fb_number]->x11_screen);
441
442 if (m->fb_windows[fb_number]->x11_screen_depth != 8 &&
443 m->fb_windows[fb_number]->x11_screen_depth != 15 &&
444 m->fb_windows[fb_number]->x11_screen_depth != 16 &&
445 m->fb_windows[fb_number]->x11_screen_depth != 24) {
446 fatal("\n***\n*** WARNING! Your X server is running %i-bit "
447 "color mode. This is not really\n",
448 m->fb_windows[fb_number]->x11_screen_depth);
449 fatal("*** supported yet. 8, 15, 16, and 24 bits should "
450 "work.\n*** 24-bit server gives color. Any other bit "
451 "depth gives undefined result!\n***\n\n");
452 }
453
454 if (m->fb_windows[fb_number]->x11_screen_depth <= 8)
455 debug("WARNING! X11 screen depth is not enough for color; "
456 "using only 16 grayscales instead\n");
457
458 strlcpy(bg, "Black", sizeof(bg));
459 strlcpy(fg, "White", sizeof(fg));
460
461 XParseColor(x11_display, DefaultColormap(x11_display,
462 m->fb_windows[fb_number]->x11_screen), fg, &tmpcolor);
463 XAllocColor(x11_display, DefaultColormap(x11_display,
464 m->fb_windows[fb_number]->x11_screen), &tmpcolor);
465 m->fb_windows[fb_number]->fg_color = tmpcolor.pixel;
466 XParseColor(x11_display, DefaultColormap(x11_display,
467 m->fb_windows[fb_number]->x11_screen), bg, &tmpcolor);
468 XAllocColor(x11_display, DefaultColormap(x11_display,
469 m->fb_windows[fb_number]->x11_screen), &tmpcolor);
470 m->fb_windows[fb_number]->bg_color = tmpcolor.pixel;
471
472 for (i=0; i<N_GRAYCOLORS; i++) {
473 char cname[8];
474 cname[0] = '#';
475 cname[1] = cname[2] = cname[3] =
476 cname[4] = cname[5] = cname[6] =
477 "0123456789ABCDEF"[i];
478 cname[7] = '\0';
479 XParseColor(x11_display, DefaultColormap(x11_display,
480 m->fb_windows[fb_number]->x11_screen), cname,
481 &m->fb_windows[fb_number]->x11_graycolor[i]);
482 XAllocColor(x11_display, DefaultColormap(x11_display,
483 m->fb_windows[fb_number]->x11_screen),
484 &m->fb_windows[fb_number]->x11_graycolor[i]);
485 }
486
487 XFlush(x11_display);
488
489 alloc_depth = m->fb_windows[fb_number]->x11_screen_depth;
490
491 if (alloc_depth == 24)
492 alloc_depth = 32;
493 if (alloc_depth == 15)
494 alloc_depth = 16;
495
496 m->fb_windows[fb_number]->x11_fb_window = XCreateWindow(
497 x11_display, DefaultRootWindow(x11_display),
498 0, 0, m->fb_windows[fb_number]->x11_fb_winxsize,
499 m->fb_windows[fb_number]->x11_fb_winysize,
500 0, CopyFromParent, InputOutput, CopyFromParent, 0,0);
501
502 XSetStandardProperties(x11_display,
503 m->fb_windows[fb_number]->x11_fb_window, name,
504 #ifdef VERSION
505 "GXemul-" VERSION,
506 #else
507 "GXemul",
508 #endif
509 None, NULL, 0, NULL);
510 XSelectInput(x11_display, m->fb_windows[fb_number]->x11_fb_window,
511 StructureNotifyMask | ExposureMask | ButtonPressMask |
512 ButtonReleaseMask | PointerMotionMask | KeyPressMask);
513 m->fb_windows[fb_number]->x11_fb_gc = XCreateGC(x11_display,
514 m->fb_windows[fb_number]->x11_fb_window, 0,0);
515
516 /* Make sure the window is mapped: */
517 XMapRaised(x11_display, m->fb_windows[fb_number]->x11_fb_window);
518
519 XSetBackground(x11_display, m->fb_windows[fb_number]->x11_fb_gc,
520 m->fb_windows[fb_number]->bg_color);
521 XSetForeground(x11_display, m->fb_windows[fb_number]->x11_fb_gc,
522 m->fb_windows[fb_number]->bg_color);
523 XFillRectangle(x11_display, m->fb_windows[fb_number]->x11_fb_window,
524 m->fb_windows[fb_number]->x11_fb_gc, 0,0,
525 m->fb_windows[fb_number]->x11_fb_winxsize,
526 m->fb_windows[fb_number]->x11_fb_winysize);
527
528 m->fb_windows[fb_number]->x11_display = x11_display;
529 m->fb_windows[fb_number]->scaledown = scaledown;
530
531 m->fb_windows[fb_number]->fb_number = fb_number;
532
533 alloclen = xsize * ysize * alloc_depth / 8;
534 m->fb_windows[fb_number]->ximage_data = malloc(alloclen);
535 if (m->fb_windows[fb_number]->ximage_data == NULL) {
536 fprintf(stderr, "out of memory allocating ximage_data\n");
537 exit(1);
538 }
539
540 m->fb_windows[fb_number]->fb_ximage = XCreateImage(
541 m->fb_windows[fb_number]->x11_display, CopyFromParent,
542 m->fb_windows[fb_number]->x11_screen_depth, ZPixmap, 0,
543 (char *)m->fb_windows[fb_number]->ximage_data,
544 xsize, ysize, 8, xsize * alloc_depth / 8);
545 if (m->fb_windows[fb_number]->fb_ximage == NULL) {
546 fprintf(stderr, "out of memory allocating ximage\n");
547 exit(1);
548 }
549
550 /* Fill the ximage with black pixels: */
551 if (m->fb_windows[fb_number]->x11_screen_depth > 8)
552 memset(m->fb_windows[fb_number]->ximage_data, 0, alloclen);
553 else {
554 debug("x11_fb_init(): clearing the XImage\n");
555 for (y=0; y<ysize; y++)
556 for (x=0; x<xsize; x++)
557 XPutPixel(m->fb_windows[fb_number]->fb_ximage,
558 x, y, m->fb_windows[fb_number]->
559 x11_graycolor[0].pixel);
560 }
561
562 x11_putimage_fb(m, fb_number);
563
564 /* Fill the 64x64 "hardware" cursor with white pixels: */
565 xsize = ysize = 64;
566
567 /* Fill the cursor ximage with white pixels: */
568 for (y=0; y<ysize; y++)
569 for (x=0; x<xsize; x++)
570 m->fb_windows[fb_number]->cursor_pixels[y][x] =
571 N_GRAYCOLORS-1;
572
573 return m->fb_windows[fb_number];
574 }
575
576
577 /*
578 * x11_check_events_machine():
579 *
580 * Check for X11 events on a specific machine.
581 *
582 * TODO: Yuck! This has to be rewritten. Each display should be checked,
583 * and _then_ only those windows that are actually exposed should
584 * be redrawn!
585 */
586 static void x11_check_events_machine(struct emul **emuls, int n_emuls,
587 struct machine *m)
588 {
589 int fb_nr;
590
591 for (fb_nr=0; fb_nr<m->n_fb_windows; fb_nr++) {
592 XEvent event;
593 int need_redraw = 0, found, i, j, k;
594
595 while (XPending(m->fb_windows[fb_nr]->x11_display)) {
596 XNextEvent(m->fb_windows[fb_nr]->x11_display, &event);
597
598 if (event.type==ConfigureNotify) {
599 need_redraw = 1;
600 }
601
602 if (event.type==Expose && event.xexpose.count==0) {
603 /*
604 * TODO: the xexpose struct has x,y,width,
605 * height. Those could be used to only redraw
606 * the part of the framebuffer that was
607 * exposed. Note that the (mouse) cursor must
608 * be redrawn too.
609 */
610 /* x11_winxsize = event.xexpose.width;
611 x11_winysize = event.xexpose.height; */
612 need_redraw = 1;
613 }
614
615 if (event.type == MotionNotify) {
616 /* debug("[ X11 MotionNotify: %i,%i ]\n",
617 event.xmotion.x, event.xmotion.y); */
618
619 /* Which window in which machine in
620 which emulation? */
621 found = -1;
622 for (k=0; k<n_emuls; k++)
623 for (j=0; j<emuls[k]->n_machines; j++) {
624 struct machine *m2 = emuls[k]->
625 machines[j];
626 for (i=0; i<m2->n_fb_windows;
627 i++)
628 if (m->fb_windows[
629 fb_nr]->
630 x11_display == m2->
631 fb_windows[i]->
632 x11_display &&
633 event.xmotion.
634 window == m2->
635 fb_windows[i]->
636 x11_fb_window)
637 found = i;
638 }
639 if (found < 0) {
640 printf("Internal error in x11.c.\n");
641 exit(1);
642 }
643 console_mouse_coordinates(event.xmotion.x *
644 m->fb_windows[found]->scaledown,
645 event.xmotion.y * m->fb_windows[found]->
646 scaledown, found);
647 }
648
649 if (event.type == ButtonPress) {
650 debug("[ X11 ButtonPress: %i ]\n",
651 event.xbutton.button);
652 /* button = 1,2,3 = left,middle,right */
653
654 console_mouse_button(event.xbutton.button, 1);
655 }
656
657 if (event.type == ButtonRelease) {
658 debug("[ X11 ButtonRelease: %i ]\n",
659 event.xbutton.button);
660 /* button = 1,2,3 = left,middle,right */
661
662 console_mouse_button(event.xbutton.button, 0);
663 }
664
665 if (event.type==KeyPress) {
666 char text[15];
667 KeySym key;
668 XKeyPressedEvent *ke = &event.xkey;
669
670 memset(text, sizeof(text), 0);
671
672 if (XLookupString(&event.xkey, text,
673 sizeof(text), &key, 0) == 1) {
674 console_makeavail(
675 m->main_console_handle, text[0]);
676 } else {
677 int x = ke->keycode;
678 /*
679 * Special key codes:
680 *
681 * NOTE/TODO: I'm hardcoding these to
682 * work with my key map. Maybe they
683 * should be read from some file...
684 *
685 * Important TODO 2: It would be MUCH
686 * better if these were converted into
687 * 'native scancodes', for example for
688 * the DECstation's keyboard or the
689 * PC-style 8042 controller.
690 */
691 switch (x) {
692 case 9: /* Escape */
693 console_makeavail(m->
694 main_console_handle, 27);
695 break;
696 #if 0
697 /* TODO */
698
699 /* The numeric keypad: */
700 90=Ins('0') 91=Del(',')
701
702 /* Above the cursor keys: */
703 106=Ins 107=Del
704 #endif
705 /* F1..F4: */
706 case 67: /* F1 */
707 case 68: /* F2 */
708 case 69: /* F3 */
709 case 70: /* F4 */
710 console_makeavail(m->
711 main_console_handle, 27);
712 console_makeavail(m->
713 main_console_handle, '[');
714 console_makeavail(m->
715 main_console_handle, 'O');
716 console_makeavail(m->
717 main_console_handle, 'P' +
718 x - 67);
719 break;
720 case 71: /* F5 */
721 console_makeavail(m->
722 main_console_handle, 27);
723 console_makeavail(m->
724 main_console_handle, '[');
725 console_makeavail(m->
726 main_console_handle, '1');
727 console_makeavail(m->
728 main_console_handle, '5');
729 break;
730 case 72: /* F6 */
731 case 73: /* F7 */
732 case 74: /* F8 */
733 console_makeavail(m->
734 main_console_handle, 27);
735 console_makeavail(m->
736 main_console_handle, '[');
737 console_makeavail(m->
738 main_console_handle, '1');
739 console_makeavail(m->
740 main_console_handle, '7' +
741 x - 72);
742 break;
743 case 75: /* F9 */
744 case 76: /* F10 */
745 console_makeavail(m->
746 main_console_handle, 27);
747 console_makeavail(m->
748 main_console_handle, '[');
749 console_makeavail(m->
750 main_console_handle, '2');
751 console_makeavail(m->
752 main_console_handle, '1' +
753 x - 68);
754 break;
755 case 95: /* F11 */
756 case 96: /* F12 */
757 console_makeavail(m->
758 main_console_handle, 27);
759 console_makeavail(m->
760 main_console_handle, '[');
761 console_makeavail(m->
762 main_console_handle, '2');
763 console_makeavail(m->
764 main_console_handle, '3' +
765 x - 95);
766 break;
767 /* Cursor keys: */
768 case 98: /* Up */
769 case 104: /* Down */
770 case 100: /* Left */
771 case 102: /* Right */
772 console_makeavail(m->
773 main_console_handle, 27);
774 console_makeavail(m->
775 main_console_handle, '[');
776 console_makeavail(m->
777 main_console_handle,
778 x == 98? 'A' : (
779 x == 104? 'B' : (
780 x == 102? 'C' : (
781 'D'))));
782 break;
783 /* Numeric keys: */
784 case 80: /* Up */
785 case 88: /* Down */
786 case 83: /* Left */
787 case 85: /* Right */
788 console_makeavail(m->
789 main_console_handle, 27);
790 console_makeavail(m->
791 main_console_handle, '[');
792 console_makeavail(m->
793 main_console_handle,
794 x == 80? 'A' : (
795 x == 88? 'B' : (
796 x == 85? 'C' : (
797 'D'))));
798 break;
799 case 97: /* Cursor Home */
800 case 79: /* Numeric Home */
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, 'H');
807 break;
808 case 103: /* Cursor End */
809 case 87: /* Numeric End */
810 console_makeavail(m->
811 main_console_handle, 27);
812 console_makeavail(m->
813 main_console_handle, '[');
814 console_makeavail(m->
815 main_console_handle, 'F');
816 break;
817 case 99: /* Cursor PgUp */
818 case 81: /* Numeric PgUp */
819 console_makeavail(m->
820 main_console_handle, 27);
821 console_makeavail(m->
822 main_console_handle, '[');
823 console_makeavail(m->
824 main_console_handle, '5');
825 console_makeavail(m->
826 main_console_handle, '~');
827 break;
828 case 105: /* Cursor PgUp */
829 case 89: /* Numeric PgDn */
830 console_makeavail(m->
831 main_console_handle, 27);
832 console_makeavail(m->
833 main_console_handle, '[');
834 console_makeavail(m->
835 main_console_handle, '6');
836 console_makeavail(m->
837 main_console_handle, '~');
838 break;
839 default:
840 debug("[ unimplemented X11 "
841 "keycode %i ]\n", x);
842 }
843 }
844 }
845 }
846
847 if (need_redraw)
848 x11_redraw(m, fb_nr);
849 }
850 }
851
852
853 /*
854 * x11_check_event():
855 *
856 * Check for X11 events.
857 */
858 void x11_check_event(struct emul **emuls, int n_emuls)
859 {
860 int i, j;
861
862 for (i=0; i<n_emuls; i++)
863 for (j=0; j<emuls[i]->n_machines; j++)
864 x11_check_events_machine(emuls, n_emuls,
865 emuls[i]->machines[j]);
866 }
867
868 #endif /* WITH_X11 */

  ViewVC Help
Powered by ViewVC 1.1.26