/[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 10 - (show annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 25615 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


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.59 2005/06/20 05:52:47 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 strlcpy(bg, "Black", sizeof(bg));
460 strlcpy(fg, "White", sizeof(fg));
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