/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

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

revision 84 by astrand, Tue Jul 30 07:30:12 2002 UTC revision 1049 by astrand, Wed Mar 1 13:54:19 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2005
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
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26  #include <errno.h>  #include <errno.h>
27  #define XK_MISCELLANY  #include <strings.h>
 #include <X11/keysymdef.h>  
28  #include "rdesktop.h"  #include "rdesktop.h"
29  #include "scancodes.h"  #include "xproto.h"
30    
31  extern int width;  extern int g_width;
32  extern int height;  extern int g_height;
33  extern BOOL sendmotion;  extern int g_xpos;
34  extern BOOL fullscreen;  extern int g_ypos;
35  extern BOOL grab_keyboard;  extern int g_pos;
36    extern BOOL g_sendmotion;
37  Display *display = NULL;  extern BOOL g_fullscreen;
38  static int x_socket;  extern BOOL g_grab_keyboard;
39  static Window wnd;  extern BOOL g_hide_decorations;
40  static GC gc;  extern char g_title[];
41  static Visual *visual;  /* Color depth of the RDP session.
42  static int depth;     As of RDP 5.1, it may be 8, 15, 16 or 24. */
43  static int bpp;  extern int g_server_depth;
44    extern int g_win_button_size;
45    
46    Display *g_display;
47    Time g_last_gesturetime;
48    static int g_x_socket;
49    static Screen *g_screen;
50    Window g_wnd;
51    extern uint32 g_embed_wnd;
52    BOOL g_enable_compose = False;
53    BOOL g_Unobscured;              /* used for screenblt */
54    static GC g_gc = NULL;
55    static GC g_create_bitmap_gc = NULL;
56    static GC g_create_glyph_gc = NULL;
57    static Visual *g_visual;
58    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
59       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
60       as far as we're concerned. */
61    static int g_depth;
62    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
63       This may be larger than g_depth, in which case some of the bits would
64       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
65    static int g_bpp;
66    static XIM g_IM;
67    static XIC g_IC;
68    static XModifierKeymap *g_mod_map;
69    static Cursor g_current_cursor;
70    static HCURSOR g_null_cursor = NULL;
71    static Atom g_protocol_atom, g_kill_atom;
72    static BOOL g_focused;
73    static BOOL g_mouse_in_wnd;
74    /* Indicates that:
75       1) visual has 15, 16 or 24 depth and the same color channel masks
76          as its RDP equivalent (implies X server is LE),
77       2) host is LE
78       This will trigger an optimization whose real value is questionable.
79    */
80    static BOOL g_compatible_arch;
81    /* Indicates whether RDP's bitmaps and our XImages have the same
82       binary format. If so, we can avoid an expensive translation.
83       Note that this can be true when g_compatible_arch is false,
84       e.g.:
85      
86         RDP(LE) <-> host(BE) <-> X-Server(LE)
87        
88       ('host' is the machine running rdesktop; the host simply memcpy's
89        so its endianess doesn't matter)
90     */
91    static BOOL g_no_translate_image = False;
92    
93  /* endianness */  /* endianness */
94  static BOOL host_be;  static BOOL g_host_be;
95  static BOOL xserver_be;  static BOOL g_xserver_be;
96    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
97    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
98    
99  /* software backing store */  /* software backing store */
100  static BOOL ownbackstore;  extern BOOL g_ownbackstore;
101  static Pixmap backstore;  static Pixmap g_backstore = 0;
102    
103    /* Moving in single app mode */
104    static BOOL g_moving_wnd;
105    static int g_move_x_offset = 0;
106    static int g_move_y_offset = 0;
107    static BOOL g_using_full_workarea = False;
108    
109    #ifdef WITH_RDPSND
110    extern int g_dsp_fd;
111    extern BOOL g_dsp_busy;
112    extern BOOL g_rdpsnd;
113    #endif
114    
115    /* MWM decorations */
116    #define MWM_HINTS_DECORATIONS   (1L << 1)
117    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
118    typedef struct
119    {
120            unsigned long flags;
121            unsigned long functions;
122            unsigned long decorations;
123            long inputMode;
124            unsigned long status;
125    }
126    PropMotifWmHints;
127    
128    typedef struct
129    {
130            uint32 red;
131            uint32 green;
132            uint32 blue;
133    }
134    PixelColour;
135    
136    
137  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
138  { \  { \
139          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
140          if (ownbackstore) \          if (g_ownbackstore) \
141                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
142    }
143    
144    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
145    { \
146            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
147    }
148    
149    #define FILL_POLYGON(p,np)\
150    { \
151            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
152            if (g_ownbackstore) \
153                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
154    }
155    
156    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
157    { \
158            switch (m) \
159            { \
160                    case 0: /* Outline */ \
161                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
162                            if (g_ownbackstore) \
163                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
164                            break; \
165                    case 1: /* Filled */ \
166                            XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
167                            if (g_ownbackstore) \
168                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
169                            break; \
170            } \
171  }  }
172    
173  /* colour maps */  /* colour maps */
174  static BOOL owncolmap;  extern BOOL g_owncolmap;
175  static Colormap xcolmap;  static Colormap g_xcolmap;
176  static uint32 white;  static uint32 *g_colmap = NULL;
177  static uint32 *colmap;  
178  static XIM IM = NULL;  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
179  static XIC IC = NULL;  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
180    #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
 /* Compose support */  
 BOOL enable_compose = False;  
   
 #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  
 #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  
 #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  
