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

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


1 /*
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.62 2006/07/08 12:30:02 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_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 * 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 strlcpy(bg, "Black", sizeof(bg));
477 strlcpy(fg, "White", sizeof(fg));
478
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 m->fb_windows[fb_number]->x11_display = x11_display;
521
522 x11_set_standard_properties(m->fb_windows[fb_number], name);
523
524 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