/[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 102 - (hide annotations)
Mon Aug 26 17:14:04 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 28170 byte(s)
Alt modifier for fullscreen toggle

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

  ViewVC Help
Powered by ViewVC 1.1.26