181    
182  static int rop2_map[] = {  static int rop2_map[] = {
183          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 90  static int rop2_map[] = { Line 198  static int rop2_map[] = {
198          GXset                   /* 1 */          GXset                   /* 1 */
199  };  };
200    
201  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
202  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
203    
204  static void  static void
205  translate8(uint8 * data, uint8 * out, uint8 * end)  mwm_hide_decorations(void)
206  {  {
207          while (out < end)          PropMotifWmHints motif_hints;
208                  *(out++) = (uint8) colmap[*(data++)];          Atom hintsatom;
209    
210            /* setup the property */
211            motif_hints.flags = MWM_HINTS_DECORATIONS;
212            motif_hints.decorations = 0;
213    
214            /* get the atom for the property */
215            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
216            if (!hintsatom)
217            {
218                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
219                    return;
220            }
221    
222            XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
223                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
224    }
225    
226    #define SPLITCOLOUR15(colour, rv) \
227    { \
228            rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
229            rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
230            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
231    }
232    
233    #define SPLITCOLOUR16(colour, rv) \
234    { \
235            rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
236            rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
237            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
238    } \
239    
240    #define SPLITCOLOUR24(colour, rv) \
241    { \
242            rv.blue = (colour & 0xff0000) >> 16; \
243            rv.green = (colour & 0x00ff00) >> 8; \
244            rv.red = (colour & 0x0000ff); \
245    }
246    
247    #define MAKECOLOUR(pc) \
248            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
249                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
250                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
251    
252    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
253    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
254    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
255                            x = (x << 16) | (x >> 16); }
256    
257    /* The following macros output the same octet sequences
258       on both BE and LE hosts: */
259    
260    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
261    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
262    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
263    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
264    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
265    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
266    
267    static uint32
268    translate_colour(uint32 colour)
269    {
270            PixelColour pc;
271            switch (g_server_depth)
272            {
273                    case 15:
274                            SPLITCOLOUR15(colour, pc);
275                            break;
276                    case 16:
277                            SPLITCOLOUR16(colour, pc);
278                            break;
279                    case 24:
280                            SPLITCOLOUR24(colour, pc);
281                            break;
282                    default:
283                            /* Avoid warning */
284                            pc.red = 0;
285                            pc.green = 0;
286                            pc.blue = 0;
287                            break;
288            }
289            return MAKECOLOUR(pc);
290    }
291    
292    /* indent is confused by UNROLL8 */
293    /* *INDENT-OFF* */
294    
295    /* repeat and unroll, similar to bitmap.c */
296    /* potentialy any of the following translate */
297    /* functions can use repeat but just doing */
298    /* the most common ones */
299    
300    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
301    /* 2 byte output repeat */
302    #define REPEAT2(stm) \
303    { \
304            while (out <= end - 8 * 2) \
305                    UNROLL8(stm) \
306            while (out < end) \
307                    { stm } \
308    }
309    /* 3 byte output repeat */
310    #define REPEAT3(stm) \
311    { \
312            while (out <= end - 8 * 3) \
313                    UNROLL8(stm) \
314            while (out < end) \
315                    { stm } \
316  }  }
317    /* 4 byte output repeat */
318    #define REPEAT4(stm) \
319    { \
320            while (out <= end - 8 * 4) \
321                    UNROLL8(stm) \
322            while (out < end) \
323                    { stm } \
324    }
325    /* *INDENT-ON* */
326    
327  static void  static void
328  translate16(uint8 * data, uint16 * out, uint16 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
329  {  {
330          while (out < end)          while (out < end)
331                  *(out++) = (uint16) colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
332    }
333    
334    static void
335    translate8to16(const uint8 * data, uint8 * out, uint8 * end)
336    {
337            uint16 value;
338    
339            if (g_compatible_arch)
340            {
341                    /* *INDENT-OFF* */
342                    REPEAT2
343                    (
344                            *((uint16 *) out) = g_colmap[*(data++)];
345                            out += 2;
346                    )
347                    /* *INDENT-ON* */
348            }
349            else if (g_xserver_be)
350            {
351                    while (out < end)
352                    {
353                            value = (uint16) g_colmap[*(data++)];
354                            BOUT16(out, value);
355                    }
356            }
357            else
358            {
359                    while (out < end)
360                    {
361                            value = (uint16) g_colmap[*(data++)];
362                            LOUT16(out, value);
363                    }
364            }
365  }  }
366    
367  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
368  static void  static void
369  translate24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
370  {  {
371          uint32 value;          uint32 value;
372    
373          while (out < end)          if (g_compatible_arch)
374            {
375                    while (out < end)
376                    {
377                            value = g_colmap[*(data++)];
378                            BOUT24(out, value);
379                    }
380            }
381            else
382          {          {
383                  value = colmap[*(data++)];                  while (out < end)
384                  *(out++) = value;                  {
385                  *(out++) = value >> 8;                          value = g_colmap[*(data++)];
386                  *(out++) = value >> 16;                          LOUT24(out, value);
387                    }
388          }          }
389  }  }
390    
391  static void  static void
392  translate32(uint8 * data, uint32 * out, uint32 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
393  {  {
394          while (out < end)          uint32 value;
395                  *(out++) = colmap[*(data++)];  
396            if (g_compatible_arch)
397            {
398                    /* *INDENT-OFF* */
399                    REPEAT4
400                    (
401                            *((uint32 *) out) = g_colmap[*(data++)];
402                            out += 4;
403                    )
404                    /* *INDENT-ON* */
405            }
406            else if (g_xserver_be)
407            {
408                    while (out < end)
409                    {
410                            value = g_colmap[*(data++)];
411                            BOUT32(out, value);
412                    }
413            }
414            else
415            {
416                    while (out < end)
417                    {
418                            value = g_colmap[*(data++)];
419                            LOUT32(out, value);
420                    }
421            }
422  }  }
423    
424  static uint8 *  static void
425  translate_image(int width, int height, uint8 * data)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
426  {  {
427          int size = width * height * bpp / 8;          uint16 pixel;
428          uint8 *out = xmalloc(size);          uint16 value;
429          uint8 *end = out + size;          PixelColour pc;
430    
431          switch (bpp)          if (g_xserver_be)
432          {          {
433                  case 8:                  while (out < end)
434                          translate8(data, out, end);                  {
435                          break;                          pixel = *(data++);
436                            if (g_host_be)
437                  case 16:                          {
438                          translate16(data, (uint16 *) out, (uint16 *) end);                                  BSWAP16(pixel);
439                          break;                          }
440                            SPLITCOLOUR15(pixel, pc);
441                            value = MAKECOLOUR(pc);
442                            BOUT16(out, value);
443                    }
444            }
445            else
446            {
447                    while (out < end)
448                    {
449                            pixel = *(data++);
450                            if (g_host_be)
451                            {
452                                    BSWAP16(pixel);
453                            }
454                            SPLITCOLOUR15(pixel, pc);
455                            value = MAKECOLOUR(pc);
456                            LOUT16(out, value);
457                    }
458            }
459    }
460    
461                  case 24:  static void
462                          translate24(data, out, end);  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
463                          break;  {
464            uint32 value;
465            uint16 pixel;
466            PixelColour pc;
467    
468                  case 32:          if (g_compatible_arch)
469                          translate32(data, (uint32 *) out, (uint32 *) end);          {
470                          break;                  /* *INDENT-OFF* */
471                    REPEAT3
472                    (
473                            pixel = *(data++);
474                            SPLITCOLOUR15(pixel, pc);
475                            *(out++) = pc.blue;
476                            *(out++) = pc.green;
477                            *(out++) = pc.red;
478                    )
479                    /* *INDENT-ON* */
480            }
481            else if (g_xserver_be)
482            {
483                    while (out < end)
484                    {
485                            pixel = *(data++);
486                            if (g_host_be)
487                            {
488                                    BSWAP16(pixel);
489                            }
490                            SPLITCOLOUR15(pixel, pc);
491                            value = MAKECOLOUR(pc);
492                            BOUT24(out, value);
493                    }
494            }
495            else
496            {
497                    while (out < end)
498                    {
499                            pixel = *(data++);
500                            if (g_host_be)
501                            {
502                                    BSWAP16(pixel);
503                            }
504                            SPLITCOLOUR15(pixel, pc);
505                            value = MAKECOLOUR(pc);
506                            LOUT24(out, value);
507                    }
508          }          }
   
         return out;  
509  }  }
510    
511  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  static void
512  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  
                         x = (x << 16) | (x >> 16); }  
   
 static uint32  
 translate_colour(uint32 colour)  
513  {  {
514          switch (bpp)          uint16 pixel;
515            uint32 value;
516            PixelColour pc;
517    
518            if (g_compatible_arch)
519          {          {
520                  case 16:                  /* *INDENT-OFF* */
521                          if (host_be != xserver_be)                  REPEAT4
522                                  BSWAP16(colour);                  (
523                          break;                          pixel = *(data++);
524                            SPLITCOLOUR15(pixel, pc);
525                            *(out++) = pc.blue;
526                            *(out++) = pc.green;
527                            *(out++) = pc.red;
528                            *(out++) = 0;
529                    )
530                    /* *INDENT-ON* */
531            }
532            else if (g_xserver_be)
533            {
534                    while (out < end)
535                    {
536                            pixel = *(data++);
537                            if (g_host_be)
538                            {
539                                    BSWAP16(pixel);
540                            }
541                            SPLITCOLOUR15(pixel, pc);
542                            value = MAKECOLOUR(pc);
543                            BOUT32(out, value);
544                    }
545            }
546            else
547            {
548                    while (out < end)
549                    {
550                            pixel = *(data++);
551                            if (g_host_be)
552                            {
553                                    BSWAP16(pixel);
554                            }
555                            SPLITCOLOUR15(pixel, pc);
556                            value = MAKECOLOUR(pc);
557                            LOUT32(out, value);
558                    }
559            }
560    }
561    
562                  case 24:  static void
563                          if (xserver_be)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
564                                  BSWAP24(colour);  {
565                          break;          uint16 pixel;
566            uint16 value;
567            PixelColour pc;
568    
569                  case 32:          if (g_xserver_be)
570                          if (host_be != xserver_be)          {
571                                  BSWAP32(colour);                  if (g_host_be)
572                          break;                  {
573                            while (out < end)
574                            {
575                                    pixel = *(data++);
576                                    BSWAP16(pixel);
577                                    SPLITCOLOUR16(pixel, pc);
578                                    value = MAKECOLOUR(pc);
579                                    BOUT16(out, value);
580                            }
581                    }
582                    else
583                    {
584                            while (out < end)
585                            {
586                                    pixel = *(data++);
587                                    SPLITCOLOUR16(pixel, pc);
588                                    value = MAKECOLOUR(pc);
589                                    BOUT16(out, value);
590                            }
591                    }
592            }
593            else
594            {
595                    if (g_host_be)
596                    {
597                            while (out < end)
598                            {
599                                    pixel = *(data++);
600                                    BSWAP16(pixel);
601                                    SPLITCOLOUR16(pixel, pc);
602                                    value = MAKECOLOUR(pc);
603                                    LOUT16(out, value);
604                            }
605                    }
606                    else
607                    {
608                            while (out < end)
609                            {
610                                    pixel = *(data++);
611                                    SPLITCOLOUR16(pixel, pc);
612                                    value = MAKECOLOUR(pc);
613                                    LOUT16(out, value);
614                            }
615                    }
616          }          }
   
         return colour;  
617  }  }
618    
619  static unsigned long  static void
620  init_inputmethod(void)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
621  {  {
622          unsigned long filtered_events = 0;          uint32 value;
623            uint16 pixel;
624            PixelColour pc;
625    
626          IM = XOpenIM(display, NULL, NULL, NULL);          if (g_compatible_arch)
627          if (IM == NULL)          {
628                    /* *INDENT-OFF* */
629                    REPEAT3
630                    (
631                            pixel = *(data++);
632                            SPLITCOLOUR16(pixel, pc);
633                            *(out++) = pc.blue;
634                            *(out++) = pc.green;
635                            *(out++) = pc.red;
636                    )
637                    /* *INDENT-ON* */
638            }
639            else if (g_xserver_be)
640          {          {
641                  error("Failed to open input method\n");                  if (g_host_be)
642                    {
643                            while (out < end)
644                            {
645                                    pixel = *(data++);
646                                    BSWAP16(pixel);
647                                    SPLITCOLOUR16(pixel, pc);
648                                    value = MAKECOLOUR(pc);
649                                    BOUT24(out, value);
650                            }
651                    }
652                    else
653                    {
654                            while (out < end)
655                            {
656                                    pixel = *(data++);
657                                    SPLITCOLOUR16(pixel, pc);
658                                    value = MAKECOLOUR(pc);
659                                    BOUT24(out, value);
660                            }
661                    }
662          }          }
663            else
664            {
665                    if (g_host_be)
666                    {
667                            while (out < end)
668                            {
669                                    pixel = *(data++);
670                                    BSWAP16(pixel);
671                                    SPLITCOLOUR16(pixel, pc);
672                                    value = MAKECOLOUR(pc);
673                                    LOUT24(out, value);
674                            }
675                    }
676                    else
677                    {
678                            while (out < end)
679                            {
680                                    pixel = *(data++);
681                                    SPLITCOLOUR16(pixel, pc);
682                                    value = MAKECOLOUR(pc);
683                                    LOUT24(out, value);
684                            }
685                    }
686            }
687    }
688    
689    static void
690    translate16to32(const uint16 * data, uint8 * out, uint8 * end)
691    {
692            uint16 pixel;
693            uint32 value;
694            PixelColour pc;
695    
696          if (IM != NULL)          if (g_compatible_arch)
697            {
698                    /* *INDENT-OFF* */
699                    REPEAT4
700                    (
701                            pixel = *(data++);
702                            SPLITCOLOUR16(pixel, pc);
703                            *(out++) = pc.blue;
704                            *(out++) = pc.green;
705                            *(out++) = pc.red;
706                            *(out++) = 0;
707                    )
708                    /* *INDENT-ON* */
709            }
710            else if (g_xserver_be)
711          {          {
712                  /* Must be done after XCreateWindow */                  if (g_host_be)
713                  IC = XCreateIC(IM, XNInputStyle,                  {
714                                 (XIMPreeditNothing | XIMStatusNothing),                          while (out < end)
715                                 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);                          {
716                                    pixel = *(data++);
717                                    BSWAP16(pixel);
718                                    SPLITCOLOUR16(pixel, pc);
719                                    value = MAKECOLOUR(pc);
720                                    BOUT32(out, value);
721                            }
722                    }
723                    else
724                    {
725                            while (out < end)
726                            {
727                                    pixel = *(data++);
728                                    SPLITCOLOUR16(pixel, pc);
729                                    value = MAKECOLOUR(pc);
730                                    BOUT32(out, value);
731                            }
732                    }
733            }
734            else
735            {
736                    if (g_host_be)
737                    {
738                            while (out < end)
739                            {
740                                    pixel = *(data++);
741                                    BSWAP16(pixel);
742                                    SPLITCOLOUR16(pixel, pc);
743                                    value = MAKECOLOUR(pc);
744                                    LOUT32(out, value);
745                            }
746                    }
747                    else
748                    {
749                            while (out < end)
750                            {
751                                    pixel = *(data++);
752                                    SPLITCOLOUR16(pixel, pc);
753                                    value = MAKECOLOUR(pc);
754                                    LOUT32(out, value);
755                            }
756                    }
757            }
758    }
759    
760    static void
761    translate24to16(const uint8 * data, uint8 * out, uint8 * end)
762    {
763            uint32 pixel = 0;
764            uint16 value;
765            PixelColour pc;
766    
767                  if (IC == NULL)          while (out < end)
768            {
769                    pixel = *(data++) << 16;
770                    pixel |= *(data++) << 8;
771                    pixel |= *(data++);
772                    SPLITCOLOUR24(pixel, pc);
773                    value = MAKECOLOUR(pc);
774                    if (g_xserver_be)
775                  {                  {
776                          error("Failed to create input context\n");                          BOUT16(out, value);
777                          XCloseIM(IM);                  }
778                          IM = NULL;                  else
779                    {
780                            LOUT16(out, value);
781                  }                  }
782          }          }
783    }
784    
785    static void
786    translate24to24(const uint8 * data, uint8 * out, uint8 * end)
787    {
788            uint32 pixel;
789            uint32 value;
790            PixelColour pc;
791    
792          /* For correct Multi_key/Compose processing, I guess.          if (g_xserver_be)
793             It seems to work alright anyway, though. */          {
794          if (IC != NULL)                  while (out < end)
795                    {
796                            pixel = *(data++) << 16;
797                            pixel |= *(data++) << 8;
798                            pixel |= *(data++);
799                            SPLITCOLOUR24(pixel, pc);
800                            value = MAKECOLOUR(pc);
801                            BOUT24(out, value);
802                    }
803            }
804            else
805          {          {
806                  if (XGetICValues(IC, XNFilterEvents, &filtered_events, NULL) != NULL)                  while (out < end)
807                  {                  {
808                          error("Failed to obtain XNFilterEvents value from IC\n");                          pixel = *(data++) << 16;
809                          filtered_events = 0;                          pixel |= *(data++) << 8;
810                            pixel |= *(data++);
811                            SPLITCOLOUR24(pixel, pc);
812                            value = MAKECOLOUR(pc);
813                            LOUT24(out, value);
814                  }                  }
815          }          }
         return filtered_events;  
816  }  }
817    
818  static void  static void
819  close_inputmethod(void)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
820  {  {
821          if (IC != NULL)          uint32 pixel;
822            uint32 value;
823            PixelColour pc;
824    
825            if (g_compatible_arch)
826            {
827                    /* *INDENT-OFF* */
828    #ifdef NEED_ALIGN
829                    REPEAT4
830                    (
831                            *(out++) = *(data++);
832                            *(out++) = *(data++);
833                            *(out++) = *(data++);
834                            *(out++) = 0;
835                    )
836    #else
837                    REPEAT4
838                    (
839                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
840                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
841                     out += 4;
842                     data += 3;
843                    )
844    #endif
845                    /* *INDENT-ON* */
846            }
847            else if (g_xserver_be)
848            {
849                    while (out < end)
850                    {
851                            pixel = *(data++) << 16;
852                            pixel |= *(data++) << 8;
853                            pixel |= *(data++);
854                            SPLITCOLOUR24(pixel, pc);
855                            value = MAKECOLOUR(pc);
856                            BOUT32(out, value);
857                    }
858            }
859            else
860          {          {
861                  XDestroyIC(IC);                  while (out < end)
                 if (IM != NULL)  
862                  {                  {
863                          XCloseIM(IM);                          pixel = *(data++) << 16;
864                          IM = NULL;                          pixel |= *(data++) << 8;
865                            pixel |= *(data++);
866                            SPLITCOLOUR24(pixel, pc);
867                            value = MAKECOLOUR(pc);
868                            LOUT32(out, value);
869                  }                  }
870          }          }
871  }  }
872    
873  BOOL  static uint8 *
874  ui_init()  translate_image(int width, int height, uint8 * data)
875  {  {
876          Screen *screen;          int size;
877          display = XOpenDisplay(NULL);          uint8 *out;
878          if (display == NULL)          uint8 *end;
879    
880            /*
881               If RDP depth and X Visual depths match,
882               and arch(endian) matches, no need to translate:
883               just return data.
884               Note: select_visual should've already ensured g_no_translate
885               is only set for compatible depths, but the RDP depth might've
886               changed during connection negotiations.
887             */
888            if (g_no_translate_image)
889            {
890                    if ((g_depth == 15 && g_server_depth == 15) ||
891                        (g_depth == 16 && g_server_depth == 16) ||
892                        (g_depth == 24 && g_server_depth == 24))
893                            return data;
894            }
895    
896            size = width * height * (g_bpp / 8);
897            out = (uint8 *) xmalloc(size);
898            end = out + size;
899    
900            switch (g_server_depth)
901          {          {
902                  error("Failed to open display\n");                  case 24:
903                            switch (g_bpp)
904                            {
905                                    case 32:
906                                            translate24to32(data, out, end);
907                                            break;
908                                    case 24:
909                                            translate24to24(data, out, end);
910                                            break;
911                                    case 16:
912                                            translate24to16(data, out, end);
913                                            break;
914                            }
915                            break;
916                    case 16:
917                            switch (g_bpp)
918                            {
919                                    case 32:
920                                            translate16to32((uint16 *) data, out, end);
921                                            break;
922                                    case 24:
923                                            translate16to24((uint16 *) data, out, end);
924                                            break;
925                                    case 16:
926                                            translate16to16((uint16 *) data, out, end);
927                                            break;
928                            }
929                            break;
930                    case 15:
931                            switch (g_bpp)
932                            {
933                                    case 32:
934                                            translate15to32((uint16 *) data, out, end);
935                                            break;
936                                    case 24:
937                                            translate15to24((uint16 *) data, out, end);
938                                            break;
939                                    case 16:
940                                            translate15to16((uint16 *) data, out, end);
941                                            break;
942                            }
943                            break;
944                    case 8:
945                            switch (g_bpp)
946                            {
947                                    case 8:
948                                            translate8to8(data, out, end);
949                                            break;
950                                    case 16:
951                                            translate8to16(data, out, end);
952                                            break;
953                                    case 24:
954                                            translate8to24(data, out, end);
955                                            break;
956                                    case 32:
957                                            translate8to32(data, out, end);
958                                            break;
959                            }
960                            break;
961            }
962            return out;
963    }
964    
965    BOOL
966    get_key_state(unsigned int state, uint32 keysym)
967    {
968            int modifierpos, key, keysymMask = 0;
969            int offset;
970    
971            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
972    
973            if (keycode == NoSymbol)
974                  return False;                  return False;
975    
976            for (modifierpos = 0; modifierpos < 8; modifierpos++)
977            {
978                    offset = g_mod_map->max_keypermod * modifierpos;
979    
980                    for (key = 0; key < g_mod_map->max_keypermod; key++)
981                    {
982                            if (g_mod_map->modifiermap[offset + key] == keycode)
983                                    keysymMask |= 1 << modifierpos;
984                    }
985          }          }
986          if (fullscreen)  
987            return (state & keysymMask) ? True : False;
988    }
989    
990    static void
991    calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
992    {
993            *shift_l = ffs(mask) - 1;
994            mask >>= *shift_l;
995            *shift_r = 8 - ffs(mask & ~(mask >> 1));
996    }
997    
998    /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
999       calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1000     */
1001    static unsigned
1002    calculate_mask_weight(uint32 mask)
1003    {
1004            unsigned weight = 0;
1005            do
1006          {          {
1007                  screen = DefaultScreenOfDisplay(display);                  weight += (mask & 1);
                 width = WidthOfScreen(screen);  
                 height = HeightOfScreen(screen);  
1008          }          }
1009          return True;          while (mask >>= 1);
1010            return weight;
1011  }  }
1012    
1013  BOOL  static BOOL
1014  ui_create_window(char *title)  select_visual()
1015  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
1016          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1017          Screen *screen;          int pixmap_formats_count, visuals_count;
1018          uint16 test;          XVisualInfo *vmatches = NULL;
1019            XVisualInfo template;
1020          int i;          int i;
1021            unsigned red_weight, blue_weight, green_weight;
1022    
1023            red_weight = blue_weight = green_weight = 0;
1024    
1025          x_socket = ConnectionNumber(display);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1026          screen = DefaultScreenOfDisplay(display);          if (pfm == NULL)
1027          visual = DefaultVisualOfScreen(screen);          {
1028          depth = DefaultDepthOfScreen(screen);                  error("Unable to get list of pixmap formats from display.\n");
1029                    XCloseDisplay(g_display);
1030                    return False;
1031            }
1032    
1033          pfm = XListPixmapFormats(display, &i);          /* Search for best TrueColor visual */
1034          if (pfm != NULL)          template.class = TrueColor;
1035            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1036            g_visual = NULL;
1037            g_no_translate_image = False;
1038            g_compatible_arch = False;
1039            if (vmatches != NULL)
1040          {          {
1041                  /* Use maximum bpp for this depth - this is generally                  for (i = 0; i < visuals_count; ++i)
                    desirable, e.g. 24 bits->32 bits. */  
                 while (i--)  
1042                  {                  {
1043                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))                          XVisualInfo *visual_info = &vmatches[i];
1044    
1045                            /* Try to find a no-translation visual that'll
1046                               allow us to use RDP bitmaps directly as ZPixmaps. */
1047                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1048                                                   /* R5G5B5 */
1049                                                   (visual_info->red_mask == 0x7c00) &&
1050                                                   (visual_info->green_mask == 0x3e0) &&
1051                                                   (visual_info->blue_mask == 0x1f)) ||
1052                                                  ((visual_info->depth == 16) &&
1053                                                   /* R5G6B5 */
1054                                                   (visual_info->red_mask == 0xf800) &&
1055                                                   (visual_info->green_mask == 0x7e0) &&
1056                                                   (visual_info->blue_mask == 0x1f)) ||
1057                                                  ((visual_info->depth == 24) &&
1058                                                   /* R8G8B8 */
1059                                                   (visual_info->red_mask == 0xff0000) &&
1060                                                   (visual_info->green_mask == 0xff00) &&
1061                                                   (visual_info->blue_mask == 0xff))))
1062                            {
1063                                    g_visual = visual_info->visual;
1064                                    g_depth = visual_info->depth;
1065                                    g_compatible_arch = !g_host_be;
1066                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1067                                    if (g_no_translate_image)
1068                                            /* We found the best visual */
1069                                            break;
1070                            }
1071                            else
1072                            {
1073                                    g_compatible_arch = False;
1074                            }
1075    
1076                            if (visual_info->depth > 24)
1077                            {
1078                                    /* Avoid 32-bit visuals and likes like the plague.
1079                                       They're either untested or proven to work bad
1080                                       (e.g. nvidia's Composite 32-bit visual).
1081                                       Most implementation offer a 24-bit visual anyway. */
1082                                    continue;
1083                            }
1084    
1085                            /* Only care for visuals, for whose BPPs (not depths!)
1086                               we have a translateXtoY function. */
1087                            BOOL can_translate_to_bpp = False;
1088                            int j;
1089                            for (j = 0; j < pixmap_formats_count; ++j)
1090                            {
1091                                    if (pfm[j].depth == visual_info->depth)
1092                                    {
1093                                            if ((pfm[j].bits_per_pixel == 16) ||
1094                                                (pfm[j].bits_per_pixel == 24) ||
1095                                                (pfm[j].bits_per_pixel == 32))
1096                                            {
1097                                                    can_translate_to_bpp = True;
1098                                            }
1099                                            break;
1100                                    }
1101                            }
1102    
1103                            /* Prefer formats which have the most colour depth.
1104                               We're being truly aristocratic here, minding each
1105                               weight on its own. */
1106                            if (can_translate_to_bpp)
1107                          {                          {
1108                                  bpp = pfm[i].bits_per_pixel;                                  unsigned vis_red_weight =
1109                                            calculate_mask_weight(visual_info->red_mask);
1110                                    unsigned vis_green_weight =
1111                                            calculate_mask_weight(visual_info->green_mask);
1112                                    unsigned vis_blue_weight =
1113                                            calculate_mask_weight(visual_info->blue_mask);
1114                                    if ((vis_red_weight >= red_weight)
1115                                        && (vis_green_weight >= green_weight)
1116                                        && (vis_blue_weight >= blue_weight))
1117                                    {
1118                                            red_weight = vis_red_weight;
1119                                            green_weight = vis_green_weight;
1120                                            blue_weight = vis_blue_weight;
1121                                            g_visual = visual_info->visual;
1122                                            g_depth = visual_info->depth;
1123                                    }
1124                          }                          }
1125                  }                  }
1126                  XFree(pfm);                  XFree(vmatches);
1127          }          }
1128    
1129          if (bpp < 8)          if (g_visual != NULL)
1130          {          {
1131                  error("Less than 8 bpp not currently supported.\n");                  g_owncolmap = False;
1132                  XCloseDisplay(display);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1133                    calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1134                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1135            }
1136            else
1137            {
1138                    template.class = PseudoColor;
1139                    template.depth = 8;
1140                    template.colormap_size = 256;
1141                    vmatches =
1142                            XGetVisualInfo(g_display,
1143                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1144                                           &template, &visuals_count);
1145                    if (vmatches == NULL)
1146                    {
1147                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1148                            XCloseDisplay(g_display);
1149                            XFree(pfm);
1150                            return False;
1151                    }
1152    
1153                    /* we use a colourmap, so the default visual should do */
1154                    g_owncolmap = True;
1155                    g_visual = vmatches[0].visual;
1156                    g_depth = vmatches[0].depth;
1157            }
1158    
1159            g_bpp = 0;
1160            for (i = 0; i < pixmap_formats_count; ++i)
1161            {
1162                    XPixmapFormatValues *pf = &pfm[i];
1163                    if (pf->depth == g_depth)
1164                    {
1165                            g_bpp = pf->bits_per_pixel;
1166    
1167                            if (g_no_translate_image)
1168                            {
1169                                    switch (g_server_depth)
1170                                    {
1171                                            case 15:
1172                                            case 16:
1173                                                    if (g_bpp != 16)
1174                                                            g_no_translate_image = False;
1175                                                    break;
1176                                            case 24:
1177                                                    /* Yes, this will force image translation
1178                                                       on most modern servers which use 32 bits
1179                                                       for R8G8B8. */
1180                                                    if (g_bpp != 24)
1181                                                            g_no_translate_image = False;
1182                                                    break;
1183                                            default:
1184                                                    g_no_translate_image = False;
1185                                                    break;
1186                                    }
1187                            }
1188    
1189                            /* Pixmap formats list is a depth-to-bpp mapping --
1190                               there's just a single entry for every depth,
1191                               so we can safely break here */
1192                            break;
1193                    }
1194            }
1195            XFree(pfm);
1196            pfm = NULL;
1197            return True;
1198    }
1199    
1200    BOOL
1201    ui_init(void)
1202    {
1203            int screen_num;
1204    
1205            g_display = XOpenDisplay(NULL);
1206            if (g_display == NULL)
1207            {
1208                    error("Failed to open display: %s\n", XDisplayName(NULL));
1209                  return False;                  return False;
1210          }          }
1211    
1212          if (depth <= 8)          {
1213                  owncolmap = True;                  uint16 endianess_test = 1;
1214          else                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1215                  xcolmap = DefaultColormapOfScreen(screen);          }
1216    
1217          test = 1;          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1218          host_be = !(BOOL) (*(uint8 *) (&test));          screen_num = DefaultScreen(g_display);
1219          xserver_be = (ImageByteOrder(display) == MSBFirst);          g_x_socket = ConnectionNumber(g_display);
1220            g_screen = ScreenOfDisplay(g_display, screen_num);
1221            g_depth = DefaultDepthOfScreen(g_screen);
1222    
1223          white = WhitePixelOfScreen(screen);          if (!select_visual())
1224          attribs.background_pixel = BlackPixelOfScreen(screen);                  return False;
         attribs.backing_store = DoesBackingStore(screen);  
