/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

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

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

Legend:
Removed from v.316  
changed lines
  Added in v.1042

  ViewVC Help
Powered by ViewVC 1.1.26