/[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

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.7  
changed lines
  Added in v.64

  ViewVC Help
Powered by ViewVC 1.1.26