1225    
1226          if (attribs.backing_store == NotUseful)          if (g_no_translate_image)
1227                  ownbackstore = True;          {
1228                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1229            }
1230    
1231          if (fullscreen)          if (g_server_depth > g_bpp)
1232          {          {
1233                  attribs.override_redirect = True;                  warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1234                  width = WidthOfScreen(screen);                          g_server_depth, g_bpp);
                 height = HeightOfScreen(screen);  
1235          }          }
1236          else  
1237            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1238                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1239    
1240            if (!g_owncolmap)
1241            {
1242                    g_xcolmap =
1243                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1244                                            AllocNone);
1245                    if (g_depth <= 8)
1246                            warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1247            }
1248    
1249            if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1250            {
1251                    warning("External BackingStore not available. Using internal.\n");
1252                    g_ownbackstore = True;
1253            }
1254    
1255            /*
1256             * Determine desktop size
1257             */
1258            if (g_fullscreen)
1259            {
1260                    g_width = WidthOfScreen(g_screen);
1261                    g_height = HeightOfScreen(g_screen);
1262            }
1263            else if (g_width < 0)
1264          {          {
1265                  attribs.override_redirect = False;                  /* Percent of screen */
1266                    if (-g_width >= 100)
1267                            g_using_full_workarea = True;
1268                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1269                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1270          }          }
1271            else if (g_width == 0)
1272            {
1273                    /* Fetch geometry from _NET_WORKAREA */
1274                    uint32 x, y, cx, cy;
1275                    g_using_full_workarea = True;
1276    
1277                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1278                    {
1279                            g_width = cx;
1280                            g_height = cy;
1281                    }
1282                    else
1283                    {
1284                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1285                            g_width = 800;
1286                            g_height = 600;
1287                    }
1288            }
1289    
1290            /* make sure width is a multiple of 4 */
1291            g_width = (g_width + 3) & ~3;
1292    
1293            g_mod_map = XGetModifierMapping(g_display);
1294    
1295            xkeymap_init();
1296    
1297            if (g_enable_compose)
1298                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1299    
1300            xclip_init();
1301    
1302            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1303    
1304            return True;
1305    }
1306    
1307    void
1308    ui_deinit(void)
1309    {
1310            if (g_IM != NULL)
1311                    XCloseIM(g_IM);
1312    
1313            if (g_null_cursor != NULL)
1314                    ui_destroy_cursor(g_null_cursor);
1315    
1316            XFreeModifiermap(g_mod_map);
1317    
1318            if (g_ownbackstore)
1319                    XFreePixmap(g_display, g_backstore);
1320    
1321            XFreeGC(g_display, g_gc);
1322            XCloseDisplay(g_display);
1323            g_display = NULL;
1324    }
1325    
1326    BOOL
1327    ui_create_window(void)
1328    {
1329            uint8 null_pointer_mask[1] = { 0x80 };
1330            uint8 null_pointer_data[24] = { 0x00 };
1331    
1332            XSetWindowAttributes attribs;
1333            XClassHint *classhints;
1334            XSizeHints *sizehints;
1335            int wndwidth, wndheight;
1336            long input_mask, ic_input_mask;
1337            XEvent xevent;
1338    
1339            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1340            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1341    
1342            /* Handle -x-y portion of geometry string */
1343            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1344                    g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1345            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1346                    g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1347    
1348            attribs.background_pixel = BlackPixelOfScreen(g_screen);
1349            attribs.border_pixel = WhitePixelOfScreen(g_screen);
1350            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1351            attribs.override_redirect = g_fullscreen;
1352            attribs.colormap = g_xcolmap;
1353    
1354            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1355                                  wndheight, 0, g_depth, InputOutput, g_visual,
1356                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1357                                  CWBorderPixel, &attribs);
1358    
1359            if (g_gc == NULL)
1360                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1361    
1362          width = (width + 3) & ~3;       /* make width a multiple of 32 bits */          if (g_create_bitmap_gc == NULL)
1363                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1364    
1365          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          if ((g_ownbackstore) && (g_backstore == 0))
1366                              0, 0, width, height, 0, CopyFromParent,          {
1367                              InputOutput, CopyFromParent,                  g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1368                              CWBackingStore | CWBackPixel | CWOverrideRedirect, &attribs);  
1369                    /* clear to prevent rubbish being exposed at startup */
1370                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1371                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1372            }
1373    
1374          XStoreName(display, wnd, title);          XStoreName(g_display, g_wnd, g_title);
1375    
1376            if (g_hide_decorations)
1377                    mwm_hide_decorations();
1378    
1379          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1380          if (classhints != NULL)          if (classhints != NULL)
1381          {          {
1382                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
1383                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
1384                  XFree(classhints);                  XFree(classhints);
1385          }          }
1386    
# Line 346  ui_create_window(char *title) Line 1388  ui_create_window(char *title)
1388          if (sizehints)          if (sizehints)
1389          {          {
1390                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1391                  sizehints->min_width = sizehints->max_width = width;                  if (g_pos)
1392                  sizehints->min_height = sizehints->max_height = height;                          sizehints->flags |= PPosition;
1393                  XSetWMNormalHints(display, wnd, sizehints);                  sizehints->min_width = sizehints->max_width = g_width;
1394                    sizehints->min_height = sizehints->max_height = g_height;
1395                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1396                  XFree(sizehints);                  XFree(sizehints);
1397          }          }
1398    
1399          xkeymap_init2();          if (g_embed_wnd)
1400            {
1401                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1402            }
1403    
1404            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1405                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1406    
1407          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;          if (g_sendmotion)
         if (grab_keyboard)  
                 input_mask |= EnterWindowMask | LeaveWindowMask;  
         if (sendmotion)  
