/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.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 /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 250 - (hide annotations)
Sun Nov 3 12:33:02 2002 UTC (21 years, 6 months ago) by matthewc
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 26523 byte(s)
Focus upon receiving EnterNotify in fullscreen mode (in lieu of window manager)

1 matty 6 /*
2     rdesktop: A Remote Desktop Protocol client.
3 matthewc 38 User interface services - X Window System
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
5 n-ki 52
6 matty 6 This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 n-ki 52
11 matty 6 This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15 n-ki 52
16 matty 6 You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21 matty 10 #include <X11/Xlib.h>
22 matty 28 #include <X11/Xutil.h>
23 matty 10 #include <time.h>
24 matty 33 #include <errno.h>
25 matty 10 #include "rdesktop.h"
26 matty 6
27 matty 10 extern int width;
28     extern int height;
29 matty 29 extern BOOL sendmotion;
30 matty 28 extern BOOL fullscreen;
31 astrand 76 extern BOOL grab_keyboard;
32 jsorg71 100 extern char title[];
33 matthewc 188 BOOL enable_compose = False;
34 matty 10
35 matthewc 121 Display *display;
36 matty 33 static int x_socket;
37 matthewc 121 static Screen *screen;
38 matty 10 static Window wnd;
39     static GC gc;
40     static Visual *visual;
41 matty 29 static int depth;
42     static int bpp;
43 matthewc 188 static XIM IM;
44     static XIC IC;
45 matthewc 203 static XModifierKeymap *mod_map;
46 matthewc 188 static Cursor current_cursor;
47 matty 29
48 matty 33 /* endianness */
49     static BOOL host_be;
50     static BOOL xserver_be;
51    
52     /* software backing store */
53 matty 31 static BOOL ownbackstore;
54     static Pixmap backstore;
55    
56     #define FILL_RECTANGLE(x,y,cx,cy)\
57     { \
58     XFillRectangle(display, wnd, gc, x, y, cx, cy); \
59     if (ownbackstore) \
60     XFillRectangle(display, backstore, gc, x, y, cx, cy); \
61     }
62    
63 matty 33 /* colour maps */
64 matty 29 static Colormap xcolmap;
65 matty 28 static uint32 *colmap;
66 matty 10
67 n-ki 185 #define SET_FOREGROUND(col) XSetForeground(display, gc, translate_colour(colmap[col]));
68     #define SET_BACKGROUND(col) XSetBackground(display, gc, translate_colour(colmap[col]));
69 matty 28
70     static int rop2_map[] = {
71     GXclear, /* 0 */
72     GXnor, /* DPon */
73     GXandInverted, /* DPna */
74     GXcopyInverted, /* Pn */
75     GXandReverse, /* PDna */
76     GXinvert, /* Dn */
77     GXxor, /* DPx */
78     GXnand, /* DPan */
79     GXand, /* DPa */
80     GXequiv, /* DPxn */
81     GXnoop, /* D */
82     GXorInverted, /* DPno */
83     GXcopy, /* P */
84     GXorReverse, /* PDno */
85     GXor, /* DPo */
86     GXset /* 1 */
87     };
88    
89 matty 29 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
90     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
91    
92 matty 28 static void
93 astrand 64 translate8(uint8 * data, uint8 * out, uint8 * end)
94 matty 28 {
95 matty 29 while (out < end)
96 astrand 64 *(out++) = (uint8) colmap[*(data++)];
97 matty 29 }
98 matty 28
99 matty 29 static void
100 astrand 64 translate16(uint8 * data, uint16 * out, uint16 * end)
101 matty 29 {
102     while (out < end)
103 astrand 64 *(out++) = (uint16) colmap[*(data++)];
104 matty 29 }
105    
106 matty 33 /* little endian - conversion happens when colourmap is built */
107 matty 29 static void
108 astrand 64 translate24(uint8 * data, uint8 * out, uint8 * end)
109 matty 29 {
110     uint32 value;
111    
112     while (out < end)
113 matty 28 {
114 matty 29 value = colmap[*(data++)];
115     *(out++) = value;
116     *(out++) = value >> 8;
117     *(out++) = value >> 16;
118 matty 28 }
119     }
120    
121     static void
122 astrand 64 translate32(uint8 * data, uint32 * out, uint32 * end)
123 matty 28 {
124 matty 29 while (out < end)
125     *(out++) = colmap[*(data++)];
126 matty 28 }
127    
128 matty 29 static uint8 *
129 astrand 64 translate_image(int width, int height, uint8 * data)
130 matty 28 {
131 astrand 64 int size = width * height * bpp / 8;
132 matty 29 uint8 *out = xmalloc(size);
133     uint8 *end = out + size;
134    
135     switch (bpp)
136     {
137     case 8:
138     translate8(data, out, end);
139     break;
140    
141     case 16:
142 astrand 64 translate16(data, (uint16 *) out, (uint16 *) end);
143 matty 29 break;
144    
145     case 24:
146     translate24(data, out, end);
147     break;
148    
149     case 32:
150 astrand 64 translate32(data, (uint32 *) out, (uint32 *) end);
151 matty 29 break;
152     }
153    
154     return out;
155 matty 28 }
156    
157 matty 35 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
158     #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
159     #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
160     x = (x << 16) | (x >> 16); }
161 matty 29
162 matty 33 static uint32
163     translate_colour(uint32 colour)
164     {
165     switch (bpp)
166     {
167     case 16:
168     if (host_be != xserver_be)
169     BSWAP16(colour);
170     break;
171 matty 29
172 matty 33 case 24:
173     if (xserver_be)
174     BSWAP24(colour);
175     break;
176    
177     case 32:
178     if (host_be != xserver_be)
179     BSWAP32(colour);
180     break;
181     }
182    
183     return colour;
184     }
185    
186 astrand 118 BOOL
187 matthewc 209 get_key_state(unsigned int state, uint32 keysym)
188 astrand 102 {
189 matthewc 203 int modifierpos, key, keysymMask = 0;
190 astrand 102 int offset;
191    
192     KeyCode keycode = XKeysymToKeycode(display, keysym);
193    
194     if (keycode == NoSymbol)
195     return False;
196    
197     for (modifierpos = 0; modifierpos < 8; modifierpos++)
198     {
199 matthewc 203 offset = mod_map->max_keypermod * modifierpos;
200 astrand 102
201 matthewc 203 for (key = 0; key < mod_map->max_keypermod; key++)
202 astrand 102 {
203 matthewc 203 if (mod_map->modifiermap[offset + key] == keycode)
204     keysymMask |= 1 << modifierpos;
205 astrand 102 }
206     }
207    
208 matthewc 203 return (state & keysymMask) ? True : False;
209 astrand 102 }
210    
211 jsorg71 81 BOOL
212 matthewc 192 ui_init(void)
213 jsorg71 81 {
214 matthewc 121 XPixmapFormatValues *pfm;
215     uint16 test;
216     int i;
217    
218 jsorg71 81 display = XOpenDisplay(NULL);
219     if (display == NULL)
220     {
221 matthewc 210 error("Failed to open display: %s\n", XDisplayName(NULL));
222 jsorg71 81 return False;
223     }
224 matthewc 121
225     x_socket = ConnectionNumber(display);
226     screen = DefaultScreenOfDisplay(display);
227     visual = DefaultVisualOfScreen(screen);
228     depth = DefaultDepthOfScreen(screen);
229    
230     pfm = XListPixmapFormats(display, &i);
231     if (pfm != NULL)
232     {
233     /* Use maximum bpp for this depth - this is generally
234     desirable, e.g. 24 bits->32 bits. */
235     while (i--)
236     {
237     if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
238     {
239     bpp = pfm[i].bits_per_pixel;
240     }
241     }
242     XFree(pfm);
243     }
244    
245     if (bpp < 8)
246     {
247     error("Less than 8 bpp not currently supported.\n");
248     XCloseDisplay(display);
249     return False;
250     }
251    
252 n-ki 185 xcolmap = DefaultColormapOfScreen(screen);
253 matthewc 188 gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
254 matthewc 121
255 matthewc 188 if (DoesBackingStore(screen) != Always)
256 matthewc 121 ownbackstore = True;
257    
258     test = 1;
259     host_be = !(BOOL) (*(uint8 *) (&test));
260     xserver_be = (ImageByteOrder(display) == MSBFirst);
261    
262 astrand 82 if (fullscreen)
263 jsorg71 81 {
264     width = WidthOfScreen(screen);
265     height = HeightOfScreen(screen);
266     }
267 matthewc 121
268 matthewc 160 /* make sure width is a multiple of 4 */
269     width = (width + 3) & ~3;
270    
271 matthewc 188 if (ownbackstore)
272     {
273 astrand 196 backstore =
274     XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
275 matthewc 188
276     /* clear to prevent rubbish being exposed at startup */
277     XSetForeground(display, gc, BlackPixelOfScreen(screen));
278     XFillRectangle(display, backstore, gc, 0, 0, width, height);
279     }
280    
281 matthewc 203 mod_map = XGetModifierMapping(display);
282    
283 matthewc 188 if (enable_compose)
284     IM = XOpenIM(display, NULL, NULL, NULL);
285    
286 matthewc 121 xkeymap_init();
287 jsorg71 81 return True;
288     }
289 astrand 66
290 matthewc 188 void
291 matthewc 192 ui_deinit(void)
292 matthewc 188 {
293     if (IM != NULL)
294     XCloseIM(IM);
295    
296 matthewc 204 XFreeModifiermap(mod_map);
297 matthewc 203
298 matthewc 188 if (ownbackstore)
299     XFreePixmap(display, backstore);
300    
301     XFreeGC(display, gc);
302     XCloseDisplay(display);
303     display = NULL;
304     }
305    
306 matthewc 121 BOOL
307 matthewc 192 ui_create_window(void)
308 matty 6 {
309 matthewc 121 XSetWindowAttributes attribs;
310 matty 28 XClassHint *classhints;
311     XSizeHints *sizehints;
312 matthewc 188 int wndwidth, wndheight;
313     long input_mask, ic_input_mask;
314 jsorg71 100 XEvent xevent;
315    
316 astrand 196 wndwidth = fullscreen ? WidthOfScreen(screen) : width;
317 matthewc 188 wndheight = fullscreen ? HeightOfScreen(screen) : height;
318    
319 matthewc 121 attribs.background_pixel = BlackPixelOfScreen(screen);
320     attribs.backing_store = ownbackstore ? NotUseful : Always;
321     attribs.override_redirect = fullscreen;
322 matthewc 188
323     wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
324 matthewc 121 0, CopyFromParent, InputOutput, CopyFromParent,
325     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
326 jsorg71 100
327     XStoreName(display, wnd, title);
328    
329     classhints = XAllocClassHint();
330     if (classhints != NULL)
331     {
332     classhints->res_name = classhints->res_class = "rdesktop";
333     XSetClassHint(display, wnd, classhints);
334     XFree(classhints);
335     }
336    
337     sizehints = XAllocSizeHints();
338     if (sizehints)
339     {
340     sizehints->flags = PMinSize | PMaxSize;
341     sizehints->min_width = sizehints->max_width = width;
342     sizehints->min_height = sizehints->max_height = height;
343     XSetWMNormalHints(display, wnd, sizehints);
344     XFree(sizehints);
345     }
346    
347 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
348 matthewc 208 VisibilityChangeMask | FocusChangeMask;
349 matthewc 121
350     if (sendmotion)
351     input_mask |= PointerMotionMask;
352     if (ownbackstore)
353     input_mask |= ExposureMask;
354 matthewc 250 if (fullscreen)
355     input_mask |= EnterWindowMask;
356 jsorg71 100
357 matthewc 188 if (IM != NULL)
358     {
359     IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
360     XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
361    
362 astrand 196 if ((IC != NULL)
363     && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
364 matthewc 188 input_mask |= ic_input_mask;
365     }
366    
367 jsorg71 100 XSelectInput(display, wnd, input_mask);
368 matthewc 188 XMapWindow(display, wnd);
369 jsorg71 100
370 matthewc 208 /* wait for VisibilityNotify */
371 astrand 196 do
372     {
373 matthewc 208 XMaskEvent(display, VisibilityChangeMask, &xevent);
374 astrand 196 }
375 matthewc 208 while (xevent.type != VisibilityNotify);
376 matthewc 123
377 matty 10 return True;
378 matty 6 }
379    
380 matty 25 void
381 matthewc 192 ui_destroy_window(void)
382 matty 6 {
383 matthewc 188 if (IC != NULL)
384     XDestroyIC(IC);
385 matty 31
386 matty 10 XDestroyWindow(display, wnd);
387 matty 6 }
388    
389 jsorg71 100 void
390 matthewc 192 xwin_toggle_fullscreen(void)
391 jsorg71 100 {
392 matthewc 188 Pixmap contents = 0;
393 matthewc 123
394 matthewc 188 if (!ownbackstore)
395     {
396     /* need to save contents of window */
397     contents = XCreatePixmap(display, wnd, width, height, depth);
398     XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
399     }
400    
401     ui_destroy_window();
402 matthewc 123 fullscreen = !fullscreen;
403 matthewc 188 ui_create_window();
404 matthewc 123
405 matthewc 188 XDefineCursor(display, wnd, current_cursor);
406    
407     if (!ownbackstore)
408     {
409     XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
410     XFreePixmap(display, contents);
411     }
412 jsorg71 100 }
413    
414 astrand 119 /* Process all events in Xlib queue */
415 matty 33 static void
416 matthewc 192 xwin_process_events(void)
417 matty 9 {
418 n-ki 54 XEvent xevent;
419 matthewc 38 KeySym keysym;
420 matthewc 50 uint16 button, flags;
421 matty 10 uint32 ev_time;
422 astrand 66 key_translation tr;
423     char str[256];
424     Status status;
425 matthewc 203 unsigned int state;
426     Window wdummy;
427     int dummy;
428 matty 9
429 matthewc 123 while (XPending(display) > 0)
430 matty 9 {
431 matthewc 123 XNextEvent(display, &xevent);
432    
433 matthewc 188 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
434 astrand 66 {
435 astrand 84 DEBUG_KBD(("Filtering event\n"));
436 astrand 66 continue;
437     }
438    
439 matthewc 50 flags = 0;
440 matty 10
441 n-ki 54 switch (xevent.type)
442 matty 9 {
443     case KeyPress:
444 astrand 66 if (IC != NULL)
445     /* Multi_key compatible version */
446     {
447     XmbLookupString(IC,
448     (XKeyPressedEvent *) &
449 astrand 82 xevent, str, sizeof(str), &keysym, &status);
450     if (!((status == XLookupKeySym) || (status == XLookupBoth)))
451 astrand 66 {
452 astrand 82 error("XmbLookupString failed with status 0x%x\n",
453     status);
454 astrand 66 break;
455     }
456     }
457     else
458     {
459     /* Plain old XLookupString */
460 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
461 astrand 66 XLookupString((XKeyEvent *) & xevent,
462 astrand 82 str, sizeof(str), &keysym, NULL);
463 astrand 66 }
464    
465 matthewc 203 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym)));
466 astrand 66
467 matthewc 203 ev_time = time(NULL);
468     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
469 astrand 118 break;
470    
471 astrand 66 tr = xkeymap_translate_key(keysym,
472 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
473 astrand 69
474 astrand 66 if (tr.scancode == 0)
475 n-ki 52 break;
476    
477 astrand 115 ensure_remote_modifiers(ev_time, tr);
478    
479 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
480 astrand 66 break;
481 matthewc 203
482 astrand 66 case KeyRelease:
483     XLookupString((XKeyEvent *) & xevent, str,
484     sizeof(str), &keysym, NULL);
485 n-ki 52
486 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
487 matthewc 203 get_ksname(keysym)));
488 n-ki 52
489 matthewc 203 ev_time = time(NULL);
490     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
491 astrand 118 break;
492    
493 astrand 66 tr = xkeymap_translate_key(keysym,
494 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
495 astrand 66
496     if (tr.scancode == 0)
497     break;
498    
499 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
500 matty 9 break;
501    
502     case ButtonPress:
503 matthewc 50 flags = MOUSE_FLAG_DOWN;
504     /* fall through */
505 matty 9
506     case ButtonRelease:
507 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
508 matty 9 if (button == 0)
509     break;
510    
511 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
512 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
513 matty 10 break;
514    
515     case MotionNotify:
516 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
517 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
518 matty 28 break;
519    
520 matthewc 194 case FocusIn:
521 matthewc 203 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
522     reset_modifier_keys(state);
523 astrand 76 if (grab_keyboard)
524     XGrabKeyboard(display, wnd, True,
525 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
526 matty 28 break;
527    
528 matthewc 194 case FocusOut:
529 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
530 astrand 76 XUngrabKeyboard(display, CurrentTime);
531 matty 28 break;
532 matty 31
533 matthewc 250 case EnterNotify:
534     /* we only register for this event when in fullscreen mode */
535     XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
536     break;
537    
538 matty 31 case Expose:
539     XCopyArea(display, backstore, wnd, gc,
540 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
541 astrand 64 xevent.xexpose.width,
542     xevent.xexpose.height,
543 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
544 matty 31 break;
545 astrand 119
546     case MappingNotify:
547     /* Refresh keyboard mapping if it has changed. This is important for
548     Xvnc, since it allocates keycodes dynamically */
549     if (xevent.xmapping.request == MappingKeyboard
550     || xevent.xmapping.request == MappingModifier)
551     XRefreshKeyboardMapping(&xevent.xmapping);
552 matthewc 203
553     if (xevent.xmapping.request == MappingModifier)
554     {
555 matthewc 204 XFreeModifiermap(mod_map);
556 matthewc 203 mod_map = XGetModifierMapping(display);
557     }
558 astrand 119 break;
559    
560 matty 9 }
561     }
562     }
563    
564 matty 25 void
565 matty 33 ui_select(int rdp_socket)
566     {
567 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
568 matty 33 fd_set rfds;
569    
570     FD_ZERO(&rfds);
571    
572     while (True)
573     {
574 matthewc 121 /* Process any events already waiting */
575 astrand 119 xwin_process_events();
576    
577 matty 33 FD_ZERO(&rfds);
578     FD_SET(rdp_socket, &rfds);
579 matthewc 121 FD_SET(x_socket, &rfds);
580 matty 33
581     switch (select(n, &rfds, NULL, NULL, NULL))
582     {
583     case -1:
584     error("select: %s\n", strerror(errno));
585    
586     case 0:
587     continue;
588     }
589    
590     if (FD_ISSET(rdp_socket, &rfds))
591     return;
592     }
593     }
594    
595     void
596 matty 25 ui_move_pointer(int x, int y)
597 matty 9 {
598 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
599 matty 9 }
600    
601 matty 25 HBITMAP
602 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
603 matty 6 {
604     XImage *image;
605 matty 9 Pixmap bitmap;
606 matty 28 uint8 *tdata;
607 matty 29
608 n-ki 185 tdata = translate_image(width, height, data);
609 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
610 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
611     (char *) tdata, width, height, 8, 0);
612 matty 6
613 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
614 matty 9
615     XFree(image);
616 n-ki 185 xfree(tdata);
617 matty 24 return (HBITMAP) bitmap;
618 matty 6 }
619    
620 matty 25 void
621 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
622 matty 6 {
623 matty 10 XImage *image;
624 matty 29 uint8 *tdata;
625 matty 10
626 n-ki 185 tdata = translate_image(width, height, data);
627 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
628     (char *) tdata, width, height, 8, 0);
629 matty 28
630 matty 31 if (ownbackstore)
631     {
632     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
633     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
634     }
635     else
636     {
637     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
638     }
639 matty 29
640 matty 24 XFree(image);
641 n-ki 185 xfree(tdata);
642 matty 6 }
643    
644 matty 25 void
645     ui_destroy_bitmap(HBITMAP bmp)
646 matty 6 {
647 astrand 64 XFreePixmap(display, (Pixmap) bmp);
648 matty 10 }
649    
650 matty 25 HGLYPH
651 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
652 matty 10 {
653 matty 9 XImage *image;
654     Pixmap bitmap;
655     int scanline;
656     GC gc;
657 matty 6
658 matty 9 scanline = (width + 7) / 8;
659 matty 6
660 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
661     gc = XCreateGC(display, bitmap, 0, NULL);
662 matty 9
663 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
664 astrand 73 width, height, 8, scanline);
665 matty 23 image->byte_order = MSBFirst;
666     image->bitmap_bit_order = MSBFirst;
667     XInitImage(image);
668    
669 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
670 matty 29
671 matty 9 XFree(image);
672 matty 10 XFreeGC(display, gc);
673 astrand 64 return (HGLYPH) bitmap;
674 matty 6 }
675 matty 7
676 matty 25 void
677     ui_destroy_glyph(HGLYPH glyph)
678 matty 7 {
679 astrand 64 XFreePixmap(display, (Pixmap) glyph);
680 matty 9 }
681    
682 matty 29 HCURSOR
683 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
684     uint8 * andmask, uint8 * xormask)
685 matty 9 {
686 matty 29 HGLYPH maskglyph, cursorglyph;
687     XColor bg, fg;
688     Cursor xcursor;
689     uint8 *cursor, *pcursor;
690     uint8 *mask, *pmask;
691     uint8 nextbit;
692     int scanline, offset;
693     int i, j;
694    
695     scanline = (width + 7) / 8;
696     offset = scanline * height;
697    
698     cursor = xmalloc(offset);
699     memset(cursor, 0, offset);
700    
701     mask = xmalloc(offset);
702     memset(mask, 0, offset);
703    
704     /* approximate AND and XOR masks with a monochrome X pointer */
705     for (i = 0; i < height; i++)
706 matty 7 {
707 matty 29 offset -= scanline;
708     pcursor = &cursor[offset];
709     pmask = &mask[offset];
710    
711     for (j = 0; j < scanline; j++)
712 matty 28 {
713 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
714     {
715     if (xormask[0] || xormask[1] || xormask[2])
716     {
717     *pcursor |= (~(*andmask) & nextbit);
718     *pmask |= nextbit;
719     }
720     else
721     {
722     *pcursor |= ((*andmask) & nextbit);
723     *pmask |= (~(*andmask) & nextbit);
724     }
725    
726     xormask += 3;
727     }
728    
729     andmask++;
730     pcursor++;
731     pmask++;
732 matty 28 }
733 matty 7 }
734 matty 29
735     fg.red = fg.blue = fg.green = 0xffff;
736     bg.red = bg.blue = bg.green = 0x0000;
737     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
738    
739     cursorglyph = ui_create_glyph(width, height, cursor);
740     maskglyph = ui_create_glyph(width, height, mask);
741    
742 astrand 66 xcursor =
743     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
744     (Pixmap) maskglyph, &fg, &bg, x, y);
745 astrand 64
746 matty 29 ui_destroy_glyph(maskglyph);
747     ui_destroy_glyph(cursorglyph);
748     xfree(mask);
749     xfree(cursor);
750 astrand 64 return (HCURSOR) xcursor;
751 matty 29 }
752    
753     void
754     ui_set_cursor(HCURSOR cursor)
755     {
756 matthewc 188 current_cursor = (Cursor) cursor;
757     XDefineCursor(display, wnd, current_cursor);
758 matty 29 }
759    
760     void
761     ui_destroy_cursor(HCURSOR cursor)
762     {
763 astrand 64 XFreeCursor(display, (Cursor) cursor);
764 matty 29 }
765    
766     #define MAKE_XCOLOR(xc,c) \
767     (xc)->red = ((c)->red << 8) | (c)->red; \
768     (xc)->green = ((c)->green << 8) | (c)->green; \
769     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
770     (xc)->flags = DoRed | DoGreen | DoBlue;
771    
772     HCOLOURMAP
773 astrand 64 ui_create_colourmap(COLOURMAP * colours)
774 matty 29 {
775     COLOURENTRY *entry;
776     int i, ncolours = colours->ncolours;
777 n-ki 185 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
778     XColor xentry;
779     XColor xc_cache[256];
780     uint32 colour;
781     int colLookup = 256;
782     for (i = 0; i < ncolours; i++)
783 matty 28 {
784 n-ki 185 entry = &colours->colours[i];
785     MAKE_XCOLOR(&xentry, entry);
786 matty 29
787 n-ki 185 if (XAllocColor(display, xcolmap, &xentry) == 0)
788 matty 28 {
789 n-ki 185 /* Allocation failed, find closest match. */
790     int j = 256;
791     int nMinDist = 3 * 256 * 256;
792     long nDist = nMinDist;
793 matty 7
794 n-ki 185 /* only get the colors once */
795 astrand 196 while (colLookup--)
796     {
797 n-ki 185 xc_cache[colLookup].pixel = colLookup;
798 astrand 196 xc_cache[colLookup].red = xc_cache[colLookup].green =
799     xc_cache[colLookup].blue = 0;
800 n-ki 185 xc_cache[colLookup].flags = 0;
801 astrand 196 XQueryColor(display,
802     DefaultColormap(display, DefaultScreen(display)),
803     &xc_cache[colLookup]);
804 n-ki 185 }
805     colLookup = 0;
806 matty 28
807 n-ki 185 /* approximate the pixel */
808 astrand 196 while (j--)
809     {
810     if (xc_cache[j].flags)
811     {
812     nDist = ((long) (xc_cache[j].red >> 8) -
813     (long) (xentry.red >> 8)) *
814     ((long) (xc_cache[j].red >> 8) -
815     (long) (xentry.red >> 8)) +
816     ((long) (xc_cache[j].green >> 8) -
817     (long) (xentry.green >> 8)) *
818     ((long) (xc_cache[j].green >> 8) -
819     (long) (xentry.green >> 8)) +
820     ((long) (xc_cache[j].blue >> 8) -
821     (long) (xentry.blue >> 8)) *
822     ((long) (xc_cache[j].blue >> 8) -
823     (long) (xentry.blue >> 8));
824 n-ki 185 }
825 astrand 196 if (nDist < nMinDist)
826     {
827 n-ki 185 nMinDist = nDist;
828     xentry.pixel = j;
829     }
830     }
831     }
832     colour = xentry.pixel;
833 matty 29
834 n-ki 185 /* update our cache */
835 astrand 196 if (xentry.pixel < 256)
836     {
837 n-ki 185 xc_cache[xentry.pixel].red = xentry.red;
838     xc_cache[xentry.pixel].green = xentry.green;
839     xc_cache[xentry.pixel].blue = xentry.blue;
840 matty 29
841     }
842    
843 n-ki 185
844     /* byte swap here to make translate_image faster */
845     map[i] = translate_colour(colour);
846 matty 29 }
847 n-ki 185
848     return map;
849 matty 7 }
850    
851 matty 25 void
852     ui_destroy_colourmap(HCOLOURMAP map)
853 matty 7 {
854 n-ki 185 xfree(map);
855 matty 7 }
856    
857 matty 25 void
858     ui_set_colourmap(HCOLOURMAP map)
859 matty 7 {
860 n-ki 185 colmap = map;
861 matty 7 }
862    
863 matty 25 void
864     ui_set_clip(int x, int y, int cx, int cy)
865 matty 7 {
866 matty 9 XRectangle rect;
867 matty 7
868 matty 9 rect.x = x;
869     rect.y = y;
870     rect.width = cx;
871     rect.height = cy;
872 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
873 matty 9 }
874 matty 7
875 matty 25 void
876 matthewc 192 ui_reset_clip(void)
877 matty 9 {
878     XRectangle rect;
879    
880     rect.x = 0;
881     rect.y = 0;
882 matty 10 rect.width = width;
883     rect.height = height;
884     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
885 matty 7 }
886    
887 matty 25 void
888 matthewc 192 ui_bell(void)
889 matty 10 {
890     XBell(display, 0);
891     }
892    
893 matty 25 void
894     ui_destblt(uint8 opcode,
895     /* dest */ int x, int y, int cx, int cy)
896 matty 9 {
897 matty 29 SET_FUNCTION(opcode);
898 matty 31 FILL_RECTANGLE(x, y, cx, cy);
899 matty 29 RESET_FUNCTION(opcode);
900 matty 9 }
901    
902 matty 25 void
903     ui_patblt(uint8 opcode,
904     /* dest */ int x, int y, int cx, int cy,
905 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
906 matty 9 {
907     Pixmap fill;
908 jsorg71 59 uint8 i, ipattern[8];
909 matty 9
910 matty 29 SET_FUNCTION(opcode);
911 matty 9
912     switch (brush->style)
913     {
914 matty 24 case 0: /* Solid */
915 matty 29 SET_FOREGROUND(fgcolour);
916 matty 31 FILL_RECTANGLE(x, y, cx, cy);
917 matty 9 break;
918    
919 matty 24 case 3: /* Pattern */
920 jsorg71 59 for (i = 0; i != 8; i++)
921     ipattern[7 - i] = brush->pattern[i];
922     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
923 matty 9
924 matty 29 SET_FOREGROUND(bgcolour);
925     SET_BACKGROUND(fgcolour);
926     XSetFillStyle(display, gc, FillOpaqueStippled);
927     XSetStipple(display, gc, fill);
928 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
929 matty 9
930 matty 31 FILL_RECTANGLE(x, y, cx, cy);
931 matty 9
932 matty 29 XSetFillStyle(display, gc, FillSolid);
933 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
934 astrand 64 ui_destroy_glyph((HGLYPH) fill);
935 matty 9 break;
936    
937     default:
938 matty 30 unimpl("brush %d\n", brush->style);
939 matty 9 }
940 matty 29
941     RESET_FUNCTION(opcode);
942 matty 9 }
943    
944 matty 25 void
945     ui_screenblt(uint8 opcode,
946     /* dest */ int x, int y, int cx, int cy,
947     /* src */ int srcx, int srcy)
948 matty 9 {
949 matty 29 SET_FUNCTION(opcode);
950 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
951 matty 31 if (ownbackstore)
952 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
953 matty 29 RESET_FUNCTION(opcode);
954 matty 9 }
955    
956 matty 25 void
957     ui_memblt(uint8 opcode,
958     /* dest */ int x, int y, int cx, int cy,
959     /* src */ HBITMAP src, int srcx, int srcy)
960 matty 9 {
961 matty 29 SET_FUNCTION(opcode);
962 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
963 matty 31 if (ownbackstore)
964 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
965 matty 29 RESET_FUNCTION(opcode);
966 matty 9 }
967    
968 matty 25 void
969     ui_triblt(uint8 opcode,
970     /* dest */ int x, int y, int cx, int cy,
971     /* src */ HBITMAP src, int srcx, int srcy,
972 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
973 matty 9 {
974     /* This is potentially difficult to do in general. Until someone
975 matty 10 comes up with a more efficient way of doing it I am using cases. */
976 matty 9
977     switch (opcode)
978     {
979 matty 24 case 0x69: /* PDSxxn */
980 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
981 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
982 matty 16 break;
983    
984 matty 24 case 0xb8: /* PSDPxax */
985 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
986 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
987 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
988 matty 9 break;
989    
990 matty 29 case 0xc0: /* PSa */
991 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
992 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
993 matty 28 break;
994    
995 matty 9 default:
996 matty 30 unimpl("triblt 0x%x\n", opcode);
997 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
998 matty 9 }
999     }
1000    
1001 matty 25 void
1002     ui_line(uint8 opcode,
1003     /* dest */ int startx, int starty, int endx, int endy,
1004 astrand 64 /* pen */ PEN * pen)
1005 matty 9 {
1006 matty 29 SET_FUNCTION(opcode);
1007     SET_FOREGROUND(pen->colour);
1008 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1009 matty 31 if (ownbackstore)
1010     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1011 matty 29 RESET_FUNCTION(opcode);
1012 matty 9 }
1013    
1014 matty 25 void
1015     ui_rect(
1016     /* dest */ int x, int y, int cx, int cy,
1017     /* brush */ int colour)
1018 matty 9 {
1019 matty 29 SET_FOREGROUND(colour);
1020 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1021 matty 9 }
1022    
1023 matty 25 void
1024     ui_draw_glyph(int mixmode,
1025     /* dest */ int x, int y, int cx, int cy,
1026 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1027     int bgcolour, int fgcolour)
1028 matty 9 {
1029 matty 29 SET_FOREGROUND(fgcolour);
1030     SET_BACKGROUND(bgcolour);
1031 matty 9
1032 astrand 66 XSetFillStyle(display, gc,
1033 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1034 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1035 matty 29 XSetTSOrigin(display, gc, x, y);
1036 matty 9
1037 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1038 matty 9
1039 matty 29 XSetFillStyle(display, gc, FillSolid);
1040 matty 9 }
1041    
1042 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1043     {\
1044     glyph = cache_get_font (font, ttext[idx]);\
1045     if (!(flags & TEXT2_IMPLICIT_X))\
1046     {\
1047     xyoffset = ttext[++idx];\
1048     if ((xyoffset & 0x80))\
1049     {\
1050     if (flags & TEXT2_VERTICAL) \
1051 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1052 mmihalik 49 else\
1053 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1054     idx += 2;\
1055 mmihalik 49 }\
1056     else\
1057     {\
1058     if (flags & TEXT2_VERTICAL) \
1059     y += xyoffset;\
1060     else\
1061     x += xyoffset;\
1062     }\
1063     }\
1064     if (glyph != NULL)\
1065     {\
1066     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1067     y + (short) glyph->baseline,\
1068     glyph->width, glyph->height,\
1069     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1070     if (flags & TEXT2_IMPLICIT_X)\
1071     x += glyph->width;\
1072     }\
1073     }
1074    
1075 matty 25 void
1076     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1077 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1078     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1079 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1080 matty 9 {
1081 matty 10 FONTGLYPH *glyph;
1082 mmihalik 49 int i, j, xyoffset;
1083     DATABLOB *entry;
1084 matty 9
1085 matty 29 SET_FOREGROUND(bgcolour);
1086 matty 28
1087 matty 9 if (boxcx > 1)
1088 matty 31 {
1089     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1090     }
1091 matty 17 else if (mixmode == MIX_OPAQUE)
1092 matty 31 {
1093     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1094     }
1095 matty 9
1096     /* Paint text, character by character */
1097 astrand 64 for (i = 0; i < length;)
1098     {
1099     switch (text[i])
1100     {
1101     case 0xff:
1102     if (i + 2 < length)
1103 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1104 astrand 64 else
1105     {
1106     error("this shouldn't be happening\n");
1107     break;
1108     }
1109     /* this will move pointer from start to first character after FF command */
1110     length -= i + 3;
1111     text = &(text[i + 3]);
1112     i = 0;
1113 mmihalik 49 break;
1114 matty 9
1115 astrand 64 case 0xfe:
1116     entry = cache_get_text(text[i + 1]);
1117     if (entry != NULL)
1118     {
1119     if ((((uint8 *) (entry->data))[1] ==
1120 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1121 astrand 64 {
1122     if (flags & TEXT2_VERTICAL)
1123     y += text[i + 2];
1124     else
1125     x += text[i + 2];
1126     }
1127     if (i + 2 < length)
1128     i += 3;
1129 mmihalik 49 else
1130 astrand 64 i += 2;
1131     length -= i;
1132     /* this will move pointer from start to first character after FE command */
1133     text = &(text[i]);
1134     i = 0;
1135     for (j = 0; j < entry->size; j++)
1136 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1137 matthewc 44 }
1138 astrand 64 break;
1139 matty 17
1140 astrand 64 default:
1141     DO_GLYPH(text, i);
1142     i++;
1143     break;
1144 matty 29 }
1145 mmihalik 49 }
1146 matty 28
1147 matty 9
1148     }
1149    
1150 matty 25 void
1151     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1152 matty 9 {
1153 matty 28 Pixmap pix;
1154 matty 9 XImage *image;
1155    
1156 matty 31 if (ownbackstore)
1157     {
1158 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1159 matty 31 }
1160     else
1161     {
1162     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1163     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1164 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1165 matty 31 XFreePixmap(display, pix);
1166     }
1167 matty 28
1168 astrand 64 offset *= bpp / 8;
1169 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1170 matty 28
1171     XDestroyImage(image);
1172 matty 9 }
1173    
1174 matty 25 void
1175     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1176 matty 9 {
1177     XImage *image;
1178 matty 10 uint8 *data;
1179 matty 9
1180 astrand 64 offset *= bpp / 8;
1181     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1182 matty 10 if (data == NULL)
1183     return;
1184 matty 29
1185 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1186 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1187 matty 29
1188 matty 31 if (ownbackstore)
1189     {
1190     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1191     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1192     }
1193     else
1194     {
1195     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1196     }
1197    
1198 matty 9 XFree(image);
1199     }

  ViewVC Help
Powered by ViewVC 1.1.26