/[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 103 - (hide annotations)
Thu Aug 29 14:18:24 2002 UTC (21 years, 8 months ago) by matthewc
File MIME type: text/plain
File size: 28102 byte(s)
Make sure width is a multiple of 4 (previous version in ui_create_window
was getting done too late, after connection).

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

  ViewVC Help
Powered by ViewVC 1.1.26