1408                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
1409            if (g_ownbackstore)
         if (ownbackstore)  
1410                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
1411            if (g_fullscreen || g_grab_keyboard)
1412                    input_mask |= EnterWindowMask;
1413            if (g_grab_keyboard)
1414                    input_mask |= LeaveWindowMask;
1415    
1416          if (enable_compose)          if (g_IM != NULL)
1417                  input_mask |= init_inputmethod();          {
1418                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1419                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1420    
1421          XSelectInput(display, wnd, input_mask);                  if ((g_IC != NULL)
1422                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1423                            input_mask |= ic_input_mask;
1424            }
1425    
1426          gc = XCreateGC(display, wnd, 0, NULL);          XSelectInput(g_display, g_wnd, input_mask);
1427            XMapWindow(g_display, g_wnd);
1428    
1429          if (ownbackstore)          /* wait for VisibilityNotify */
1430                  backstore = XCreatePixmap(display, wnd, width, height, depth);          do
1431            {
1432                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1433            }
1434            while (xevent.type != VisibilityNotify);
1435            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1436    
1437          XMapWindow(display, wnd);          g_focused = False;
1438            g_mouse_in_wnd = False;
1439    
1440            /* handle the WM_DELETE_WINDOW protocol */
1441            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1442            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1443            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1444    
1445            /* create invisible 1x1 cursor to be used as null cursor */
1446            if (g_null_cursor == NULL)
1447                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1448    
1449          return True;          return True;
1450  }  }
1451    
1452  void  void
1453  ui_destroy_window()  ui_resize_window()
1454    {
1455            XSizeHints *sizehints;
1456            Pixmap bs;
1457    
1458            sizehints = XAllocSizeHints();
1459            if (sizehints)
1460            {
1461                    sizehints->flags = PMinSize | PMaxSize;
1462                    sizehints->min_width = sizehints->max_width = g_width;
1463                    sizehints->min_height = sizehints->max_height = g_height;
1464                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1465                    XFree(sizehints);
1466            }
1467    
1468            if (!(g_fullscreen || g_embed_wnd))
1469            {
1470                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1471            }
1472    
1473            /* create new backstore pixmap */
1474            if (g_backstore != 0)
1475            {
1476                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1477                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1478                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1479                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1480                    XFreePixmap(g_display, g_backstore);
1481                    g_backstore = bs;
1482            }
1483    }
1484    
1485    void
1486    ui_destroy_window(void)
1487    {
1488            if (g_IC != NULL)
1489                    XDestroyIC(g_IC);
1490    
1491            XDestroyWindow(g_display, g_wnd);
1492    }
1493    
1494    void
1495    xwin_toggle_fullscreen(void)
1496  {  {
1497          if (ownbackstore)          Pixmap contents = 0;
1498                  XFreePixmap(display, backstore);  
1499            if (!g_ownbackstore)
1500            {
1501                    /* need to save contents of window */
1502                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1503                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1504            }
1505    
1506          XFreeGC(display, gc);          ui_destroy_window();
1507            g_fullscreen = !g_fullscreen;
1508            ui_create_window();
1509    
1510          close_inputmethod();          XDefineCursor(g_display, g_wnd, g_current_cursor);
1511    
1512          XDestroyWindow(display, wnd);          if (!g_ownbackstore)
1513          XCloseDisplay(display);          {
1514          display = NULL;                  XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1515                    XFreePixmap(g_display, contents);
1516            }
1517  }  }
1518    
1519  static void  static void
1520  xwin_process_events()  handle_button_event(XEvent xevent, BOOL down)
1521  {  {
1522          XEvent xevent;          uint16 button, flags = 0;
1523            g_last_gesturetime = xevent.xbutton.time;
1524            button = xkeymap_translate_button(xevent.xbutton.button);
1525            if (button == 0)
1526                    return;
1527    
1528            if (down)
1529                    flags = MOUSE_FLAG_DOWN;
1530    
1531            /* Stop moving window when button is released, regardless of cursor position */
1532            if (g_moving_wnd && (xevent.type == ButtonRelease))
1533                    g_moving_wnd = False;
1534    
1535            /* If win_button_size is nonzero, enable single app mode */
1536            if (xevent.xbutton.y < g_win_button_size)
1537            {
1538                    /*  Check from right to left: */
1539                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1540                    {
1541                            /* The close button, continue */
1542                            ;
1543                    }
1544                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1545                    {
1546                            /* The maximize/restore button. Do not send to
1547                               server.  It might be a good idea to change the
1548                               cursor or give some other visible indication
1549                               that rdesktop inhibited this click */
1550                            if (xevent.type == ButtonPress)
1551                                    return;
1552                    }
1553                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1554                    {
1555                            /* The minimize button. Iconify window. */
1556                            if (xevent.type == ButtonRelease)
1557                            {
1558                                    /* Release the mouse button outside the minimize button, to prevent the
1559                                       actual minimazation to happen */
1560                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1561                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1562                                    return;
1563                            }
1564                    }
1565                    else if (xevent.xbutton.x <= g_win_button_size)
1566                    {
1567                            /* The system menu. Ignore. */
1568                            if (xevent.type == ButtonPress)
1569                                    return;
1570                    }
1571                    else
1572                    {
1573                            /* The title bar. */
1574                            if (xevent.type == ButtonPress)
1575                            {
1576                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1577                                    {
1578                                            g_moving_wnd = True;
1579                                            g_move_x_offset = xevent.xbutton.x;
1580                                            g_move_y_offset = xevent.xbutton.y;
1581                                    }
1582                                    return;
1583                            }
1584                    }
1585            }
1586    
1587            rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1588                           flags | button, xevent.xbutton.x, xevent.xbutton.y);
1589    }
1590    
1591    /* Process events in Xlib queue
1592       Returns 0 after user quit, 1 otherwise */
1593    static int
1594    xwin_process_events(void)
1595    {
1596            XEvent xevent;
1597          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1598          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
         char *ksname = NULL;  
1599          char str[256];          char str[256];
1600          Status status;          Status status;
1601            int events = 0;
1602    
1603          /* Refresh keyboard mapping if it has changed. This is important for          while ((XPending(g_display) > 0) && events++ < 20)
            Xvnc, since it allocates keycodes dynamically */  
         if (XCheckTypedEvent(display, MappingNotify, &xevent))  
1604          {          {
1605                  if (xevent.xmapping.request == MappingKeyboard                  XNextEvent(g_display, &xevent);
                     || xevent.xmapping.request == MappingModifier)  
                         XRefreshKeyboardMapping(&xevent.xmapping);  
         }  
1606    
1607          while (XCheckMaskEvent(display, ~0, &xevent))                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
         {  
                 if (enable_compose && (XFilterEvent(&xevent, None) == True))  
1608                  {                  {
1609                          DEBUG_KBD(("Filtering event\n"));                          DEBUG_KBD(("Filtering event\n"));
1610                          continue;                          continue;
1611                  }                  }
1612    
                 ev_time = time(NULL);  
                 flags = 0;  
   
1613                  switch (xevent.type)                  switch (xevent.type)
1614                  {                  {
1615                            case VisibilityNotify:
1616                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1617                                    break;
1618                            case ClientMessage:
1619                                    /* the window manager told us to quit */
1620                                    if ((xevent.xclient.message_type == g_protocol_atom)
1621                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1622                                            /* Quit */
1623                                            return 0;
1624                                    break;
1625    
1626                          case KeyPress:                          case KeyPress:
1627                                  if (IC != NULL)                                  g_last_gesturetime = xevent.xkey.time;
1628                                    if (g_IC != NULL)
1629                                          /* Multi_key compatible version */                                          /* Multi_key compatible version */
1630                                  {                                  {
1631                                          XmbLookupString(IC,                                          XmbLookupString(g_IC,
1632                                                          (XKeyPressedEvent *) &                                                          &xevent.xkey, str, sizeof(str), &keysym,
1633                                                          xevent, str, sizeof(str), &keysym, &status);                                                          &status);
1634                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1635                                          {                                          {
1636                                                  error("XmbLookupString failed with status 0x%x\n",                                                  error("XmbLookupString failed with status 0x%x\n",
# Line 445  xwin_process_events() Line 1641  xwin_process_events()
1641                                  else                                  else
1642                                  {                                  {
1643                                          /* Plain old XLookupString */                                          /* Plain old XLookupString */
1644                                          DEBUG_KBD(("No input context, using XLookupString\n"));                                          DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1645                                          XLookupString((XKeyEvent *) & xevent,                                          XLookupString((XKeyEvent *) & xevent,
1646                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1647                                  }                                  }
1648    
1649                                  ksname = get_ksname(keysym);                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1650                                  DEBUG_KBD(("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));                                             get_ksname(keysym)));
1651    
1652                                  if (inhibit_key(keysym))                                  ev_time = time(NULL);
1653                                  {                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
                                         DEBUG_KBD(("Inhibiting key\n"));  
1654                                          break;                                          break;
                                 }  
1655    
1656                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1657                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, True, 0);
   
                                 ensure_remote_modifiers(ev_time, tr);  
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);  
1658                                  break;                                  break;
1659    
1660                          case KeyRelease:                          case KeyRelease:
1661                                    g_last_gesturetime = xevent.xkey.time;
1662                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1663                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1664    
1665                                  ksname = get_ksname(keysym);                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1666                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                             get_ksname(keysym)));
                                            ksname));  
1667    
1668                                  if (inhibit_key(keysym))                                  ev_time = time(NULL);
1669                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1670                                          break;                                          break;
1671    
1672                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1673                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1674                                  break;                                  break;
1675    
1676                          case ButtonPress:                          case ButtonPress:
1677                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1678                                  /* fall through */                                  break;
1679    
1680                          case ButtonRelease:                          case ButtonRelease:
1681                                  button = xkeymap_translate_button(xevent.xbutton.button);                                  handle_button_event(xevent, False);
                                 if (button == 0)  
                                         break;  
   
                                 rdp_send_input(ev_time, RDP_INPUT_MOUSE,  
                                                flags | button, xevent.xbutton.x, xevent.xbutton.y);  
1682                                  break;                                  break;
1683    
1684                          case MotionNotify:                          case MotionNotify:
1685                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_moving_wnd)
1686                                    {
1687                                            XMoveWindow(g_display, g_wnd,
1688                                                        xevent.xmotion.x_root - g_move_x_offset,
1689                                                        xevent.xmotion.y_root - g_move_y_offset);
1690                                            break;
1691                                    }
1692    
1693                                    if (g_fullscreen && !g_focused)
1694                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1695                                                           CurrentTime);
1696                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1697                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1698                                  break;                                  break;
1699    
1700                          case FocusIn:                          case FocusIn:
1701                                  /* fall through */                                  if (xevent.xfocus.mode == NotifyGrab)
1702                          case EnterNotify:                                          break;
1703                                  if (grab_keyboard)                                  g_focused = True;
1704                                          XGrabKeyboard(display, wnd, True,                                  reset_modifier_keys();
1705                                    if (g_grab_keyboard && g_mouse_in_wnd)
1706                                            XGrabKeyboard(g_display, g_wnd, True,
1707                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1708                                  break;                                  break;
1709    
1710                          case FocusOut:                          case FocusOut:
1711                                  /* reset keys */                                  if (xevent.xfocus.mode == NotifyUngrab)
1712                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                          break;
1713                                                 KBD_FLAG_DOWN | KBD_FLAG_UP, SCANCODE_CHAR_LCTRL, 0);                                  g_focused = False;
1714                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)
1715                                                 KBD_FLAG_DOWN | KBD_FLAG_UP, SCANCODE_CHAR_LALT, 0);                                          XUngrabKeyboard(g_display, CurrentTime);
1716                                  /* fall through */                                  break;
1717    
1718                            case EnterNotify:
1719                                    /* we only register for this event when in fullscreen mode */
1720                                    /* or grab_keyboard */
1721                                    g_mouse_in_wnd = True;
1722                                    if (g_fullscreen)
1723                                    {
1724                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1725                                                           CurrentTime);
1726                                            break;
1727                                    }
1728                                    if (g_focused)
1729                                            XGrabKeyboard(g_display, g_wnd, True,
1730                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1731                                    break;
1732    
1733                          case LeaveNotify:                          case LeaveNotify:
1734                                  if (grab_keyboard)                                  /* we only register for this event when grab_keyboard */
1735                                          XUngrabKeyboard(display, CurrentTime);                                  g_mouse_in_wnd = False;
1736                                    XUngrabKeyboard(g_display, CurrentTime);
1737                                  break;                                  break;
1738    
1739                          case Expose:                          case Expose:
1740                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1741                                            xevent.xexpose.x, xevent.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
1742                                            xevent.xexpose.width,                                            xevent.xexpose.width,
1743                                            xevent.xexpose.height,                                            xevent.xexpose.height,
1744                                            xevent.xexpose.x, xevent.xexpose.y);                                            xevent.xexpose.x, xevent.xexpose.y);
1745                                  break;                                  break;
1746    
1747                            case MappingNotify:
1748                                    /* Refresh keyboard mapping if it has changed. This is important for
1749                                       Xvnc, since it allocates keycodes dynamically */
1750                                    if (xevent.xmapping.request == MappingKeyboard
1751                                        || xevent.xmapping.request == MappingModifier)
1752                                            XRefreshKeyboardMapping(&xevent.xmapping);
1753    
1754                                    if (xevent.xmapping.request == MappingModifier)
1755                                    {
1756                                            XFreeModifiermap(g_mod_map);
1757                                            g_mod_map = XGetModifierMapping(g_display);
1758                                    }
1759                                    break;
1760    
1761                                    /* clipboard stuff */
1762                            case SelectionNotify:
1763                                    xclip_handle_SelectionNotify(&xevent.xselection);
1764                                    break;
1765                            case SelectionRequest:
1766                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1767                                    break;
1768                            case SelectionClear:
1769                                    xclip_handle_SelectionClear();
1770                                    break;
1771                            case PropertyNotify:
1772                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1773                                    break;
1774                            case MapNotify:
1775                                    rdp_send_client_window_status(1);
1776                                    break;
1777                            case UnmapNotify:
1778                                    rdp_send_client_window_status(0);
1779                                    break;
1780                  }                  }
1781          }          }
1782            /* Keep going */
1783            return 1;
1784  }  }
1785    
1786  void  /* Returns 0 after user quit, 1 otherwise */
1787    int
1788  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1789  {  {
1790          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;          int n;
1791          fd_set rfds;          fd_set rfds, wfds;
1792            struct timeval tv;
1793          FD_ZERO(&rfds);          BOOL s_timeout = False;
1794    
1795          while (True)          while (True)
1796          {          {
1797                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1798                    /* Process any events already waiting */
1799                    if (!xwin_process_events())
1800                            /* User quit */
1801                            return 0;
1802    
1803                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1804                    FD_ZERO(&wfds);
1805                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1806                  if (display != NULL)                  FD_SET(g_x_socket, &rfds);
1807    
1808    #ifdef WITH_RDPSND
1809                    /* FIXME: there should be an API for registering fds */
1810                    if (g_dsp_busy)
1811                  {                  {
1812                          FD_SET(x_socket, &rfds);                          FD_SET(g_dsp_fd, &wfds);
1813                          XFlush(display);                          n = (g_dsp_fd > n) ? g_dsp_fd : n;
1814                  }                  }
1815    #endif
1816                    /* default timeout */
1817                    tv.tv_sec = 60;
1818                    tv.tv_usec = 0;
1819    
1820                    /* add redirection handles */
1821                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1822    
1823                  switch (select(n, &rfds, NULL, NULL, NULL))                  n++;
1824    
1825                    switch (select(n, &rfds, &wfds, NULL, &tv))
1826                  {                  {
1827                          case -1:                          case -1:
1828                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1829    
1830                          case 0:                          case 0:
1831                                    /* Abort serial read calls */
1832                                    if (s_timeout)
1833                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1834                                  continue;                                  continue;
1835                  }                  }
1836    
1837                  if (FD_ISSET(x_socket, &rfds))                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
                         xwin_process_events();  
1838    
1839                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1840                          return;                          return 1;
1841    
1842    #ifdef WITH_RDPSND
1843                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1844                            wave_out_play();
1845    #endif
1846          }          }
1847  }  }
1848    
1849  void  void
1850  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1851  {  {
1852          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1853  }  }
1854    
1855  HBITMAP  HBITMAP
# Line 585  ui_create_bitmap(int width, int height, Line 1858  ui_create_bitmap(int width, int height,
1858          XImage *image;          XImage *image;
1859          Pixmap bitmap;          Pixmap bitmap;
1860          uint8 *tdata;          uint8 *tdata;
1861            int bitmap_pad;
1862    
1863          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_server_depth == 8)
1864          bitmap = XCreatePixmap(display, wnd, width, height, depth);          {
1865          image = XCreateImage(display, visual, depth, ZPixmap, 0,                  bitmap_pad = 8;
1866                               (char *) tdata, width, height, 8, 0);          }
1867            else
1868            {
1869                    bitmap_pad = g_bpp;
1870    
1871                    if (g_bpp == 24)
1872                            bitmap_pad = 32;
1873            }
1874    
1875          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1876            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1877            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1878                                 (char *) tdata, width, height, bitmap_pad, 0);
1879    
1880            XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1881    
1882          XFree(image);          XFree(image);
1883          if (!owncolmap)          if (tdata != data)
1884                  xfree(tdata);                  xfree(tdata);
1885          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1886  }  }
# Line 604  ui_paint_bitmap(int x, int y, int cx, in Line 1890  ui_paint_bitmap(int x, int y, int cx, in
1890  {  {
1891          XImage *image;          XImage *image;
1892          uint8 *tdata;          uint8 *tdata;
1893            int bitmap_pad;
1894    
1895            if (g_server_depth == 8)
1896            {
1897                    bitmap_pad = 8;
1898            }
1899            else
1900            {
1901                    bitmap_pad = g_bpp;
1902    
1903          tdata = (owncolmap ? data : translate_image(width, height, data));                  if (g_bpp == 24)
1904          image = XCreateImage(display, visual, depth, ZPixmap, 0,                          bitmap_pad = 32;
1905                               (char *) tdata, width, height, 8, 0);          }
1906    
1907            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1908            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1909                                 (char *) tdata, width, height, bitmap_pad, 0);
1910    
1911          if (ownbackstore)          if (g_ownbackstore)
1912          {          {
1913                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1914                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1915          }          }
1916          else          else
1917          {          {
1918                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1919          }          }
1920    
1921          XFree(image);          XFree(image);
1922          if (!owncolmap)          if (tdata != data)
1923                  xfree(tdata);                  xfree(tdata);
1924  }  }
1925    
1926  void  void
1927  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1928  {  {
1929          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1930  }  }
1931    
1932  HGLYPH  HGLYPH
# Line 636  ui_create_glyph(int width, int height, u Line 1935  ui_create_glyph(int width, int height, u
1935          XImage *image;          XImage *image;
1936          Pixmap bitmap;          Pixmap bitmap;
1937          int scanline;          int scanline;
         GC gc;  
