/[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 319 by astrand, Mon Feb 10 13:02:57 2003 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-2002     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    #include <strings.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29    #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 hide_decorations;  extern BOOL g_sendmotion;
37  extern char title[];  extern BOOL g_fullscreen;
38  extern int server_bpp;  extern BOOL g_grab_keyboard;
39  BOOL enable_compose = False;  extern BOOL g_hide_decorations;
40  BOOL focused;  extern char g_title[];
41  BOOL mouse_in_wnd;  /* Color depth of the RDP session.
42       As of RDP 5.1, it may be 8, 15, 16 or 24. */
43  Display *display;  extern int g_server_depth;
44  static int x_socket;  extern int g_win_button_size;
45  static Screen *screen;  
46  static Window wnd;  Display *g_display;
47  static GC gc;  Time g_last_gesturetime;
48  static Visual *visual;  static int g_x_socket;
49  static int depth;  static Screen *g_screen;
50  static int bpp;  Window g_wnd;
51  static XIM IM;  extern uint32 g_embed_wnd;
52  static XIC IC;  BOOL g_enable_compose = False;
53  static XModifierKeymap *mod_map;  BOOL g_Unobscured;              /* used for screenblt */
54  static Cursor current_cursor;  static GC g_gc = NULL;
55  static Atom protocol_atom, kill_atom;  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 */  /* MWM decorations */
116  #define MWM_HINTS_DECORATIONS   (1L << 1)  #define MWM_HINTS_DECORATIONS   (1L << 1)
117  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
118  typedef struct  typedef struct
119  {  {
120          uint32 flags;          unsigned long flags;
121          uint32 functions;          unsigned long functions;
122          uint32 decorations;          unsigned long decorations;
123          sint32 inputMode;          long inputMode;
124          uint32 status;          unsigned long status;
125  }  }
126  PropMotifWmHints;  PropMotifWmHints;
127    
# Line 79  typedef struct Line 133  typedef struct
133  }  }
134  PixelColour;  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)\  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
145  { \  { \
146          XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \          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  BOOL owncolmap = False;  extern BOOL g_owncolmap;
175  static Colormap xcolmap;  static Colormap g_xcolmap;
176  static uint32 *colmap;  static uint32 *g_colmap = NULL;
177    
178  #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
179  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
180  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
181    
182  static int rop2_map[] = {  static int rop2_map[] = {
183          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 119  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  mwm_hide_decorations(void)  mwm_hide_decorations(void)
# Line 133  mwm_hide_decorations(void) Line 212  mwm_hide_decorations(void)
212          motif_hints.decorations = 0;          motif_hints.decorations = 0;
213    
214          /* get the atom for the property */          /* get the atom for the property */
215          hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);          hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
216          if (!hintsatom)          if (!hintsatom)
217          {          {
218                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
219                  return;                  return;
220          }          }
221    
222          XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
223                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
224  }  }
225    
226  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
227  split_colour15(uint32 colour)  { \
228  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
229          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
230          rv.red = (colour & 0x7c00) >> 10;          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
         rv.red = (rv.red * 0xff) / 0x1f;  
         rv.green = (colour & 0x03e0) >> 5;  
         rv.green = (rv.green * 0xff) / 0x1f;  
         rv.blue = (colour & 0x1f);  
         rv.blue = (rv.blue * 0xff) / 0x1f;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = (colour & 0xf800) >> 11;  
         rv.red = (rv.red * 0xff) / 0x1f;  
         rv.green = (colour & 0x07e0) >> 5;  
         rv.green = (rv.green * 0xff) / 0x3f;  
         rv.blue = (colour & 0x001f);  
         rv.blue = (rv.blue * 0xff) / 0x1f;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour24(uint32 colour)  
 {  
         PixelColour rv;  
         rv.blue = (colour & 0xff0000) >> 16;  
         rv.green = (colour & 0xff00) >> 8;  
         rv.red = (colour & 0xff);  
         return rv;  
231  }  }
232    
233  static uint32  #define SPLITCOLOUR16(colour, rv) \
234  make_colour16(PixelColour pc)  { \
235  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
236          pc.red = (pc.red * 0x1f) / 0xff;          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
237          pc.green = (pc.green * 0x3f) / 0xff;          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
238          pc.blue = (pc.blue * 0x1f) / 0xff;  } \
         return (pc.red << 11) | (pc.green << 5) | pc.blue;  
 }  
239    
240  static uint32  #define SPLITCOLOUR24(colour, rv) \
241  make_colour24(PixelColour pc)  { \
242  {          rv.blue = (colour & 0xff0000) >> 16; \
243          return (pc.red << 16) | (pc.green << 8) | pc.blue;          rv.green = (colour & 0x00ff00) >> 8; \
244            rv.red = (colour & 0x0000ff); \
245  }  }
246    
247  static uint32  #define MAKECOLOUR(pc) \
248  make_colour32(PixelColour pc)          ((pc.red >> g_red_shift_r) << g_red_shift_l) \
249  {                  | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
250          return (pc.red << 16) | (pc.green << 8) | pc.blue;                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
 }  
