/[gxemul]/upstream/0.3.6.1/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

Annotation of /upstream/0.3.6.1/src/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (hide annotations)
Mon Oct 8 16:19:05 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25615 byte(s)
0.3.6.1
1 dpavlin 2 /*
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 dpavlin 10 * $Id: x11.c,v 1.59 2005/06/20 05:52:47 debug Exp $
29 dpavlin 2 *
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 dpavlin 6 * 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 dpavlin 2 * 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 dpavlin 10 strlcpy(bg, "Black", sizeof(bg));
460     strlcpy(fg, "White", sizeof(fg));
461 dpavlin 2
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