1938    
1939          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1940    
1941          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1942          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1943                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1944    
1945          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1946                               width, height, 8, scanline);                               width, height, 8, scanline);
1947          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1948          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1949          XInitImage(image);          XInitImage(image);
1950    
1951          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
1952    
1953          XFree(image);          XFree(image);
         XFreeGC(display, gc);  
1954          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1955  }  }
1956    
1957  void  void
1958  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1959  {  {
1960          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1961  }  }
1962    
1963  HCURSOR  HCURSOR
# Line 678  ui_create_cursor(unsigned int x, unsigne Line 1976  ui_create_cursor(unsigned int x, unsigne
1976          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1977          offset = scanline * height;          offset = scanline * height;
1978    
1979          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1980          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1981    
1982          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1983          memset(mask, 0, offset);          memset(mask, 0, offset);
1984    
1985          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 723  ui_create_cursor(unsigned int x, unsigne Line 2021  ui_create_cursor(unsigned int x, unsigne
2021          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
2022    
2023          xcursor =          xcursor =
2024                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
2025                                      (Pixmap) maskglyph, &fg, &bg, x, y);                                      (Pixmap) maskglyph, &fg, &bg, x, y);
2026    
2027          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
# Line 736  ui_create_cursor(unsigned int x, unsigne Line 2034  ui_create_cursor(unsigned int x, unsigne
2034  void  void
2035  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
2036  {  {
2037          XDefineCursor(display, wnd, (Cursor) cursor);          g_current_cursor = (Cursor) cursor;
2038            XDefineCursor(g_display, g_wnd, g_current_cursor);
2039  }  }
2040    
2041  void  void
2042  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
2043  {  {
2044          XFreeCursor(display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2045    }
2046    
2047    void
2048    ui_set_null_cursor(void)
2049    {
2050            ui_set_cursor(g_null_cursor);
2051  }  }
2052    
2053  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 751  ui_destroy_cursor(HCURSOR cursor) Line 2056  ui_destroy_cursor(HCURSOR cursor)
2056                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
2057                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2058    
2059    
2060  HCOLOURMAP  HCOLOURMAP
2061  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
2062  {  {
2063          COLOURENTRY *entry;          COLOURENTRY *entry;
2064          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
2065            if (!g_owncolmap)
2066            {
2067                    uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
2068                    XColor xentry;
2069                    XColor xc_cache[256];
2070                    uint32 colour;
2071                    int colLookup = 256;
2072                    for (i = 0; i < ncolours; i++)
2073                    {
2074                            entry = &colours->colours[i];
2075                            MAKE_XCOLOR(&xentry, entry);
2076    
2077                            if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
2078                            {
2079                                    /* Allocation failed, find closest match. */
2080                                    int j = 256;
2081                                    int nMinDist = 3 * 256 * 256;
2082                                    long nDist = nMinDist;
2083    
2084          if (owncolmap)                                  /* only get the colors once */
2085                                    while (colLookup--)
2086                                    {
2087                                            xc_cache[colLookup].pixel = colLookup;
2088                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
2089                                                    xc_cache[colLookup].blue = 0;
2090                                            xc_cache[colLookup].flags = 0;
2091                                            XQueryColor(g_display,
2092                                                        DefaultColormap(g_display,
2093                                                                        DefaultScreen(g_display)),
2094                                                        &xc_cache[colLookup]);
2095                                    }
2096                                    colLookup = 0;
2097    
2098                                    /* approximate the pixel */
2099                                    while (j--)
2100                                    {
2101                                            if (xc_cache[j].flags)
2102                                            {
2103                                                    nDist = ((long) (xc_cache[j].red >> 8) -
2104                                                             (long) (xentry.red >> 8)) *
2105                                                            ((long) (xc_cache[j].red >> 8) -
2106                                                             (long) (xentry.red >> 8)) +
2107                                                            ((long) (xc_cache[j].green >> 8) -
2108                                                             (long) (xentry.green >> 8)) *
2109                                                            ((long) (xc_cache[j].green >> 8) -
2110                                                             (long) (xentry.green >> 8)) +
2111                                                            ((long) (xc_cache[j].blue >> 8) -
2112                                                             (long) (xentry.blue >> 8)) *
2113                                                            ((long) (xc_cache[j].blue >> 8) -
2114                                                             (long) (xentry.blue >> 8));
2115                                            }
2116                                            if (nDist < nMinDist)
2117                                            {
2118                                                    nMinDist = nDist;
2119                                                    xentry.pixel = j;
2120                                            }
2121                                    }
2122                            }
2123                            colour = xentry.pixel;
2124    
2125                            /* update our cache */
2126                            if (xentry.pixel < 256)
2127                            {
2128                                    xc_cache[xentry.pixel].red = xentry.red;
2129                                    xc_cache[xentry.pixel].green = xentry.green;
2130                                    xc_cache[xentry.pixel].blue = xentry.blue;
2131    
2132                            }
2133    
2134                            map[i] = colour;
2135                    }
2136                    return map;
2137            }
2138            else
2139          {          {
2140                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
2141                  Colormap map;                  Colormap map;
2142    
2143                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
2144                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
2145                  {                  {
2146                          entry = &colours->colours[i];                          entry = &colours->colours[i];
# Line 771  ui_create_colourmap(COLOURMAP * colours) Line 2149  ui_create_colourmap(COLOURMAP * colours)
2149                          MAKE_XCOLOR(xentry, entry);                          MAKE_XCOLOR(xentry, entry);
2150                  }                  }
2151    
2152                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
2153                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2154    
2155                  xfree(xcolours);                  xfree(xcolours);
2156                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
2157          }          }
         else  
         {  
                 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);  
                 XColor xentry;  
                 uint32 colour;  
   
                 for (i = 0; i < ncolours; i++)  
                 {  
                         entry = &colours->colours[i];  
                         MAKE_XCOLOR(&xentry, entry);  
   
                         if (XAllocColor(display, xcolmap, &xentry) != 0)  
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
                 }  
   
                 return map;  
         }  
2158  }  }
2159    
2160  void  void
2161  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
2162  {  {
2163          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap) map);  
         else  
