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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations)
Mon Oct 8 16:20:03 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 25543 byte(s)
0.4.0
1 dpavlin 2 /*
2 dpavlin 22 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 dpavlin 2 *
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 22 * $Id: x11.c,v 1.61 2006/01/14 12:51:59 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 dpavlin 22 *
71     * NOTE: It is up to the caller to call XFlush.
72 dpavlin 2 */
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 dpavlin 6 * 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 dpavlin 2 * 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 dpavlin 10 strlcpy(bg, "Black", sizeof(bg));
459     strlcpy(fg, "White", sizeof(fg));
460 dpavlin 2
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