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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show annotations)
Mon Oct 8 16:18:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25615 byte(s)
0.3.6
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