2164                  xfree(map);                  xfree(map);
2165            else
2166                    XFreeColormap(g_display, (Colormap) map);
2167  }  }
2168    
2169  void  void
2170  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
2171  {  {
2172          if (owncolmap)          if (!g_owncolmap)
2173                  XSetWindowColormap(display, wnd, (Colormap) map);          {
2174                    if (g_colmap)
2175                            xfree(g_colmap);
2176    
2177                    g_colmap = (uint32 *) map;
2178            }
2179          else          else
2180                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2181  }  }
2182    
2183  void  void
# Line 828  ui_set_clip(int x, int y, int cx, int cy Line 2189  ui_set_clip(int x, int y, int cx, int cy
2189          rect.y = y;          rect.y = y;
2190          rect.width = cx;          rect.width = cx;
2191          rect.height = cy;          rect.height = cy;
2192          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2193  }  }
2194    
2195  void  void
2196  ui_reset_clip()  ui_reset_clip(void)
2197  {  {
2198          XRectangle rect;          XRectangle rect;
2199    
2200          rect.x = 0;          rect.x = 0;
2201          rect.y = 0;          rect.y = 0;
2202          rect.width = width;          rect.width = g_width;
2203          rect.height = height;          rect.height = g_height;
2204          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2205  }  }
2206    
2207  void  void
2208  ui_bell()  ui_bell(void)
2209  {  {
2210          XBell(display, 0);          XBell(g_display, 0);
2211  }  }
2212    
2213  void  void
# Line 858  ui_destblt(uint8 opcode, Line 2219  ui_destblt(uint8 opcode,
2219          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2220  }  }
2221    
2222    static uint8 hatch_patterns[] = {
2223            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2224            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2225            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2226            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2227            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2228            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
2229    };
2230    
2231  void  void
2232  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
2233            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
# Line 872  ui_patblt(uint8 opcode, Line 2242  ui_patblt(uint8 opcode,
2242          {          {
2243                  case 0: /* Solid */                  case 0: /* Solid */
2244                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2245                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2246                            break;
2247    
2248                    case 2: /* Hatch */
2249                            fill = (Pixmap) ui_create_glyph(8, 8,
2250                                                            hatch_patterns + brush->pattern[0] * 8);
2251                            SET_FOREGROUND(fgcolour);
2252                            SET_BACKGROUND(bgcolour);
2253                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2254                            XSetStipple(g_display, g_gc, fill);
2255                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2256                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2257                            XSetFillStyle(g_display, g_gc, FillSolid);
2258                            XSetTSOrigin(g_display, g_gc, 0, 0);
2259                            ui_destroy_glyph((HGLYPH) fill);
2260                          break;                          break;
2261    
2262                  case 3: /* Pattern */                  case 3: /* Pattern */
2263                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2264                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2265                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
2266                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2267                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2268                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2269                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
2270                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2271                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2272                          FILL_RECTANGLE(x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
2273                            XSetTSOrigin(g_display, g_gc, 0, 0);
                         XSetFillStyle(display, gc, FillSolid);  
                         XSetTSOrigin(display, gc, 0, 0);  
2274                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
2275                          break;                          break;
2276    
# Line 898  ui_patblt(uint8 opcode, Line 2279  ui_patblt(uint8 opcode,
2279          }          }
2280    
2281          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2282    
2283            if (g_ownbackstore)
2284                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2285  }  }
2286    
2287  void  void
# Line 906  ui_screenblt(uint8 opcode, Line 2290  ui_screenblt(uint8 opcode,
2290               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2291  {  {
2292          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2293          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
2294          if (ownbackstore)          {
2295                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);                  if (g_Unobscured)
2296                    {
2297                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2298                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2299                                      y);
2300                    }
2301                    else
2302                    {
2303                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2304                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2305                                      y);
2306                    }
2307            }
2308            else
2309            {
2310                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2311            }
2312          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2313  }  }
2314    
# Line 918  ui_memblt(uint8 opcode, Line 2318  ui_memblt(uint8 opcode,
2318            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
2319  {  {
2320          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2321          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2322          if (ownbackstore)          if (g_ownbackstore)
2323                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2324          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2325  }  }
2326    
# Line 964  ui_line(uint8 opcode, Line 2364  ui_line(uint8 opcode,
2364  {  {
2365          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2366          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2367          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2368          if (ownbackstore)          if (g_ownbackstore)
2369                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2370          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2371  }  }
2372    
# Line 980  ui_rect( Line 2380  ui_rect(
2380  }  }
2381    
2382  void  void
2383    ui_polygon(uint8 opcode,
2384               /* mode */ uint8 fillmode,
2385               /* dest */ POINT * point, int npoints,
2386               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2387    {
2388            uint8 style, i, ipattern[8];
2389            Pixmap fill;
2390    
2391            SET_FUNCTION(opcode);
2392    
2393            switch (fillmode)
2394            {
2395                    case ALTERNATE:
2396                            XSetFillRule(g_display, g_gc, EvenOddRule);
2397                            break;
2398                    case WINDING:
2399                            XSetFillRule(g_display, g_gc, WindingRule);
2400                            break;
2401                    default:
2402                            unimpl("fill mode %d\n", fillmode);
2403            }
2404    
2405            if (brush)
2406                    style = brush->style;
2407            else
2408                    style = 0;
2409    
2410            switch (style)
2411            {
2412                    case 0: /* Solid */
2413                            SET_FOREGROUND(fgcolour);
2414                            FILL_POLYGON((XPoint *) point, npoints);
2415                            break;
2416    
2417                    case 2: /* Hatch */
2418                            fill = (Pixmap) ui_create_glyph(8, 8,
2419                                                            hatch_patterns + brush->pattern[0] * 8);
2420                            SET_FOREGROUND(fgcolour);
2421                            SET_BACKGROUND(bgcolour);
2422                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2423                            XSetStipple(g_display, g_gc, fill);
2424                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2425                            FILL_POLYGON((XPoint *) point, npoints);
2426                            XSetFillStyle(g_display, g_gc, FillSolid);
2427                            XSetTSOrigin(g_display, g_gc, 0, 0);
2428                            ui_destroy_glyph((HGLYPH) fill);
2429                            break;
2430    
2431                    case 3: /* Pattern */
2432                            for (i = 0; i != 8; i++)
2433                                    ipattern[7 - i] = brush->pattern[i];
2434                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2435                            SET_FOREGROUND(bgcolour);
2436                            SET_BACKGROUND(fgcolour);
2437                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2438                            XSetStipple(g_display, g_gc, fill);
2439                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2440                            FILL_POLYGON((XPoint *) point, npoints);
2441                            XSetFillStyle(g_display, g_gc, FillSolid);
2442                            XSetTSOrigin(g_display, g_gc, 0, 0);
2443                            ui_destroy_glyph((HGLYPH) fill);
2444                            break;
2445    
2446                    default:
2447                            unimpl("brush %d\n", brush->style);
2448            }
2449    
2450            RESET_FUNCTION(opcode);
2451    }
2452    
2453    void
2454    ui_polyline(uint8 opcode,
2455                /* dest */ POINT * points, int npoints,
2456                /* pen */ PEN * pen)
2457    {
2458            /* TODO: set join style */
2459            SET_FUNCTION(opcode);
2460            SET_FOREGROUND(pen->colour);
2461            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2462            if (g_ownbackstore)
2463                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2464                               CoordModePrevious);
2465            RESET_FUNCTION(opcode);
2466    }
2467    
2468    void
2469    ui_ellipse(uint8 opcode,
2470               /* mode */ uint8 fillmode,
2471               /* dest */ int x, int y, int cx, int cy,
2472               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2473    {
2474            uint8 style, i, ipattern[8];
2475            Pixmap fill;
2476    
2477            SET_FUNCTION(opcode);
2478    
2479            if (brush)
2480                    style = brush->style;
2481            else
2482                    style = 0;
2483    
2484            switch (style)
2485            {
2486                    case 0: /* Solid */
2487                            SET_FOREGROUND(fgcolour);
2488                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2489                            break;
2490    
2491                    case 2: /* Hatch */
2492                            fill = (Pixmap) ui_create_glyph(8, 8,
2493                                                            hatch_patterns + brush->pattern[0] * 8);
2494                            SET_FOREGROUND(fgcolour);
2495                            SET_BACKGROUND(bgcolour);
2496                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2497                            XSetStipple(g_display, g_gc, fill);
2498                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2499                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2500                            XSetFillStyle(g_display, g_gc, FillSolid);
2501                            XSetTSOrigin(g_display, g_gc, 0, 0);
2502                            ui_destroy_glyph((HGLYPH) fill);
2503                            break;
2504    
2505                    case 3: /* Pattern */
2506                            for (i = 0; i != 8; i++)
2507                                    ipattern[7 - i] = brush->pattern[i];
2508                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2509                            SET_FOREGROUND(bgcolour);
2510                            SET_BACKGROUND(fgcolour);
2511                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2512                            XSetStipple(g_display, g_gc, fill);
2513                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2514                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2515                            XSetFillStyle(g_display, g_gc, FillSolid);
2516                            XSetTSOrigin(g_display, g_gc, 0, 0);
2517                            ui_destroy_glyph((HGLYPH) fill);
2518                            break;
2519    
2520                    default:
2521                            unimpl("brush %d\n", brush->style);
2522            }
2523    
2524            RESET_FUNCTION(opcode);
2525    }
2526    
2527    /* warning, this function only draws on wnd or backstore, not both */
2528    void
2529  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
2530                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
2531                /* src */ HGLYPH glyph, int srcx, int srcy,                /* src */ HGLYPH glyph, int srcx, int srcy,
# Line 988  ui_draw_glyph(int mixmode, Line 2534  ui_draw_glyph(int mixmode,
2534          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
2535          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2536    
2537          XSetFillStyle(display, gc,          XSetFillStyle(g_display, g_gc,
2538                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2539          XSetStipple(display, gc, (Pixmap) glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2540          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
2541    
2542          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2543    
2544          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
2545  }  }
2546    
2547  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
2548  {\  {\
2549    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
2550    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
2551      {\
2552        xyoffset = ttext[++idx];\
2553        if ((xyoffset & 0x80))\
2554      {\      {\
2555        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
2556        if ((xyoffset & 0x80))\          y += ttext[idx+1] | (ttext[idx+2] << 8);\
         {\  
           if (flags & TEXT2_VERTICAL) \  
             y += ttext[idx+1] | (ttext[idx+2] << 8);\  
           else\  
             x += ttext[idx+1] | (ttext[idx+2] << 8);\  
           idx += 2;\  
         }\  
2557        else\        else\
2558          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
2559            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
2560      }\      }\
2561    if (glyph != NULL)\      else\
2562      {\      {\
2563        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2564                       y + (short) glyph->baseline,\          y += xyoffset;\
2565                       glyph->width, glyph->height,\        else\
2566                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
2567      }\      }\
2568      }\
2569      if (glyph != NULL)\
2570      {\
2571        x1 = x + glyph->offset;\
2572        y1 = y + glyph->baseline;\
2573        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2574        XSetTSOrigin(g_display, g_gc, x1, y1);\
2575        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2576        if (flags & TEXT2_IMPLICIT_X)\
2577          x += glyph->width;\
2578      }\
2579  }  }
2580    
2581  void  void
2582  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
2583               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2584               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2585               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2586  {  {
2587            /* TODO: use brush appropriately */
2588    
2589          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2590          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2591          DATABLOB *entry;          DATABLOB *entry;
2592    
2593          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2594    
2595            /* Sometimes, the boxcx value is something really large, like
2596               32691. This makes XCopyArea fail with Xvnc. The code below
2597               is a quick fix. */
2598            if (boxx + boxcx > g_width)
2599                    boxcx = g_width - boxx;
2600    
2601          if (boxcx > 1)          if (boxcx > 1)
2602          {          {
2603                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2604          }          }
2605          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
2606          {          {
2607                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2608          }          }
2609    
2610            SET_FOREGROUND(fgcolour);
2611            SET_BACKGROUND(bgcolour);
2612            XSetFillStyle(g_display, g_gc, FillStippled);
2613    
2614          /* Paint text, character by character */          /* Paint text, character by character */
2615          for (i = 0; i < length;)          for (i = 0; i < length;)
2616          {          {
2617                  switch (text[i])                  switch (text[i])
2618                  {                  {
2619                          case 0xff:                          case 0xff:
2620                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2621                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2622                                  {                                  {
2623                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2624                                            for (j = 0; j < length; j++)
2625                                                    fprintf(stderr, "%02x ", text[j]);
2626                                            fprintf(stderr, "\n");
2627                                            i = length = 0;
2628                                          break;                                          break;
2629                                  }                                  }
2630                                    cache_put_text(text[i + 1], text, text[i + 2]);
2631                                    i += 3;
2632                                    length -= i;
2633                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2634                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2635                                  i = 0;                                  i = 0;
2636                                  break;                                  break;
2637    
2638                          case 0xfe:                          case 0xfe:
2639                                    /* At least one byte needs to follow */
2640                                    if (i + 2 > length)
2641                                    {
2642                                            warning("Skipping short 0xfe command:");
2643                                            for (j = 0; j < length; j++)
2644                                                    fprintf(stderr, "%02x ", text[j]);
2645                                            fprintf(stderr, "\n");
2646                                            i = length = 0;
2647                                            break;
2648                                    }
2649                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2650                                  if (entry != NULL)                                  if (entry->data != NULL)
2651                                  {                                  {
2652                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2653                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2654                                          {                                          {
2655                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2656                                                          y += text[i + 2];                                                          y += text[i + 2];
2657                                                  else                                                  else
2658                                                          x += text[i + 2];                                                          x += text[i + 2];
2659                                          }                                          }
                                         if (i + 2 < length)  
                                                 i += 3;  
                                         else  
                                                 i += 2;  
                                         length -= i;  
                                         /* this will move pointer from start to first character after FE command */  
                                         text = &(text[i]);  
                                         i = 0;  
2660                                          for (j = 0; j < entry->size; j++)                                          for (j = 0; j < entry->size; j++)
2661                                                  DO_GLYPH(((uint8 *) (entry->data)), j);                                                  DO_GLYPH(((uint8 *) (entry->data)), j);
2662                                  }                                  }
2663                                    if (i + 2 < length)
2664                                            i += 3;
2665                                    else
2666                                            i += 2;
2667                                    length -= i;
2668                                    /* this will move pointer from start to first character after FE command */
2669                                    text = &(text[i]);
2670                                    i = 0;
2671                                  break;                                  break;
2672    
2673                          default:                          default:
# Line 1103  ui_draw_text(uint8 font, uint8 flags, in Line 2677  ui_draw_text(uint8 font, uint8 flags, in
2677                  }                  }
2678          }          }
2679    
2680            XSetFillStyle(g_display, g_gc, FillSolid);
2681    
2682            if (g_ownbackstore)
2683            {
2684                    if (boxcx > 1)
2685                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2686                                      boxy, boxcx, boxcy, boxx, boxy);
2687                    else
2688                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2689                                      clipy, clipcx, clipcy, clipx, clipy);
2690            }
2691  }  }
2692    
2693  void  void
# Line 1112  ui_desktop_save(uint32 offset, int x, in Line 2696  ui_desktop_save(uint32 offset, int x, in
2696          Pixmap pix;          Pixmap pix;
2697          XImage *image;          XImage *image;
2698    
2699          if (ownbackstore)          if (g_ownbackstore)
2700          {          {
2701                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2702          }          }
2703          else          else
2704          {          {
2705                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2706                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2707                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2708                  XFreePixmap(display, pix);                  XFreePixmap(g_display, pix);
2709          }          }
2710    
2711          offset *= bpp / 8;          offset *= g_bpp / 8;
2712          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2713    
2714          XDestroyImage(image);          XDestroyImage(image);
2715  }  }
# Line 1136  ui_desktop_restore(uint32 offset, int x, Line 2720  ui_desktop_restore(uint32 offset, int x,
2720          XImage *image;          XImage *image;
2721          uint8 *data;          uint8 *data;
2722    
2723          offset *= bpp / 8;          offset *= g_bpp / 8;
2724          data = cache_get_desktop(offset, cx, cy, bpp / 8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2725          if (data == NULL)          if (data == NULL)
2726                  return;                  return;
2727    
2728          image = XCreateImage(display, visual, depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2729                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2730    
2731          if (ownbackstore)          if (g_ownbackstore)
2732          {          {
2733                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2734                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2735          }          }
2736          else          else
2737          {          {
2738                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2739          }          }
2740    
2741          XFree(image);          XFree(image);
2742  }  }
2743    
2744    /* these do nothing here but are used in uiports */
2745    void
2746    ui_begin_update(void)
2747    {
2748    }
2749    
2750    void
2751    ui_end_update(void)
2752    {
2753    }

Legend:
Removed from v.84  
changed lines
  Added in v.1049

  ViewVC Help
Powered by ViewVC 1.1.26