251    
252  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
253  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
254  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
255                          x = (x << 16) | (x >> 16); }                          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  static uint32
268  translate_colour(uint32 colour)  translate_colour(uint32 colour)
269  {  {
270          switch (server_bpp)          PixelColour pc;
271            switch (g_server_depth)
272          {          {
273                  case 15:                  case 15:
274                          switch (bpp)                          SPLITCOLOUR15(colour, pc);
                         {  
                                 case 16:  
                                         colour = make_colour16(split_colour15(colour));  
                                         break;  
                                 case 24:  
                                         colour = make_colour24(split_colour15(colour));  
                                         break;  
                                 case 32:  
                                         colour = make_colour32(split_colour15(colour));  
                                         break;  
                         }  
275                          break;                          break;
276                  case 16:                  case 16:
277                          switch (bpp)                          SPLITCOLOUR16(colour, pc);
                         {  
                                 case 16:  
                                         break;  
                                 case 24:  
                                         colour = make_colour24(split_colour16(colour));  
                                         break;  
                                 case 32:  
                                         colour = make_colour32(split_colour16(colour));  
                                         break;  
                         }  
278                          break;                          break;
279                  case 24:                  case 24:
280                          switch (bpp)                          SPLITCOLOUR24(colour, pc);
                         {  
                                 case 16:  
                                         colour = make_colour16(split_colour24(colour));  
                                         break;  
                                 case 24:  
                                         break;  
                                 case 32:  
                                         colour = make_colour32(split_colour24(colour));  
                                         break;  
                         }  
281                          break;                          break;
282          }                  default:
283          switch (bpp)                          /* Avoid warning */
284          {                          pc.red = 0;
285                  case 16:                          pc.green = 0;
286                          if (host_be != xserver_be)                          pc.blue = 0;
                                 BSWAP16(colour);  
287                          break;                          break;
288            }
289            return MAKECOLOUR(pc);
290    }
291    
292                  case 24:  /* indent is confused by UNROLL8 */
293                          if (xserver_be)  /* *INDENT-OFF* */
                                 BSWAP24(colour);  
                         break;  
294    
295                  case 32:  /* repeat and unroll, similar to bitmap.c */
296                          if (host_be != xserver_be)  /* potentialy any of the following translate */
297                                  BSWAP32(colour);  /* functions can use repeat but just doing */
298                          break;  /* the most common ones */
         }  
299    
300          return colour;  #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  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
329  {  {
330          while (out < end)          while (out < end)
331                  *(out++) = (uint8) colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
332  }  }
333    
334  static void  static void
335  translate8to16(uint8 * data, uint16 * out, uint16 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
336  {  {
337          while (out < end)          uint16 value;
338                  *(out++) = (uint16) colmap[*(data++)];  
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  translate8to24(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                  value = colmap[*(data++)];                  while (out < end)
376                  *(out++) = value;                  {
377                  *(out++) = value >> 8;                          value = g_colmap[*(data++)];
378                  *(out++) = value >> 16;                          BOUT24(out, value);
379                    }
380            }
381            else
382            {
383                    while (out < end)
384                    {
385                            value = g_colmap[*(data++)];
386                            LOUT24(out, value);
387                    }
388          }          }
389  }  }
390    
391  static void  static void
392  translate8to32(uint8 * data, uint32 * out, uint32 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
393  {  {
394          while (out < end)          uint32 value;
                 *(out++) = colmap[*(data++)];  
 }  
395    
396  /* todo the remaining translate function might need some big endian check ?? */          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 void  static void
425  translate15to16(uint16 * data, uint16 * out, uint16 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
426  {  {
427          while (out < end)          uint16 pixel;
428                  *(out++) = (uint16) make_colour16(split_colour15(*(data++)));          uint16 value;
429            PixelColour pc;
430    
431            if (g_xserver_be)
432            {
433                    while (out < end)
434                    {
435                            pixel = *(data++);
436                            if (g_host_be)
437                            {
438                                    BSWAP16(pixel);
439                            }
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  static void  static void
462  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
463  {  {
464          uint32 value;          uint32 value;
465            uint16 pixel;
466            PixelColour pc;
467    
468          while (out < end)          if (g_compatible_arch)
469            {
470                    /* *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                  value = make_colour24(split_colour15(*(data++)));                  while (out < end)
498                  *(out++) = value;                  {
499                  *(out++) = value >> 8;                          pixel = *(data++);
500                  *(out++) = value >> 16;                          if (g_host_be)
501                            {
502                                    BSWAP16(pixel);
503                            }
504                            SPLITCOLOUR15(pixel, pc);
505                            value = MAKECOLOUR(pc);
506                            LOUT24(out, value);
507                    }
508          }          }
509  }  }
510    
511  static void  static void
512  translate15to32(uint16 * data, uint32 * out, uint32 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
513  {  {
514          while (out < end)          uint16 pixel;
515                  *(out++) = make_colour32(split_colour15(*(data++)));          uint32 value;
516            PixelColour pc;
517    
518            if (g_compatible_arch)
519            {
520                    /* *INDENT-OFF* */
521                    REPEAT4
522                    (
523                            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  static void  static void
563  translate16to16(uint16 * data, uint16 * out, uint16 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
564  {  {
565          while (out < end)          uint16 pixel;
566                  *(out++) = (uint16) (*(data++));          uint16 value;
567  }          PixelColour pc;
568    
569            if (g_xserver_be)
570            {
571                    if (g_host_be)
572                    {
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            }
617    }
618    
619  static void  static void
620  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
621  {  {
622          uint32 value;          uint32 value;
623            uint16 pixel;
624            PixelColour pc;
625    
626          while (out < end)          if (g_compatible_arch)
627            {
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                    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                  value = make_colour24(split_colour16(*(data++)));                  if (g_host_be)
666                  *(out++) = value;                  {
667                  *(out++) = value >> 8;                          while (out < end)
668                  *(out++) = value >> 16;                          {
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  static void
690  translate16to32(uint16 * data, uint32 * out, uint32 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
691  {  {
692          while (out < end)          uint16 pixel;
693                  *(out++) = make_colour32(split_colour16(*(data++)));          uint32 value;
694            PixelColour pc;
695    
696            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                    if (g_host_be)
713                    {
714                            while (out < end)
715                            {
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  static void
761  translate24to16(uint8 * data, uint16 * out, uint16 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
762  {  {
763          uint32 pixel = 0;          uint32 pixel = 0;
764            uint16 value;
765            PixelColour pc;
766    
767          while (out < end)          while (out < end)
768          {          {
769                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
770                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
771                  pixel |= *(data++);                  pixel |= *(data++);
772                  *(out++) = (uint16) make_colour16(split_colour24(pixel));                  SPLITCOLOUR24(pixel, pc);
773                    value = MAKECOLOUR(pc);
774                    if (g_xserver_be)
775                    {
776                            BOUT16(out, value);
777                    }
778                    else
779                    {
780                            LOUT16(out, value);
781                    }
782          }          }
783  }  }
784    
785  static void  static void
786  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
787  {  {
788          while (out < end)          uint32 pixel;
789            uint32 value;
790            PixelColour pc;
791    
792            if (g_xserver_be)
793            {
794                    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                  *(out++) = (*(data++));                  while (out < end)
807                    {
808                            pixel = *(data++) << 16;
809                            pixel |= *(data++) << 8;
810                            pixel |= *(data++);
811                            SPLITCOLOUR24(pixel, pc);
812                            value = MAKECOLOUR(pc);
813                            LOUT24(out, value);
814                    }
815          }          }
816  }  }
817    
818  static void  static void
819  translate24to32(uint8 * data, uint32 * out, uint32 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
820  {  {
821          uint32 pixel = 0;          uint32 pixel;
822          while (out < end)          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                  memcpy(&pixel, data, 3);                  while (out < end)
850                  data += 3;                  {
851                  *(out++) = pixel;                          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                    while (out < end)
862                    {
863                            pixel = *(data++) << 16;
864                            pixel |= *(data++) << 8;
865                            pixel |= *(data++);
866                            SPLITCOLOUR24(pixel, pc);
867                            value = MAKECOLOUR(pc);
868                            LOUT32(out, value);
869                    }
870          }          }
871  }  }
872    
873  static uint8 *  static uint8 *
874  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
875  {  {
876          int size = width * height * bpp / 8;          int size;
877          uint8 *out = xmalloc(size);          uint8 *out;
878          uint8 *end = out + size;          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 (server_bpp)          switch (g_server_depth)
901          {          {
902                  case 24:                  case 24:
903                          switch (bpp)                          switch (g_bpp)
904                          {                          {
905                                  case 32:                                  case 32:
906                                          translate24to32(data, (uint32 *) out, (uint32 *) end);                                          translate24to32(data, out, end);
907                                          break;                                          break;
908                                  case 24:                                  case 24:
909                                          translate24to24(data, out, end);                                          translate24to24(data, out, end);
910                                          break;                                          break;
911                                  case 16:                                  case 16:
912                                          translate24to16(data, (uint16 *) out, (uint16 *) end);                                          translate24to16(data, out, end);
913                                          break;                                          break;
914                          }                          }
915                          break;                          break;
916                  case 16:                  case 16:
917                          switch (bpp)                          switch (g_bpp)
918                          {                          {
919                                  case 32:                                  case 32:
920                                          translate16to32((uint16 *) data, (uint32 *) out,                                          translate16to32((uint16 *) data, out, end);
                                                         (uint32 *) end);  
921                                          break;                                          break;
922                                  case 24:                                  case 24:
923                                          translate16to24((uint16 *) data, out, end);                                          translate16to24((uint16 *) data, out, end);
924                                          break;                                          break;
925                                  case 16:                                  case 16:
926                                          translate16to16((uint16 *) data, (uint16 *) out,                                          translate16to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
927                                          break;                                          break;
928                          }                          }
929                          break;                          break;
930                  case 15:                  case 15:
931                          switch (bpp)                          switch (g_bpp)
932                          {                          {
933                                  case 32:                                  case 32:
934                                          translate15to32((uint16 *) data, (uint32 *) out,                                          translate15to32((uint16 *) data, out, end);
                                                         (uint32 *) end);  
935                                          break;                                          break;
936                                  case 24:                                  case 24:
937                                          translate15to24((uint16 *) data, out, end);                                          translate15to24((uint16 *) data, out, end);
938                                          break;                                          break;
939                                  case 16:                                  case 16:
940                                          translate15to16((uint16 *) data, (uint16 *) out,                                          translate15to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
941                                          break;                                          break;
942                          }                          }
943                          break;                          break;
944                  case 8:                  case 8:
945                          switch (bpp)                          switch (g_bpp)
946                          {                          {
947                                  case 8:                                  case 8:
948                                          translate8to8(data, out, end);                                          translate8to8(data, out, end);
949                                          break;                                          break;
950                                  case 16:                                  case 16:
951                                          translate8to16(data, (uint16 *) out, (uint16 *) end);                                          translate8to16(data, out, end);
952                                          break;                                          break;
953                                  case 24:                                  case 24:
954                                          translate8to24(data, out, end);                                          translate8to24(data, out, end);
955                                          break;                                          break;
956                                  case 32:                                  case 32:
957                                          translate8to32(data, (uint32 *) out, (uint32 *) end);                                          translate8to32(data, out, end);
958                                          break;                                          break;
959                          }                          }
960                          break;                          break;
# Line 484  get_key_state(unsigned int state, uint32 Line 968  get_key_state(unsigned int state, uint32
968          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
969          int offset;          int offset;
970    
971          KeyCode keycode = XKeysymToKeycode(display, keysym);          KeyCode keycode = XKeysymToKeycode(g_display, keysym);
972    
973          if (keycode == NoSymbol)          if (keycode == NoSymbol)
974                  return False;                  return False;
975    
976          for (modifierpos = 0; modifierpos < 8; modifierpos++)          for (modifierpos = 0; modifierpos < 8; modifierpos++)
977          {          {
978                  offset = mod_map->max_keypermod * modifierpos;                  offset = g_mod_map->max_keypermod * modifierpos;
979    
980                  for (key = 0; key < mod_map->max_keypermod; key++)                  for (key = 0; key < g_mod_map->max_keypermod; key++)
981                  {                  {
982                          if (mod_map->modifiermap[offset + key] == keycode)                          if (g_mod_map->modifiermap[offset + key] == keycode)
983                                  keysymMask |= 1 << modifierpos;                                  keysymMask |= 1 << modifierpos;
984                  }                  }
985          }          }
# Line 503  get_key_state(unsigned int state, uint32 Line 987  get_key_state(unsigned int state, uint32
987          return (state & keysymMask) ? True : False;          return (state & keysymMask) ? True : False;
988  }  }
989    
990  BOOL  static void
991  ui_init(void)  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                    weight += (mask & 1);
1008            }
1009            while (mask >>= 1);
1010            return weight;
1011    }
1012    
1013    static BOOL
1014    select_visual()
1015  {  {
1016          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1017          uint16 test;          int pixmap_formats_count, visuals_count;
1018            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          display = XOpenDisplay(NULL);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1026          if (display == NULL)          if (pfm == NULL)
1027          {          {
1028                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1029                    XCloseDisplay(g_display);
1030                  return False;                  return False;
1031          }          }
1032    
1033          x_socket = ConnectionNumber(display);          /* Search for best TrueColor visual */
1034          screen = DefaultScreenOfDisplay(display);          template.class = TrueColor;
1035          visual = DefaultVisualOfScreen(screen);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1036          depth = DefaultDepthOfScreen(screen);          g_visual = NULL;
1037            g_no_translate_image = False;
1038            g_compatible_arch = False;
1039            if (vmatches != NULL)
1040            {
1041                    for (i = 0; i < visuals_count; ++i)
1042                    {
1043                            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                                    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(vmatches);
1127            }
1128    
1129            if (g_visual != NULL)
1130            {
1131                    g_owncolmap = False;
1132                    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          pfm = XListPixmapFormats(display, &i);          g_bpp = 0;
1160          if (pfm != NULL)          for (i = 0; i < pixmap_formats_count; ++i)
1161          {          {
1162                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1163                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1164                  {                  {
1165                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))                          g_bpp = pf->bits_per_pixel;
1166    
1167                            if (g_no_translate_image)
1168                          {                          {
1169                                  bpp = pfm[i].bits_per_pixel;                                  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                  }                  }
                 XFree(pfm);  
1194          }          }
1195            XFree(pfm);
1196            pfm = NULL;
1197            return True;
1198    }
1199    
1200          if (bpp < 8)  BOOL
1201    ui_init(void)
1202    {
1203            int screen_num;
1204    
1205            g_display = XOpenDisplay(NULL);
1206            if (g_display == NULL)
1207          {          {
1208                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
                 XCloseDisplay(display);  
1209                  return False;                  return False;
1210          }          }
1211    
         if (owncolmap != True)  
1212          {          {
1213                  xcolmap = DefaultColormapOfScreen(screen);                  uint16 endianess_test = 1;
1214                  if (depth <= 8)                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
                         warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");  
1215          }          }
1216    
1217          gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1218            screen_num = DefaultScreen(g_display);
1219            g_x_socket = ConnectionNumber(g_display);
1220            g_screen = ScreenOfDisplay(g_display, screen_num);
1221            g_depth = DefaultDepthOfScreen(g_screen);
1222    
1223          if (DoesBackingStore(screen) != Always)          if (!select_visual())
1224                  ownbackstore = True;                  return False;
1225    
1226          test = 1;          if (g_no_translate_image)
1227          host_be = !(BOOL) (*(uint8 *) (&test));          {
1228          xserver_be = (ImageByteOrder(display) == MSBFirst);                  DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1229            }
1230    
1231          if ((width == 0) || (height == 0))          if (g_server_depth > g_bpp)
1232            {
1233                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1234                            g_server_depth, g_bpp);
1235            }
1236    
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                    /* 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 */                  /* Fetch geometry from _NET_WORKAREA */
1274                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
1275                    g_using_full_workarea = True;
1276    
1277                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1278                  {                  {
1279                          width = cx;                          g_width = cx;
1280                          height = cy;                          g_height = cy;
1281                  }                  }
1282                  else                  else
1283                  {                  {
1284                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1285                          width = 800;                          g_width = 800;
1286                          height = 600;                          g_height = 600;
1287                  }                  }
1288          }          }
1289    
         if (fullscreen)  
         {  
                 width = WidthOfScreen(screen);  
                 height = HeightOfScreen(screen);  
         }  
   
1290          /* make sure width is a multiple of 4 */          /* make sure width is a multiple of 4 */
1291          width = (width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1292    
1293          if (ownbackstore)          g_mod_map = XGetModifierMapping(g_display);
         {  
                 backstore =  
                         XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);  
1294    
1295                  /* clear to prevent rubbish being exposed at startup */          xkeymap_init();
                 XSetForeground(display, gc, BlackPixelOfScreen(screen));  
                 XFillRectangle(display, backstore, gc, 0, 0, width, height);  
         }  
   
         mod_map = XGetModifierMapping(display);  
1296    
1297          if (enable_compose)          if (g_enable_compose)
1298                  IM = XOpenIM(display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1299    
1300          xkeymap_init();          xclip_init();
1301    
1302          /* todo take this out when high colour is done */          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
         printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);  
1303    
1304          return True;          return True;
1305  }  }
# Line 613  ui_init(void) Line 1307  ui_init(void)
1307  void  void
1308  ui_deinit(void)  ui_deinit(void)
1309  {  {
1310          if (IM != NULL)          if (g_IM != NULL)
1311                  XCloseIM(IM);                  XCloseIM(g_IM);
1312    
1313            if (g_null_cursor != NULL)
1314                    ui_destroy_cursor(g_null_cursor);
1315    
1316          XFreeModifiermap(mod_map);          XFreeModifiermap(g_mod_map);
1317    
1318          if (ownbackstore)          if (g_ownbackstore)
1319                  XFreePixmap(display, backstore);                  XFreePixmap(g_display, g_backstore);
1320    
1321          XFreeGC(display, gc);          XFreeGC(g_display, g_gc);
1322          XCloseDisplay(display);          XCloseDisplay(g_display);
1323          display = NULL;          g_display = NULL;
1324  }  }
1325    
1326  BOOL  BOOL
1327  ui_create_window(void)  ui_create_window(void)
1328  {  {
1329            uint8 null_pointer_mask[1] = { 0x80 };
1330            uint8 null_pointer_data[24] = { 0x00 };
1331    
1332          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1333          XClassHint *classhints;          XClassHint *classhints;
1334          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 636  ui_create_window(void) Line 1336  ui_create_window(void)
1336          long input_mask, ic_input_mask;          long input_mask, ic_input_mask;
1337          XEvent xevent;          XEvent xevent;
1338    
1339          wndwidth = fullscreen ? WidthOfScreen(screen) : width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1340          wndheight = fullscreen ? HeightOfScreen(screen) : height;          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          attribs.background_pixel = BlackPixelOfScreen(screen);          if (g_create_bitmap_gc == NULL)
1363          attribs.backing_store = ownbackstore ? NotUseful : Always;                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
         attribs.override_redirect = fullscreen;  
1364    
1365          wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,          if ((g_ownbackstore) && (g_backstore == 0))
1366                              0, CopyFromParent, InputOutput, CopyFromParent,          {
1367                              CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);                  g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1368    
1369          XStoreName(display, wnd, title);                  /* 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          if (hide_decorations)          XStoreName(g_display, g_wnd, g_title);
1375    
1376            if (g_hide_decorations)
1377                  mwm_hide_decorations();                  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 664  ui_create_window(void) Line 1388  ui_create_window(void)
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            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 |          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1405                  VisibilityChangeMask | FocusChangeMask;                  VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1406    
1407          if (sendmotion)          if (g_sendmotion)
1408                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
1409          if (ownbackstore)          if (g_ownbackstore)
1410                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
1411          if (fullscreen || grab_keyboard)          if (g_fullscreen || g_grab_keyboard)
1412                  input_mask |= EnterWindowMask;                  input_mask |= EnterWindowMask;
1413          if (grab_keyboard)          if (g_grab_keyboard)
1414                  input_mask |= LeaveWindowMask;                  input_mask |= LeaveWindowMask;
1415    
1416          if (IM != NULL)          if (g_IM != NULL)
1417          {          {
1418                  IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),                  g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1419                                 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);                                   XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1420    
1421                  if ((IC != NULL)                  if ((g_IC != NULL)
1422                      && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1423                          input_mask |= ic_input_mask;                          input_mask |= ic_input_mask;
1424          }          }
1425    
1426          XSelectInput(display, wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1427          XMapWindow(display, wnd);          XMapWindow(g_display, g_wnd);
1428    
1429          /* wait for VisibilityNotify */          /* wait for VisibilityNotify */
1430          do          do
1431          {          {
1432                  XMaskEvent(display, VisibilityChangeMask, &xevent);                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1433          }          }
1434          while (xevent.type != VisibilityNotify);          while (xevent.type != VisibilityNotify);
1435            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1436    
1437          focused = False;          g_focused = False;
1438          mouse_in_wnd = False;          g_mouse_in_wnd = False;
1439    
1440          /* handle the WM_DELETE_WINDOW protocol */          /* handle the WM_DELETE_WINDOW protocol */
1441          protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);          g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1442          kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);          g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1443          XSetWMProtocols(display, wnd, &kill_atom, 1);          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_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)  ui_destroy_window(void)
1487  {  {
1488          if (IC != NULL)          if (g_IC != NULL)
1489                  XDestroyIC(IC);                  XDestroyIC(g_IC);
1490    
1491          XDestroyWindow(display, wnd);          XDestroyWindow(g_display, g_wnd);
1492  }  }
1493    
1494  void  void
# Line 727  xwin_toggle_fullscreen(void) Line 1496  xwin_toggle_fullscreen(void)
1496  {  {
1497          Pixmap contents = 0;          Pixmap contents = 0;
1498    
1499          if (!ownbackstore)          if (!g_ownbackstore)
1500          {          {
1501                  /* need to save contents of window */                  /* need to save contents of window */
1502                  contents = XCreatePixmap(display, wnd, width, height, depth);                  contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1503                  XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);                  XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1504          }          }
1505    
1506          ui_destroy_window();          ui_destroy_window();
1507          fullscreen = !fullscreen;          g_fullscreen = !g_fullscreen;
1508          ui_create_window();          ui_create_window();
1509    
1510          XDefineCursor(display, wnd, current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
1511    
1512            if (!g_ownbackstore)
1513            {
1514                    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
1520    handle_button_event(XEvent xevent, BOOL down)
1521    {
1522            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          if (!ownbackstore)          /* 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                  XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);                  /*  Check from right to left: */
1539                  XFreePixmap(display, contents);                  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 all events in Xlib queue  /* Process events in Xlib queue
1592     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1593  static int  static int
1594  xwin_process_events(void)  xwin_process_events(void)
1595  {  {
1596          XEvent xevent;          XEvent xevent;
1597          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1598          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1599          char str[256];          char str[256];
1600          Status status;          Status status;
1601          unsigned int state;          int events = 0;
         Window wdummy;  
         int dummy;  
1602    
1603          while (XPending(display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1604          {          {
1605                  XNextEvent(display, &xevent);                  XNextEvent(g_display, &xevent);
1606    
1607                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1608                  {                  {
1609                          DEBUG_KBD(("Filtering event\n"));                          DEBUG_KBD(("Filtering event\n"));
1610                          continue;                          continue;
1611                  }                  }
1612    
                 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:                          case ClientMessage:
1619                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1620                                  if ((xevent.xclient.message_type == protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
1621                                      && (xevent.xclient.data.l[0] == kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1622                                          /* Quit */                                          /* Quit */
1623                                          return 0;                                          return 0;
1624                                  break;                                  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 807  xwin_process_events(void) Line 1646  xwin_process_events(void)
1646                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1647                                  }                                  }
1648    
1649                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1650                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1651    
1652                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1653                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
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);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 ensure_remote_modifiers(ev_time, tr);  
   
                                 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                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1666                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1667    
1668                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1669                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  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(time(NULL), RDP_INPUT_MOUSE,  
                                                flags | button, xevent.xbutton.x, xevent.xbutton.y);  
1682                                  break;                                  break;
1683    
1684                          case MotionNotify:                          case MotionNotify:
1685                                  if (fullscreen && !focused)                                  if (g_moving_wnd)
1686                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                  {
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);                                                         CurrentTime);
1696                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,                                  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);
# Line 869  xwin_process_events(void) Line 1700  xwin_process_events(void)
1700                          case FocusIn:                          case FocusIn:
1701                                  if (xevent.xfocus.mode == NotifyGrab)                                  if (xevent.xfocus.mode == NotifyGrab)
1702                                          break;                                          break;
1703                                  focused = True;                                  g_focused = True;
1704                                  XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,                                  reset_modifier_keys();
1705                                                &dummy, &dummy, &state);                                  if (g_grab_keyboard && g_mouse_in_wnd)
1706                                  reset_modifier_keys(state);                                          XGrabKeyboard(g_display, g_wnd, True,
                                 if (grab_keyboard && mouse_in_wnd)  
                                         XGrabKeyboard(display, wnd, True,  
1707                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1708                                  break;                                  break;
1709    
1710                          case FocusOut:                          case FocusOut:
1711                                  if (xevent.xfocus.mode == NotifyUngrab)                                  if (xevent.xfocus.mode == NotifyUngrab)
1712                                          break;                                          break;
1713                                  focused = False;                                  g_focused = False;
1714                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)
1715                                          XUngrabKeyboard(display, CurrentTime);                                          XUngrabKeyboard(g_display, CurrentTime);
1716                                  break;                                  break;
1717    
1718                          case EnterNotify:                          case EnterNotify:
1719                                  /* we only register for this event when in fullscreen mode */                                  /* we only register for this event when in fullscreen mode */
1720                                  /* or grab_keyboard */                                  /* or grab_keyboard */
1721                                  mouse_in_wnd = True;                                  g_mouse_in_wnd = True;
1722                                  if (fullscreen)                                  if (g_fullscreen)
1723                                  {                                  {
1724                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1725                                                         CurrentTime);                                                         CurrentTime);
1726                                          break;                                          break;
1727                                  }                                  }
1728                                  if (focused)                                  if (g_focused)
1729                                          XGrabKeyboard(display, wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
1730                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1731                                  break;                                  break;
1732    
1733                          case LeaveNotify:                          case LeaveNotify:
1734                                  /* we only register for this event when grab_keyboard */                                  /* we only register for this event when grab_keyboard */
1735                                  mouse_in_wnd = False;                                  g_mouse_in_wnd = False;
1736                                  XUngrabKeyboard(display, CurrentTime);                                  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,
# Line 924  xwin_process_events(void) Line 1753  xwin_process_events(void)
1753    
1754                                  if (xevent.xmapping.request == MappingModifier)                                  if (xevent.xmapping.request == MappingModifier)
1755                                  {                                  {
1756                                          XFreeModifiermap(mod_map);                                          XFreeModifiermap(g_mod_map);
1757                                          mod_map = XGetModifierMapping(display);                                          g_mod_map = XGetModifierMapping(g_display);
1758                                  }                                  }
1759                                  break;                                  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 */          /* Keep going */
# Line 939  xwin_process_events(void) Line 1787  xwin_process_events(void)
1787  int  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 */                  /* Process any events already waiting */
1799                  if (!xwin_process_events())                  if (!xwin_process_events())
1800                          /* User quit */                          /* User quit */
1801                          return 0;                          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                  FD_SET(x_socket, &rfds);                  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(g_dsp_fd, &wfds);
1813                            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                    n++;
1824    
1825                  switch (select(n, &rfds, NULL, NULL, NULL))                  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                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1838    
1839                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1840                          return 1;                          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 981  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, server_bpp == 8 ? 8 : bpp, 0);          }
1867            else
1868            {
1869                    bitmap_pad = g_bpp;
1870    
1871          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);                  if (g_bpp == 24)
1872                            bitmap_pad = 32;
1873            }
1874    
1875            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 1000  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          tdata = (owncolmap ? data : translate_image(width, height, data));          int bitmap_pad;
1894          image = XCreateImage(display, visual, depth, ZPixmap, 0,  
1895                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);          if (g_server_depth == 8)
1896            {
1897                    bitmap_pad = 8;
1898            }
1899            else
1900            {
1901                    bitmap_pad = g_bpp;
1902    
1903                    if (g_bpp == 24)
1904                            bitmap_pad = 32;
1905            }
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 1031  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 1073  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 1118  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 1131  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          current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2038          XDefineCursor(display, wnd, current_cursor);          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 1153  ui_create_colourmap(COLOURMAP * colours) Line 2062  ui_create_colourmap(COLOURMAP * colours)
2062  {  {
2063          COLOURENTRY *entry;          COLOURENTRY *entry;
2064          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
2065          if (!owncolmap)          if (!g_owncolmap)
2066          {          {
2067                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
2068                  XColor xentry;                  XColor xentry;
2069                  XColor xc_cache[256];                  XColor xc_cache[256];
2070                  uint32 colour;                  uint32 colour;
# Line 1165  ui_create_colourmap(COLOURMAP * colours) Line 2074  ui_create_colourmap(COLOURMAP * colours)
2074                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2075                          MAKE_XCOLOR(&xentry, entry);                          MAKE_XCOLOR(&xentry, entry);
2076    
2077                          if (XAllocColor(display, xcolmap, &xentry) == 0)                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
2078                          {                          {
2079                                  /* Allocation failed, find closest match. */                                  /* Allocation failed, find closest match. */
2080                                  int j = 256;                                  int j = 256;
# Line 1179  ui_create_colourmap(COLOURMAP * colours) Line 2088  ui_create_colourmap(COLOURMAP * colours)
2088                                          xc_cache[colLookup].red = xc_cache[colLookup].green =                                          xc_cache[colLookup].red = xc_cache[colLookup].green =
2089                                                  xc_cache[colLookup].blue = 0;                                                  xc_cache[colLookup].blue = 0;
2090                                          xc_cache[colLookup].flags = 0;                                          xc_cache[colLookup].flags = 0;
2091                                          XQueryColor(display,                                          XQueryColor(g_display,
2092                                                      DefaultColormap(display,                                                      DefaultColormap(g_display,
2093                                                                      DefaultScreen(display)),                                                                      DefaultScreen(g_display)),
2094                                                      &xc_cache[colLookup]);                                                      &xc_cache[colLookup]);
2095                                  }                                  }
2096                                  colLookup = 0;                                  colLookup = 0;
# Line 1222  ui_create_colourmap(COLOURMAP * colours) Line 2131  ui_create_colourmap(COLOURMAP * colours)
2131    
2132                          }                          }
2133    
2134                            map[i] = colour;
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
2135                  }                  }
2136                  return map;                  return map;
2137          }          }
# Line 1233  ui_create_colourmap(COLOURMAP * colours) Line 2140  ui_create_colourmap(COLOURMAP * colours)
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 1242  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;
# Line 1253  ui_create_colourmap(COLOURMAP * colours) Line 2160  ui_create_colourmap(COLOURMAP * colours)
2160  void  void
2161  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
2162  {  {
2163          if (!owncolmap)          if (!g_owncolmap)
2164                  xfree(map);                  xfree(map);
2165          else          else
2166                  XFreeColormap(display, (Colormap) map);                  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                  colmap = map;          {
2174                    if (g_colmap)
2175                            xfree(g_colmap);
2176    
2177                    g_colmap = (uint32 *) map;
2178            }
2179          else          else
2180                  XSetWindowColormap(display, wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2181  }  }
2182    
2183  void  void
# Line 1277  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
# Line 1287  ui_reset_clip(void) Line 2199  ui_reset_clip(void)
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(void)  ui_bell(void)
2209  {  {
2210          XBell(display, 0);          XBell(g_display, 0);
2211  }  }
2212    
2213  void  void
# Line 1307  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 1321  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 1347  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 1355  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 1367  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 1413  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 1428  ui_rect( Line 2379  ui_rect(
2379          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2380  }  }
2381    
2382    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 */  /* warning, this function only draws on wnd or backstore, not both */
2528  void  void
2529  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1438  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_BACKSTORE(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 + glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2564                       y + 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_BACKSTORE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
# Line 1502  ui_draw_text(uint8 font, uint8 flags, in Line 2607  ui_draw_text(uint8 font, uint8 flags, in
2607                  FILL_RECTANGLE_BACKSTORE(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                                          exit(1);                                          for (j = 0; j < length; j++)
2625                                                    fprintf(stderr, "%02x ", text[j]);
2626                                            fprintf(stderr, "\n");
2627                                            i = length = 0;
2628                                            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];
# Line 1552  ui_draw_text(uint8 font, uint8 flags, in Line 2676  ui_draw_text(uint8 font, uint8 flags, in
2676                                  break;                                  break;
2677                  }                  }
2678          }          }
2679          if (ownbackstore)  
2680            XSetFillStyle(g_display, g_gc, FillSolid);
2681    
2682            if (g_ownbackstore)
2683          {          {
2684                  if (boxcx > 1)                  if (boxcx > 1)
2685                          XCopyArea(display, backstore, wnd, gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2686                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2687                  else                  else
2688                          XCopyArea(display, backstore, wnd, gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2689                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2690          }          }
2691  }  }
# Line 1569  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 1593  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.319  
changed lines
  Added in v.1049

  ViewVC Help
Powered by ViewVC 1.1.26