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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 119 - (hide annotations)
Thu Sep 12 09:38:31 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 28095 byte(s)
Fixes Excel scroll-of-death problem: earlier select-loop failed to call xwin_process_events
when the queue was non-zero but the X11 socket was empty.

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

  ViewVC Help
Powered by ViewVC 1.1.26