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

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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26