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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (hide annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 23243 byte(s)
0.4.6
1 dpavlin 2 /*
2 dpavlin 34 * Copyright (C) 2003-2007 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 42 * $Id: x11.c,v 1.65 2007/06/15 17:02:38 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 dpavlin 42 struct fb_window *fbwin = m->x11_md.fb_windows[i];
78 dpavlin 2
79     /* Remove old cursor, if any: */
80 dpavlin 42 if (fbwin->x11_display != NULL && fbwin->OLD_cursor_on) {
81     XPutImage(fbwin->x11_display, fbwin->x11_fb_window,
82     fbwin->x11_fb_gc, fbwin->fb_ximage,
83     fbwin->OLD_cursor_x/fbwin->scaledown,
84     fbwin->OLD_cursor_y/fbwin->scaledown,
85     fbwin->OLD_cursor_x/fbwin->scaledown,
86     fbwin->OLD_cursor_y/fbwin->scaledown,
87     fbwin->OLD_cursor_xsize/fbwin->scaledown + 1,
88     fbwin->OLD_cursor_ysize/fbwin->scaledown + 1);
89 dpavlin 2 }
90    
91 dpavlin 42 if (fbwin->x11_display != NULL && fbwin->cursor_on) {
92 dpavlin 2 int x, y, subx, suby;
93     XImage *xtmp;
94    
95 dpavlin 42 CHECK_ALLOCATION(xtmp = XSubImage(fbwin->fb_ximage,
96     fbwin->cursor_x/fbwin->scaledown,
97     fbwin->cursor_y/fbwin->scaledown,
98     fbwin->cursor_xsize/fbwin->scaledown + 1,
99     fbwin->cursor_ysize/fbwin->scaledown + 1));
100 dpavlin 2
101 dpavlin 42 for (y=0; y<fbwin->cursor_ysize;
102     y+=fbwin->scaledown)
103     for (x=0; x<fbwin->cursor_xsize;
104     x+=fbwin->scaledown) {
105     int px = x/fbwin->scaledown;
106     int py = y/fbwin->scaledown;
107 dpavlin 2 int p = 0, n = 0, c = 0;
108     unsigned long oldcol;
109    
110 dpavlin 42 for (suby=0; suby<fbwin->scaledown;
111 dpavlin 2 suby++)
112 dpavlin 42 for (subx=0; subx<fbwin->
113 dpavlin 2 scaledown; subx++) {
114 dpavlin 42 c = fbwin->
115 dpavlin 2 cursor_pixels[y+suby]
116     [x+subx];
117     if (c >= 0) {
118     p += c;
119     n++;
120     }
121     }
122     if (n > 0)
123     p /= n;
124     else
125     p = c;
126    
127     if (n_colors_used == 0) {
128     last_color_used = p;
129     n_colors_used = 1;
130     } else
131     if (p != last_color_used)
132     n_colors_used = 2;
133    
134     switch (p) {
135     case CURSOR_COLOR_TRANSPARENT:
136     break;
137     case CURSOR_COLOR_INVERT:
138     oldcol = XGetPixel(xtmp, px, py);
139 dpavlin 42 if (oldcol != fbwin->
140 dpavlin 2 x11_graycolor[N_GRAYCOLORS-1].pixel)
141 dpavlin 42 oldcol = fbwin->
142 dpavlin 2 x11_graycolor[N_GRAYCOLORS
143     -1].pixel;
144     else
145 dpavlin 42 oldcol = fbwin->
146 dpavlin 2 x11_graycolor[0].pixel;
147     XPutPixel(xtmp, px, py, oldcol);
148     break;
149     default: /* Normal grayscale: */
150 dpavlin 42 XPutPixel(xtmp, px, py, fbwin->
151     x11_graycolor[p].pixel);
152 dpavlin 2 }
153     }
154    
155 dpavlin 42 XPutImage(fbwin->x11_display,
156     fbwin->x11_fb_window,
157     fbwin->x11_fb_gc,
158 dpavlin 2 xtmp, 0, 0,
159 dpavlin 42 fbwin->cursor_x/fbwin->scaledown,
160     fbwin->cursor_y/fbwin->scaledown,
161     fbwin->cursor_xsize/fbwin->scaledown,
162     fbwin->cursor_ysize/fbwin->scaledown);
163 dpavlin 2
164     XDestroyImage(xtmp);
165    
166 dpavlin 42 fbwin->OLD_cursor_on = fbwin->cursor_on;
167     fbwin->OLD_cursor_x = fbwin->cursor_x;
168     fbwin->OLD_cursor_y = fbwin->cursor_y;
169     fbwin->OLD_cursor_xsize =
170     fbwin->cursor_xsize;
171     fbwin->OLD_cursor_ysize =
172     fbwin->cursor_ysize;
173 dpavlin 2 }
174    
175     /* printf("n_colors_used = %i\n", n_colors_used); */
176    
177 dpavlin 42 if (fbwin->host_cursor != 0 && n_colors_used < 2) {
178 dpavlin 2 /* Remove the old X11 host cursor: */
179 dpavlin 42 XUndefineCursor(fbwin->x11_display,
180     fbwin->x11_fb_window);
181     XFreeCursor(fbwin->x11_display,
182     fbwin->host_cursor);
183     fbwin->host_cursor = 0;
184 dpavlin 2 }
185    
186 dpavlin 42 if (n_colors_used >= 2 && fbwin->host_cursor == 0) {
187 dpavlin 2 GC tmpgc;
188    
189     /* Create a new X11 host cursor: */
190 dpavlin 42 /* cursor = XCreateFontCursor(fbwin->x11_display,
191 dpavlin 2 XC_coffee_mug); :-) */
192 dpavlin 42 if (fbwin->host_cursor_pixmap != 0) {
193     XFreePixmap(fbwin->x11_display,
194     fbwin->host_cursor_pixmap);
195     fbwin->host_cursor_pixmap = 0;
196 dpavlin 2 }
197 dpavlin 42 fbwin->host_cursor_pixmap =
198     XCreatePixmap(fbwin->x11_display,
199     fbwin->x11_fb_window, 1, 1, 1);
200     XSetForeground(fbwin->x11_display,
201     fbwin->x11_fb_gc,
202     fbwin->x11_graycolor[0].pixel);
203 dpavlin 2
204 dpavlin 42 tmpgc = XCreateGC(fbwin->x11_display,
205     fbwin->host_cursor_pixmap, 0,0);
206 dpavlin 2
207 dpavlin 42 XDrawPoint(fbwin->x11_display,
208     fbwin->host_cursor_pixmap,
209 dpavlin 2 tmpgc, 0, 0);
210    
211 dpavlin 42 XFreeGC(fbwin->x11_display, tmpgc);
212 dpavlin 2
213 dpavlin 42 fbwin->host_cursor =
214     XCreatePixmapCursor(fbwin->x11_display,
215     fbwin->host_cursor_pixmap,
216     fbwin->host_cursor_pixmap,
217     &fbwin->x11_graycolor[N_GRAYCOLORS-1],
218     &fbwin->x11_graycolor[N_GRAYCOLORS-1],
219 dpavlin 2 0, 0);
220 dpavlin 42 if (fbwin->host_cursor != 0) {
221     XDefineCursor(fbwin->x11_display,
222     fbwin->x11_fb_window,
223     fbwin->host_cursor);
224 dpavlin 2 }
225     }
226     }
227    
228    
229     /*
230     * x11_redraw():
231     *
232     * Redraw X11 windows.
233     */
234     void x11_redraw(struct machine *m, int i)
235     {
236 dpavlin 42 if (i < 0 || i >= m->x11_md.n_fb_windows ||
237     m->x11_md.fb_windows[i]->x11_fb_winxsize <= 0)
238 dpavlin 2 return;
239    
240     x11_putimage_fb(m, i);
241     x11_redraw_cursor(m, i);
242 dpavlin 42 XFlush(m->x11_md.fb_windows[i]->x11_display);
243 dpavlin 2 }
244    
245    
246     /*
247     * x11_putpixel_fb():
248     *
249     * Output a framebuffer pixel. i is the framebuffer number.
250     */
251     void x11_putpixel_fb(struct machine *m, int i, int x, int y, int color)
252     {
253 dpavlin 42 struct fb_window *fbwin;
254     if (i < 0 || i >= m->x11_md.n_fb_windows)
255 dpavlin 2 return;
256    
257 dpavlin 42 fbwin = m->x11_md.fb_windows[i];
258    
259     if (fbwin->x11_fb_winxsize <= 0)
260     return;
261    
262 dpavlin 2 if (color)
263 dpavlin 42 XSetForeground(fbwin->x11_display,
264     fbwin->x11_fb_gc, fbwin->fg_color);
265 dpavlin 2 else
266 dpavlin 42 XSetForeground(fbwin->x11_display,
267     fbwin->x11_fb_gc, fbwin->bg_color);
268 dpavlin 2
269 dpavlin 42 XDrawPoint(fbwin->x11_display,
270     fbwin->x11_fb_window, fbwin->x11_fb_gc, x, y);
271 dpavlin 2
272 dpavlin 42 XFlush(fbwin->x11_display);
273 dpavlin 2 }
274    
275    
276     /*
277     * x11_putimage_fb():
278     *
279     * Output an entire XImage to a framebuffer window. i is the
280     * framebuffer number.
281     */
282     void x11_putimage_fb(struct machine *m, int i)
283     {
284 dpavlin 42 struct fb_window *fbwin;
285     if (i < 0 || i >= m->x11_md.n_fb_windows)
286 dpavlin 2 return;
287    
288 dpavlin 42 fbwin = m->x11_md.fb_windows[i];
289    
290     if (fbwin->x11_fb_winxsize <= 0)
291     return;
292    
293     XPutImage(fbwin->x11_display,
294     fbwin->x11_fb_window,
295     fbwin->x11_fb_gc, fbwin->fb_ximage, 0,0, 0,0,
296     fbwin->x11_fb_winxsize,
297     fbwin->x11_fb_winysize);
298     XFlush(fbwin->x11_display);
299 dpavlin 2 }
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 dpavlin 42 m->x11_md.n_fb_windows = 0;
313 dpavlin 2
314 dpavlin 42 if (m->x11_md.n_display_names > 0) {
315 dpavlin 2 int i;
316 dpavlin 42 for (i=0; i<m->x11_md.n_display_names; i++)
317 dpavlin 2 fatal("Using X11 display: %s\n",
318 dpavlin 42 m->x11_md.display_names[i]);
319 dpavlin 2 }
320    
321 dpavlin 42 m->x11_md.current_display_name_nr = 0;
322 dpavlin 2 }
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 dpavlin 42 CHECK_ALLOCATION(win->ximage_data = malloc(
354     new_xsize * new_ysize * alloc_depth / 8));
355 dpavlin 6
356     /* TODO: clear for non-truecolor modes */
357     memset(win->ximage_data, 0, new_xsize * new_ysize * alloc_depth / 8);
358    
359     if (win->fb_ximage != NULL)
360     XDestroyImage(win->fb_ximage);
361     win->fb_ximage = XCreateImage(win->x11_display, CopyFromParent,
362     win->x11_screen_depth, ZPixmap, 0, (char *)win->ximage_data,
363     new_xsize, new_ysize, 8, new_xsize * alloc_depth / 8);
364 dpavlin 42 CHECK_ALLOCATION(win->fb_ximage);
365 dpavlin 6
366     XResizeWindow(win->x11_display, win->x11_fb_window,
367     new_xsize, new_ysize);
368     }
369    
370    
371     /*
372 dpavlin 28 * x11_set_standard_properties():
373     *
374     * Right now, this only sets the title of a window.
375     */
376     void x11_set_standard_properties(struct fb_window *fb_window, char *name)
377     {
378     XSetStandardProperties(fb_window->x11_display,
379     fb_window->x11_fb_window, name,
380     #ifdef VERSION
381     "GXemul-" VERSION,
382     #else
383     "GXemul",
384     #endif
385     None, NULL, 0, NULL);
386     }
387    
388    
389     /*
390 dpavlin 2 * x11_fb_init():
391     *
392     * Initialize a framebuffer window.
393     */
394     struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
395     int scaledown, struct machine *m)
396     {
397     Display *x11_display;
398     int x, y, fb_number = 0;
399     size_t alloclen, alloc_depth;
400     XColor tmpcolor;
401 dpavlin 42 struct fb_window *fbwin;
402 dpavlin 2 int i;
403     char fg[80], bg[80];
404     char *display_name;
405    
406 dpavlin 42 fb_number = m->x11_md.n_fb_windows;
407 dpavlin 2
408 dpavlin 42 CHECK_ALLOCATION(m->x11_md.fb_windows = realloc(m->x11_md.fb_windows,
409     sizeof(struct fb_window *) * (m->x11_md.n_fb_windows + 1)));
410     CHECK_ALLOCATION(fbwin = m->x11_md.fb_windows[fb_number] =
411     malloc(sizeof(struct fb_window)));
412 dpavlin 2
413 dpavlin 42 m->x11_md.n_fb_windows ++;
414 dpavlin 2
415 dpavlin 42 memset(fbwin, 0, sizeof(struct fb_window));
416 dpavlin 2
417 dpavlin 42 fbwin->x11_fb_winxsize = xsize;
418     fbwin->x11_fb_winysize = ysize;
419 dpavlin 2
420     /* Which display name? */
421     display_name = NULL;
422 dpavlin 42 if (m->x11_md.n_display_names > 0) {
423     display_name = m->x11_md.display_names[
424     m->x11_md.current_display_name_nr];
425     m->x11_md.current_display_name_nr ++;
426     m->x11_md.current_display_name_nr %= m->x11_md.n_display_names;
427 dpavlin 2 }
428    
429     if (display_name != NULL)
430     debug("[ x11_fb_init(): framebuffer window %i, %ix%i, DISPLAY"
431     "=%s ]\n", fb_number, xsize, ysize, display_name);
432    
433     x11_display = XOpenDisplay(display_name);
434    
435     if (x11_display == NULL) {
436     fatal("x11_fb_init(\"%s\"): couldn't open display\n", name);
437     if (display_name != NULL)
438     fatal("display_name = '%s'\n", display_name);
439     exit(1);
440     }
441    
442 dpavlin 42 fbwin->x11_screen =
443     DefaultScreen(x11_display);
444     fbwin->x11_screen_depth =
445     DefaultDepth(x11_display,
446     fbwin->x11_screen);
447 dpavlin 2
448 dpavlin 42 if (fbwin->x11_screen_depth != 8 &&
449     fbwin->x11_screen_depth != 15 &&
450     fbwin->x11_screen_depth != 16 &&
451     fbwin->x11_screen_depth != 24) {
452 dpavlin 2 fatal("\n***\n*** WARNING! Your X server is running %i-bit "
453     "color mode. This is not really\n",
454 dpavlin 42 fbwin->x11_screen_depth);
455 dpavlin 2 fatal("*** supported yet. 8, 15, 16, and 24 bits should "
456     "work.\n*** 24-bit server gives color. Any other bit "
457     "depth gives undefined result!\n***\n\n");
458     }
459    
460 dpavlin 42 if (fbwin->x11_screen_depth <= 8)
461 dpavlin 2 debug("WARNING! X11 screen depth is not enough for color; "
462     "using only 16 grayscales instead\n");
463    
464 dpavlin 10 strlcpy(bg, "Black", sizeof(bg));
465     strlcpy(fg, "White", sizeof(fg));
466 dpavlin 2
467     XParseColor(x11_display, DefaultColormap(x11_display,
468 dpavlin 42 fbwin->x11_screen), fg, &tmpcolor);
469 dpavlin 2 XAllocColor(x11_display, DefaultColormap(x11_display,
470 dpavlin 42 fbwin->x11_screen), &tmpcolor);
471     fbwin->fg_color = tmpcolor.pixel;
472 dpavlin 2 XParseColor(x11_display, DefaultColormap(x11_display,
473 dpavlin 42 fbwin->x11_screen), bg, &tmpcolor);
474 dpavlin 2 XAllocColor(x11_display, DefaultColormap(x11_display,
475 dpavlin 42 fbwin->x11_screen), &tmpcolor);
476     fbwin->bg_color = tmpcolor.pixel;
477 dpavlin 2
478     for (i=0; i<N_GRAYCOLORS; i++) {
479     char cname[8];
480     cname[0] = '#';
481     cname[1] = cname[2] = cname[3] =
482     cname[4] = cname[5] = cname[6] =
483     "0123456789ABCDEF"[i];
484     cname[7] = '\0';
485     XParseColor(x11_display, DefaultColormap(x11_display,
486 dpavlin 42 fbwin->x11_screen), cname,
487     &fbwin->x11_graycolor[i]);
488 dpavlin 2 XAllocColor(x11_display, DefaultColormap(x11_display,
489 dpavlin 42 fbwin->x11_screen),
490     &fbwin->x11_graycolor[i]);
491 dpavlin 2 }
492    
493     XFlush(x11_display);
494    
495 dpavlin 42 alloc_depth = fbwin->x11_screen_depth;
496 dpavlin 2
497     if (alloc_depth == 24)
498     alloc_depth = 32;
499     if (alloc_depth == 15)
500     alloc_depth = 16;
501    
502 dpavlin 42 fbwin->x11_fb_window = XCreateWindow(
503 dpavlin 2 x11_display, DefaultRootWindow(x11_display),
504 dpavlin 42 0, 0, fbwin->x11_fb_winxsize,
505     fbwin->x11_fb_winysize,
506 dpavlin 2 0, CopyFromParent, InputOutput, CopyFromParent, 0,0);
507    
508 dpavlin 42 fbwin->x11_display = x11_display;
509 dpavlin 28
510 dpavlin 42 x11_set_standard_properties(fbwin, name);
511 dpavlin 28
512 dpavlin 42 XSelectInput(x11_display,
513     fbwin->x11_fb_window,
514 dpavlin 2 StructureNotifyMask | ExposureMask | ButtonPressMask |
515     ButtonReleaseMask | PointerMotionMask | KeyPressMask);
516 dpavlin 42 fbwin->x11_fb_gc = XCreateGC(x11_display,
517     fbwin->x11_fb_window, 0,0);
518 dpavlin 2
519     /* Make sure the window is mapped: */
520 dpavlin 42 XMapRaised(x11_display, fbwin->x11_fb_window);
521 dpavlin 2
522 dpavlin 42 XSetBackground(x11_display, fbwin->x11_fb_gc, fbwin->bg_color);
523     XSetForeground(x11_display, fbwin->x11_fb_gc, fbwin->bg_color);
524     XFillRectangle(x11_display, fbwin->x11_fb_window, fbwin->x11_fb_gc, 0,0,
525     fbwin->x11_fb_winxsize, fbwin->x11_fb_winysize);
526 dpavlin 2
527 dpavlin 42 fbwin->scaledown = scaledown;
528 dpavlin 2
529 dpavlin 42 fbwin->fb_number = fb_number;
530 dpavlin 2
531     alloclen = xsize * ysize * alloc_depth / 8;
532 dpavlin 42 CHECK_ALLOCATION(fbwin->ximage_data = malloc(alloclen));
533 dpavlin 2
534 dpavlin 42 fbwin->fb_ximage = XCreateImage(fbwin->x11_display, CopyFromParent,
535     fbwin->x11_screen_depth, ZPixmap, 0, (char *)fbwin->ximage_data,
536 dpavlin 2 xsize, ysize, 8, xsize * alloc_depth / 8);
537 dpavlin 42 CHECK_ALLOCATION(fbwin->fb_ximage);
538 dpavlin 2
539     /* Fill the ximage with black pixels: */
540 dpavlin 42 if (fbwin->x11_screen_depth > 8)
541     memset(fbwin->ximage_data, 0, alloclen);
542 dpavlin 2 else {
543     debug("x11_fb_init(): clearing the XImage\n");
544     for (y=0; y<ysize; y++)
545     for (x=0; x<xsize; x++)
546 dpavlin 42 XPutPixel(fbwin->fb_ximage, x, y,
547     fbwin->x11_graycolor[0].pixel);
548 dpavlin 2 }
549    
550     x11_putimage_fb(m, fb_number);
551    
552     /* Fill the 64x64 "hardware" cursor with white pixels: */
553     xsize = ysize = 64;
554    
555     /* Fill the cursor ximage with white pixels: */
556     for (y=0; y<ysize; y++)
557     for (x=0; x<xsize; x++)
558 dpavlin 42 fbwin->cursor_pixels[y][x] = N_GRAYCOLORS-1;
559 dpavlin 2
560 dpavlin 42 return fbwin;
561 dpavlin 2 }
562    
563    
564     /*
565     * x11_check_events_machine():
566     *
567     * Check for X11 events on a specific machine.
568     *
569     * TODO: Yuck! This has to be rewritten. Each display should be checked,
570     * and _then_ only those windows that are actually exposed should
571     * be redrawn!
572     */
573     static void x11_check_events_machine(struct emul **emuls, int n_emuls,
574     struct machine *m)
575     {
576     int fb_nr;
577    
578 dpavlin 42 for (fb_nr = 0; fb_nr < m->x11_md.n_fb_windows; fb_nr ++) {
579     struct fb_window *fbwin = m->x11_md.fb_windows[fb_nr];
580 dpavlin 2 XEvent event;
581     int need_redraw = 0, found, i, j, k;
582    
583 dpavlin 42 while (XPending(fbwin->x11_display)) {
584     XNextEvent(fbwin->x11_display, &event);
585 dpavlin 2
586     if (event.type==ConfigureNotify) {
587     need_redraw = 1;
588     }
589    
590     if (event.type==Expose && event.xexpose.count==0) {
591     /*
592     * TODO: the xexpose struct has x,y,width,
593     * height. Those could be used to only redraw
594     * the part of the framebuffer that was
595     * exposed. Note that the (mouse) cursor must
596     * be redrawn too.
597     */
598     /* x11_winxsize = event.xexpose.width;
599     x11_winysize = event.xexpose.height; */
600     need_redraw = 1;
601     }
602    
603     if (event.type == MotionNotify) {
604     /* debug("[ X11 MotionNotify: %i,%i ]\n",
605     event.xmotion.x, event.xmotion.y); */
606    
607     /* Which window in which machine in
608     which emulation? */
609     found = -1;
610     for (k=0; k<n_emuls; k++)
611     for (j=0; j<emuls[k]->n_machines; j++) {
612     struct machine *m2 = emuls[k]->
613     machines[j];
614 dpavlin 42 for (i=0; i<m2->x11_md.
615     n_fb_windows; i++)
616     if (m->x11_md.
617     fb_windows[fb_nr]->
618 dpavlin 2 x11_display == m2->
619 dpavlin 42 x11_md.
620 dpavlin 2 fb_windows[i]->
621     x11_display &&
622     event.xmotion.
623     window == m2->
624 dpavlin 42 x11_md.
625 dpavlin 2 fb_windows[i]->
626     x11_fb_window)
627     found = i;
628     }
629     if (found < 0) {
630     printf("Internal error in x11.c.\n");
631     exit(1);
632     }
633     console_mouse_coordinates(event.xmotion.x *
634 dpavlin 42 m->x11_md.fb_windows[found]->scaledown,
635     event.xmotion.y * m->x11_md.fb_windows[
636     found]->scaledown, found);
637 dpavlin 2 }
638    
639     if (event.type == ButtonPress) {
640     debug("[ X11 ButtonPress: %i ]\n",
641     event.xbutton.button);
642     /* button = 1,2,3 = left,middle,right */
643    
644     console_mouse_button(event.xbutton.button, 1);
645     }
646    
647     if (event.type == ButtonRelease) {
648     debug("[ X11 ButtonRelease: %i ]\n",
649     event.xbutton.button);
650     /* button = 1,2,3 = left,middle,right */
651    
652     console_mouse_button(event.xbutton.button, 0);
653     }
654    
655     if (event.type==KeyPress) {
656     char text[15];
657     KeySym key;
658     XKeyPressedEvent *ke = &event.xkey;
659    
660 dpavlin 38 memset(text, 0, sizeof(text));
661 dpavlin 2
662     if (XLookupString(&event.xkey, text,
663     sizeof(text), &key, 0) == 1) {
664     console_makeavail(
665     m->main_console_handle, text[0]);
666     } else {
667     int x = ke->keycode;
668     /*
669     * Special key codes:
670     *
671     * NOTE/TODO: I'm hardcoding these to
672     * work with my key map. Maybe they
673     * should be read from some file...
674     *
675     * Important TODO 2: It would be MUCH
676     * better if these were converted into
677     * 'native scancodes', for example for
678     * the DECstation's keyboard or the
679     * PC-style 8042 controller.
680     */
681     switch (x) {
682     case 9: /* Escape */
683     console_makeavail(m->
684     main_console_handle, 27);
685     break;
686     #if 0
687     /* TODO */
688    
689     /* The numeric keypad: */
690     90=Ins('0') 91=Del(',')
691    
692     /* Above the cursor keys: */
693     106=Ins 107=Del
694     #endif
695     /* F1..F4: */
696     case 67: /* F1 */
697     case 68: /* F2 */
698     case 69: /* F3 */
699     case 70: /* F4 */
700     console_makeavail(m->
701     main_console_handle, 27);
702     console_makeavail(m->
703     main_console_handle, '[');
704     console_makeavail(m->
705     main_console_handle, 'O');
706     console_makeavail(m->
707     main_console_handle, 'P' +
708     x - 67);
709     break;
710     case 71: /* F5 */
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, '1');
717     console_makeavail(m->
718     main_console_handle, '5');
719     break;
720     case 72: /* F6 */
721     case 73: /* F7 */
722     case 74: /* F8 */
723     console_makeavail(m->
724     main_console_handle, 27);
725     console_makeavail(m->
726     main_console_handle, '[');
727     console_makeavail(m->
728     main_console_handle, '1');
729     console_makeavail(m->
730     main_console_handle, '7' +
731     x - 72);
732     break;
733     case 75: /* F9 */
734     case 76: /* F10 */
735     console_makeavail(m->
736     main_console_handle, 27);
737     console_makeavail(m->
738     main_console_handle, '[');
739     console_makeavail(m->
740     main_console_handle, '2');
741     console_makeavail(m->
742     main_console_handle, '1' +
743     x - 68);
744     break;
745     case 95: /* F11 */
746     case 96: /* F12 */
747     console_makeavail(m->
748     main_console_handle, 27);
749     console_makeavail(m->
750     main_console_handle, '[');
751     console_makeavail(m->
752     main_console_handle, '2');
753     console_makeavail(m->
754     main_console_handle, '3' +
755     x - 95);
756     break;
757     /* Cursor keys: */
758     case 98: /* Up */
759     case 104: /* Down */
760     case 100: /* Left */
761     case 102: /* Right */
762     console_makeavail(m->
763     main_console_handle, 27);
764     console_makeavail(m->
765     main_console_handle, '[');
766     console_makeavail(m->
767     main_console_handle,
768     x == 98? 'A' : (
769     x == 104? 'B' : (
770     x == 102? 'C' : (
771     'D'))));
772     break;
773     /* Numeric keys: */
774     case 80: /* Up */
775     case 88: /* Down */
776     case 83: /* Left */
777     case 85: /* Right */
778     console_makeavail(m->
779     main_console_handle, 27);
780     console_makeavail(m->
781     main_console_handle, '[');
782     console_makeavail(m->
783     main_console_handle,
784     x == 80? 'A' : (
785     x == 88? 'B' : (
786     x == 85? 'C' : (
787     'D'))));
788     break;
789     case 97: /* Cursor Home */
790     case 79: /* Numeric Home */
791     console_makeavail(m->
792     main_console_handle, 27);
793     console_makeavail(m->
794     main_console_handle, '[');
795     console_makeavail(m->
796     main_console_handle, 'H');
797     break;
798     case 103: /* Cursor End */
799     case 87: /* Numeric End */
800     console_makeavail(m->
801     main_console_handle, 27);
802     console_makeavail(m->
803     main_console_handle, '[');
804     console_makeavail(m->
805     main_console_handle, 'F');
806     break;
807     case 99: /* Cursor PgUp */
808     case 81: /* Numeric PgUp */
809     console_makeavail(m->
810     main_console_handle, 27);
811     console_makeavail(m->
812     main_console_handle, '[');
813     console_makeavail(m->
814     main_console_handle, '5');
815     console_makeavail(m->
816     main_console_handle, '~');
817     break;
818     case 105: /* Cursor PgUp */
819     case 89: /* Numeric PgDn */
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, '6');
826     console_makeavail(m->
827     main_console_handle, '~');
828     break;
829     default:
830     debug("[ unimplemented X11 "
831     "keycode %i ]\n", x);
832     }
833     }
834     }
835     }
836    
837     if (need_redraw)
838     x11_redraw(m, fb_nr);
839     }
840     }
841    
842    
843     /*
844     * x11_check_event():
845     *
846     * Check for X11 events.
847     */
848     void x11_check_event(struct emul **emuls, int n_emuls)
849     {
850     int i, j;
851    
852     for (i=0; i<n_emuls; i++)
853     for (j=0; j<emuls[i]->n_machines; j++)
854     x11_check_events_machine(emuls, n_emuls,
855     emuls[i]->machines[j]);
856     }
857    
858     #endif /* WITH_X11 */

  ViewVC Help
Powered by ViewVC 1.1.26