/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 25781 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


1 /*
2 * Copyright (C) 2003-2007 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.64 2007/03/29 06:52:19 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, 0, sizeof(text));
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