/[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 118 - (hide annotations)
Wed Sep 11 11:45:20 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 27911 byte(s)
Support for Windows keys (via Ctrl-Esc)

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

  ViewVC Help
Powered by ViewVC 1.1.26