/[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 116 - (hide annotations)
Wed Sep 11 11:11:27 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 27968 byte(s)
Inhibited keys are defined in keymap files; not hardcoded

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 102 static BOOL
251     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 matty 33 static void
521     xwin_process_events()
522 matty 9 {
523 n-ki 54 XEvent xevent;
524    
525 matthewc 38 KeySym keysym;
526 matthewc 50 uint16 button, flags;
527 matty 10 uint32 ev_time;
528 astrand 66 key_translation tr;
529     char *ksname = NULL;
530     char str[256];
531     Status status;
532 matty 9
533 jsorg71 100 /* Refresh keyboard mapping if it has changed. This is important for
534 astrand 66 Xvnc, since it allocates keycodes dynamically */
535     if (XCheckTypedEvent(display, MappingNotify, &xevent))
536     {
537     if (xevent.xmapping.request == MappingKeyboard
538     || xevent.xmapping.request == MappingModifier)
539     XRefreshKeyboardMapping(&xevent.xmapping);
540     }
541    
542 n-ki 54 while (XCheckMaskEvent(display, ~0, &xevent))
543 matty 9 {
544 astrand 70 if (enable_compose && (XFilterEvent(&xevent, None) == True))
545 astrand 66 {
546 astrand 84 DEBUG_KBD(("Filtering event\n"));
547 astrand 66 continue;
548     }
549    
550 matty 10 ev_time = time(NULL);
551 matthewc 50 flags = 0;
552 matty 10
553 n-ki 54 switch (xevent.type)
554 matty 9 {
555     case KeyPress:
556 astrand 66 if (IC != NULL)
557     /* Multi_key compatible version */
558     {
559     XmbLookupString(IC,
560     (XKeyPressedEvent *) &
561 astrand 82 xevent, str, sizeof(str), &keysym, &status);
562     if (!((status == XLookupKeySym) || (status == XLookupBoth)))
563 astrand 66 {
564 astrand 82 error("XmbLookupString failed with status 0x%x\n",
565     status);
566 astrand 66 break;
567     }
568     }
569     else
570     {
571     /* Plain old XLookupString */
572 astrand 84 DEBUG_KBD(("No input context, using XLookupString\n"));
573 astrand 66 XLookupString((XKeyEvent *) & xevent,
574 astrand 82 str, sizeof(str), &keysym, NULL);
575 astrand 66 }
576    
577 astrand 101 if (keysym == XK_Break) /* toggle full screen */
578 jsorg71 100 {
579 astrand 102 if (get_key_state(XK_Alt_L) || get_key_state(XK_Alt_R))
580     {
581     toggle_fullscreen();
582     break;
583     }
584 jsorg71 100 }
585 astrand 102
586 astrand 66 ksname = get_ksname(keysym);
587 astrand 84 DEBUG_KBD(("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
588 astrand 66
589     tr = xkeymap_translate_key(keysym,
590 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
591 astrand 69
592 astrand 66 if (tr.scancode == 0)
593 n-ki 52 break;
594    
595 astrand 115 ensure_remote_modifiers(ev_time, tr);
596    
597 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
598 astrand 66 break;
599     case KeyRelease:
600     XLookupString((XKeyEvent *) & xevent, str,
601     sizeof(str), &keysym, NULL);
602 n-ki 52
603 astrand 66 ksname = get_ksname(keysym);
604 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
605     ksname));
606 n-ki 52
607 astrand 66 tr = xkeymap_translate_key(keysym,
608 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
609 astrand 66
610     if (tr.scancode == 0)
611     break;
612    
613 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
614 matty 9 break;
615    
616     case ButtonPress:
617 matthewc 50 flags = MOUSE_FLAG_DOWN;
618     /* fall through */
619 matty 9
620     case ButtonRelease:
621 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
622 matty 9 if (button == 0)
623     break;
624    
625 matty 10 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
626 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
627 matty 10 break;
628    
629     case MotionNotify:
630     rdp_send_input(ev_time, RDP_INPUT_MOUSE,
631 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
632 matty 28 break;
633    
634 astrand 76 case FocusIn:
635     /* fall through */
636 matty 28 case EnterNotify:
637 astrand 76 if (grab_keyboard)
638     XGrabKeyboard(display, wnd, True,
639 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
640 matty 28 break;
641    
642 astrand 76 case FocusOut:
643 jsorg71 100 reset_keys();
644 astrand 76 /* fall through */
645 matty 28 case LeaveNotify:
646 astrand 76 if (grab_keyboard)
647     XUngrabKeyboard(display, CurrentTime);
648 matty 28 break;
649 matty 31
650     case Expose:
651     XCopyArea(display, backstore, wnd, gc,
652 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
653 astrand 64 xevent.xexpose.width,
654     xevent.xexpose.height,
655 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
656 matty 31 break;
657 matty 9 }
658     }
659     }
660    
661 matty 25 void
662 matty 33 ui_select(int rdp_socket)
663     {
664 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
665 matty 33 fd_set rfds;
666    
667     FD_ZERO(&rfds);
668    
669     while (True)
670     {
671     FD_ZERO(&rfds);
672     FD_SET(rdp_socket, &rfds);
673 matthewc 53 if (display != NULL)
674     {
675     FD_SET(x_socket, &rfds);
676     XFlush(display);
677     }
678 matty 33
679     switch (select(n, &rfds, NULL, NULL, NULL))
680     {
681     case -1:
682     error("select: %s\n", strerror(errno));
683    
684     case 0:
685     continue;
686     }
687    
688     if (FD_ISSET(x_socket, &rfds))
689     xwin_process_events();
690    
691     if (FD_ISSET(rdp_socket, &rfds))
692     return;
693     }
694     }
695    
696     void
697 matty 25 ui_move_pointer(int x, int y)
698 matty 9 {
699 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
700 matty 9 }
701    
702 matty 25 HBITMAP
703 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
704 matty 6 {
705     XImage *image;
706 matty 9 Pixmap bitmap;
707 matty 28 uint8 *tdata;
708 matty 29
709 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
710 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
711 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
712     (char *) tdata, width, height, 8, 0);
713 matty 6
714 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
715 matty 9
716     XFree(image);
717 matty 29 if (!owncolmap)
718 matty 28 xfree(tdata);
719 matty 24 return (HBITMAP) bitmap;
720 matty 6 }
721    
722 matty 25 void
723 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
724 matty 6 {
725 matty 10 XImage *image;
726 matty 29 uint8 *tdata;
727 matty 10
728 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
729 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
730     (char *) tdata, width, height, 8, 0);
731 matty 28
732 matty 31 if (ownbackstore)
733     {
734     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
735     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
736     }
737     else
738     {
739     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
740     }
741 matty 29
742 matty 24 XFree(image);
743 matty 29 if (!owncolmap)
744 matty 28 xfree(tdata);
745 matty 6 }
746    
747 matty 25 void
748     ui_destroy_bitmap(HBITMAP bmp)
749 matty 6 {
750 astrand 64 XFreePixmap(display, (Pixmap) bmp);
751 matty 10 }
752    
753 matty 25 HGLYPH
754 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
755 matty 10 {
756 matty 9 XImage *image;
757     Pixmap bitmap;
758     int scanline;
759     GC gc;
760 matty 6
761 matty 9 scanline = (width + 7) / 8;
762 matty 6
763 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
764     gc = XCreateGC(display, bitmap, 0, NULL);
765 matty 9
766 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
767 astrand 73 width, height, 8, scanline);
768 matty 23 image->byte_order = MSBFirst;
769     image->bitmap_bit_order = MSBFirst;
770     XInitImage(image);
771    
772 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
773 matty 29
774 matty 9 XFree(image);
775 matty 10 XFreeGC(display, gc);
776 astrand 64 return (HGLYPH) bitmap;
777 matty 6 }
778 matty 7
779 matty 25 void
780     ui_destroy_glyph(HGLYPH glyph)
781 matty 7 {
782 astrand 64 XFreePixmap(display, (Pixmap) glyph);
783 matty 9 }
784    
785 matty 29 HCURSOR
786 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
787     uint8 * andmask, uint8 * xormask)
788 matty 9 {
789 matty 29 HGLYPH maskglyph, cursorglyph;
790     XColor bg, fg;
791     Cursor xcursor;
792     uint8 *cursor, *pcursor;
793     uint8 *mask, *pmask;
794     uint8 nextbit;
795     int scanline, offset;
796     int i, j;
797    
798     scanline = (width + 7) / 8;
799     offset = scanline * height;
800    
801     cursor = xmalloc(offset);
802     memset(cursor, 0, offset);
803    
804     mask = xmalloc(offset);
805     memset(mask, 0, offset);
806    
807     /* approximate AND and XOR masks with a monochrome X pointer */
808     for (i = 0; i < height; i++)
809 matty 7 {
810 matty 29 offset -= scanline;
811     pcursor = &cursor[offset];
812     pmask = &mask[offset];
813    
814     for (j = 0; j < scanline; j++)
815 matty 28 {
816 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
817     {
818     if (xormask[0] || xormask[1] || xormask[2])
819     {
820     *pcursor |= (~(*andmask) & nextbit);
821     *pmask |= nextbit;
822     }
823     else
824     {
825     *pcursor |= ((*andmask) & nextbit);
826     *pmask |= (~(*andmask) & nextbit);
827     }
828    
829     xormask += 3;
830     }
831    
832     andmask++;
833     pcursor++;
834     pmask++;
835 matty 28 }
836 matty 7 }
837 matty 29
838     fg.red = fg.blue = fg.green = 0xffff;
839     bg.red = bg.blue = bg.green = 0x0000;
840     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
841    
842     cursorglyph = ui_create_glyph(width, height, cursor);
843     maskglyph = ui_create_glyph(width, height, mask);
844    
845 astrand 66 xcursor =
846     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
847     (Pixmap) maskglyph, &fg, &bg, x, y);
848 astrand 64
849 matty 29 ui_destroy_glyph(maskglyph);
850     ui_destroy_glyph(cursorglyph);
851     xfree(mask);
852     xfree(cursor);
853 astrand 64 return (HCURSOR) xcursor;
854 matty 29 }
855    
856     void
857     ui_set_cursor(HCURSOR cursor)
858     {
859 astrand 64 XDefineCursor(display, wnd, (Cursor) cursor);
860 matty 29 }
861    
862     void
863     ui_destroy_cursor(HCURSOR cursor)
864     {
865 astrand 64 XFreeCursor(display, (Cursor) cursor);
866 matty 29 }
867    
868     #define MAKE_XCOLOR(xc,c) \
869     (xc)->red = ((c)->red << 8) | (c)->red; \
870     (xc)->green = ((c)->green << 8) | (c)->green; \
871     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
872     (xc)->flags = DoRed | DoGreen | DoBlue;
873    
874     HCOLOURMAP
875 astrand 64 ui_create_colourmap(COLOURMAP * colours)
876 matty 29 {
877     COLOURENTRY *entry;
878     int i, ncolours = colours->ncolours;
879    
880     if (owncolmap)
881 matty 28 {
882     XColor *xcolours, *xentry;
883     Colormap map;
884 matty 29
885 matty 28 xcolours = xmalloc(sizeof(XColor) * ncolours);
886     for (i = 0; i < ncolours; i++)
887     {
888     entry = &colours->colours[i];
889     xentry = &xcolours[i];
890     xentry->pixel = i;
891 matty 29 MAKE_XCOLOR(xentry, entry);
892 matty 28 }
893 matty 7
894 matty 28 map = XCreateColormap(display, wnd, visual, AllocAll);
895     XStoreColors(display, map, xcolours, ncolours);
896    
897     xfree(xcolours);
898 astrand 64 return (HCOLOURMAP) map;
899 matty 28 }
900 matty 29 else
901     {
902     uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
903     XColor xentry;
904 matty 33 uint32 colour;
905 matty 29
906     for (i = 0; i < ncolours; i++)
907     {
908     entry = &colours->colours[i];
909     MAKE_XCOLOR(&xentry, entry);
910    
911     if (XAllocColor(display, xcolmap, &xentry) != 0)
912 matty 34 colour = xentry.pixel;
913 matty 29 else
914 matty 34 colour = white;
915 matty 33
916     /* byte swap here to make translate_image faster */
917     map[i] = translate_colour(colour);
918 matty 29 }
919    
920     return map;
921     }
922 matty 7 }
923    
924 matty 25 void
925     ui_destroy_colourmap(HCOLOURMAP map)
926 matty 7 {
927 matty 29 if (owncolmap)
928 astrand 64 XFreeColormap(display, (Colormap) map);
929 matty 29 else
930     xfree(map);
931 matty 7 }
932    
933 matty 25 void
934     ui_set_colourmap(HCOLOURMAP map)
935 matty 7 {
936 matty 29 if (owncolmap)
937 astrand 64 XSetWindowColormap(display, wnd, (Colormap) map);
938 matty 29 else
939 matty 28 colmap = map;
940 matty 7 }
941    
942 matty 25 void
943     ui_set_clip(int x, int y, int cx, int cy)
944 matty 7 {
945 matty 9 XRectangle rect;
946 matty 7
947 matty 9 rect.x = x;
948     rect.y = y;
949     rect.width = cx;
950     rect.height = cy;
951 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
952 matty 9 }
953 matty 7
954 matty 25 void
955     ui_reset_clip()
956 matty 9 {
957     XRectangle rect;
958    
959     rect.x = 0;
960     rect.y = 0;
961 matty 10 rect.width = width;
962     rect.height = height;
963     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
964 matty 7 }
965    
966 matty 25 void
967     ui_bell()
968 matty 10 {
969     XBell(display, 0);
970     }
971    
972 matty 25 void
973     ui_destblt(uint8 opcode,
974     /* dest */ int x, int y, int cx, int cy)
975 matty 9 {
976 matty 29 SET_FUNCTION(opcode);
977 matty 31 FILL_RECTANGLE(x, y, cx, cy);
978 matty 29 RESET_FUNCTION(opcode);
979 matty 9 }
980    
981 matty 25 void
982     ui_patblt(uint8 opcode,
983     /* dest */ int x, int y, int cx, int cy,
984 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
985 matty 9 {
986     Pixmap fill;
987 jsorg71 59 uint8 i, ipattern[8];
988 matty 9
989 matty 29 SET_FUNCTION(opcode);
990 matty 9
991     switch (brush->style)
992     {
993 matty 24 case 0: /* Solid */
994 matty 29 SET_FOREGROUND(fgcolour);
995 matty 31 FILL_RECTANGLE(x, y, cx, cy);
996 matty 9 break;
997    
998 matty 24 case 3: /* Pattern */
999 jsorg71 59 for (i = 0; i != 8; i++)
1000     ipattern[7 - i] = brush->pattern[i];
1001     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1002 matty 9
1003 matty 29 SET_FOREGROUND(bgcolour);
1004     SET_BACKGROUND(fgcolour);
1005     XSetFillStyle(display, gc, FillOpaqueStippled);
1006     XSetStipple(display, gc, fill);
1007 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1008 matty 9
1009 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1010 matty 9
1011 matty 29 XSetFillStyle(display, gc, FillSolid);
1012 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
1013 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1014 matty 9 break;
1015    
1016     default:
1017 matty 30 unimpl("brush %d\n", brush->style);
1018 matty 9 }
1019 matty 29
1020     RESET_FUNCTION(opcode);
1021 matty 9 }
1022    
1023 matty 25 void
1024     ui_screenblt(uint8 opcode,
1025     /* dest */ int x, int y, int cx, int cy,
1026     /* src */ int srcx, int srcy)
1027 matty 9 {
1028 matty 29 SET_FUNCTION(opcode);
1029 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1030 matty 31 if (ownbackstore)
1031 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1032 matty 29 RESET_FUNCTION(opcode);
1033 matty 9 }
1034    
1035 matty 25 void
1036     ui_memblt(uint8 opcode,
1037     /* dest */ int x, int y, int cx, int cy,
1038     /* src */ HBITMAP src, int srcx, int srcy)
1039 matty 9 {
1040 matty 29 SET_FUNCTION(opcode);
1041 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1042 matty 31 if (ownbackstore)
1043 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1044 matty 29 RESET_FUNCTION(opcode);
1045 matty 9 }
1046    
1047 matty 25 void
1048     ui_triblt(uint8 opcode,
1049     /* dest */ int x, int y, int cx, int cy,
1050     /* src */ HBITMAP src, int srcx, int srcy,
1051 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1052 matty 9 {
1053     /* This is potentially difficult to do in general. Until someone
1054 matty 10 comes up with a more efficient way of doing it I am using cases. */
1055 matty 9
1056     switch (opcode)
1057     {
1058 matty 24 case 0x69: /* PDSxxn */
1059 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1060 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1061 matty 16 break;
1062    
1063 matty 24 case 0xb8: /* PSDPxax */
1064 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1065 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1066 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1067 matty 9 break;
1068    
1069 matty 29 case 0xc0: /* PSa */
1070 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1071 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1072 matty 28 break;
1073    
1074 matty 9 default:
1075 matty 30 unimpl("triblt 0x%x\n", opcode);
1076 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1077 matty 9 }
1078     }
1079    
1080 matty 25 void
1081     ui_line(uint8 opcode,
1082     /* dest */ int startx, int starty, int endx, int endy,
1083 astrand 64 /* pen */ PEN * pen)
1084 matty 9 {
1085 matty 29 SET_FUNCTION(opcode);
1086     SET_FOREGROUND(pen->colour);
1087 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1088 matty 31 if (ownbackstore)
1089     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1090 matty 29 RESET_FUNCTION(opcode);
1091 matty 9 }
1092    
1093 matty 25 void
1094     ui_rect(
1095     /* dest */ int x, int y, int cx, int cy,
1096     /* brush */ int colour)
1097 matty 9 {
1098 matty 29 SET_FOREGROUND(colour);
1099 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1100 matty 9 }
1101    
1102 matty 25 void
1103     ui_draw_glyph(int mixmode,
1104     /* dest */ int x, int y, int cx, int cy,
1105 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1106     int bgcolour, int fgcolour)
1107 matty 9 {
1108 matty 29 SET_FOREGROUND(fgcolour);
1109     SET_BACKGROUND(bgcolour);
1110 matty 9
1111 astrand 66 XSetFillStyle(display, gc,
1112 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1113 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1114 matty 29 XSetTSOrigin(display, gc, x, y);
1115 matty 9
1116 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1117 matty 9
1118 matty 29 XSetFillStyle(display, gc, FillSolid);
1119 matty 9 }
1120    
1121 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1122     {\
1123     glyph = cache_get_font (font, ttext[idx]);\
1124     if (!(flags & TEXT2_IMPLICIT_X))\
1125     {\
1126     xyoffset = ttext[++idx];\
1127     if ((xyoffset & 0x80))\
1128     {\
1129     if (flags & TEXT2_VERTICAL) \
1130 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1131 mmihalik 49 else\
1132 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1133     idx += 2;\
1134 mmihalik 49 }\
1135     else\
1136     {\
1137     if (flags & TEXT2_VERTICAL) \
1138     y += xyoffset;\
1139     else\
1140     x += xyoffset;\
1141     }\
1142     }\
1143     if (glyph != NULL)\
1144     {\
1145     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1146     y + (short) glyph->baseline,\
1147     glyph->width, glyph->height,\
1148     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1149     if (flags & TEXT2_IMPLICIT_X)\
1150     x += glyph->width;\
1151     }\
1152     }
1153    
1154 matty 25 void
1155     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1156 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1157     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1158 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1159 matty 9 {
1160 matty 10 FONTGLYPH *glyph;
1161 mmihalik 49 int i, j, xyoffset;
1162     DATABLOB *entry;
1163 matty 9
1164 matty 29 SET_FOREGROUND(bgcolour);
1165 matty 28
1166 matty 9 if (boxcx > 1)
1167 matty 31 {
1168     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1169     }
1170 matty 17 else if (mixmode == MIX_OPAQUE)
1171 matty 31 {
1172     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1173     }
1174 matty 9
1175     /* Paint text, character by character */
1176 astrand 64 for (i = 0; i < length;)
1177     {
1178     switch (text[i])
1179     {
1180     case 0xff:
1181     if (i + 2 < length)
1182 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1183 astrand 64 else
1184     {
1185     error("this shouldn't be happening\n");
1186     break;
1187     }
1188     /* this will move pointer from start to first character after FF command */
1189     length -= i + 3;
1190     text = &(text[i + 3]);
1191     i = 0;
1192 mmihalik 49 break;
1193 matty 9
1194 astrand 64 case 0xfe:
1195     entry = cache_get_text(text[i + 1]);
1196     if (entry != NULL)
1197     {
1198     if ((((uint8 *) (entry->data))[1] ==
1199 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1200 astrand 64 {
1201     if (flags & TEXT2_VERTICAL)
1202     y += text[i + 2];
1203     else
1204     x += text[i + 2];
1205     }
1206     if (i + 2 < length)
1207     i += 3;
1208 mmihalik 49 else
1209 astrand 64 i += 2;
1210     length -= i;
1211     /* this will move pointer from start to first character after FE command */
1212     text = &(text[i]);
1213     i = 0;
1214     for (j = 0; j < entry->size; j++)
1215 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1216 matthewc 44 }
1217 astrand 64 break;
1218 matty 17
1219 astrand 64 default:
1220     DO_GLYPH(text, i);
1221     i++;
1222     break;
1223 matty 29 }
1224 mmihalik 49 }
1225 matty 28
1226 matty 9
1227     }
1228    
1229 matty 25 void
1230     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1231 matty 9 {
1232 matty 28 Pixmap pix;
1233 matty 9 XImage *image;
1234    
1235 matty 31 if (ownbackstore)
1236     {
1237 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1238 matty 31 }
1239     else
1240     {
1241     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1242     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1243 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1244 matty 31 XFreePixmap(display, pix);
1245     }
1246 matty 28
1247 astrand 64 offset *= bpp / 8;
1248 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1249 matty 28
1250     XDestroyImage(image);
1251 matty 9 }
1252    
1253 matty 25 void
1254     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1255 matty 9 {
1256     XImage *image;
1257 matty 10 uint8 *data;
1258 matty 9
1259 astrand 64 offset *= bpp / 8;
1260     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1261 matty 10 if (data == NULL)
1262     return;
1263 matty 29
1264 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1265 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1266 matty 29
1267 matty 31 if (ownbackstore)
1268     {
1269     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1270     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1271     }
1272     else
1273     {
1274     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1275     }
1276    
1277 matty 9 XFree(image);
1278     }

  ViewVC Help
Powered by ViewVC 1.1.26