/[gxemul]/upstream/0.3.8/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 /upstream/0.3.8/src/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26