/[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 521 by stargo, Tue Oct 28 09:02:46 2003 UTC revision 1042 by astrand, Tue Jan 24 12:40:24 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- 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"  #include "xproto.h"
30    
31  extern int g_width;  extern int g_width;
32  extern int g_height;  extern int g_height;
33    extern int g_xpos;
34    extern int g_ypos;
35    extern int g_pos;
36  extern BOOL g_sendmotion;  extern BOOL g_sendmotion;
37  extern BOOL g_fullscreen;  extern BOOL g_fullscreen;
38  extern BOOL g_grab_keyboard;  extern BOOL g_grab_keyboard;
39  extern BOOL g_hide_decorations;  extern BOOL g_hide_decorations;
40  extern char g_title[];  extern char g_title[];
41  extern int g_server_bpp;  /* Color depth of the RDP session.
42       As of RDP 5.1, it may be 8, 15, 16 or 24. */
43    extern int g_server_depth;
44  extern int g_win_button_size;  extern int g_win_button_size;
45    
46  Display *g_display;  Display *g_display;
# Line 40  Time g_last_gesturetime; Line 48  Time g_last_gesturetime;
48  static int g_x_socket;  static int g_x_socket;
49  static Screen *g_screen;  static Screen *g_screen;
50  Window g_wnd;  Window g_wnd;
51    extern uint32 g_embed_wnd;
52  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
53  static GC g_gc;  BOOL g_Unobscured;              /* used for screenblt */
54    static GC g_gc = NULL;
55    static GC g_create_bitmap_gc = NULL;
56    static GC g_create_glyph_gc = NULL;
57  static Visual *g_visual;  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;  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;  static int g_bpp;
66  static XIM g_IM;  static XIM g_IM;
67  static XIC g_IC;  static XIC g_IC;
68  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
69  static Cursor g_current_cursor;  static Cursor g_current_cursor;
70  static HCURSOR g_null_cursor;  static HCURSOR g_null_cursor = NULL;
71  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
72  static BOOL g_focused;  static BOOL g_focused;
73  static BOOL g_mouse_in_wnd;  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 g_host_be;  static BOOL g_host_be;
84  static BOOL g_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 g_ownbackstore;  extern BOOL g_ownbackstore;
90  static Pixmap g_backstore;  static Pixmap g_backstore = 0;
91    
92  /* Moving in single app mode */  /* Moving in single app mode */
93  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
94  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
95  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
96    static BOOL g_using_full_workarea = False;
97    
98  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
99  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 78  extern BOOL g_rdpsnd; Line 106  extern BOOL g_rdpsnd;
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 107  PixelColour; Line 135  PixelColour;
135          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_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 g_owncolmap = False;  extern BOOL g_owncolmap;
164  static Colormap g_xcolmap;  static Colormap g_xcolmap;
165  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
166    
167  #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : translate_colour(g_colmap[col]) )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
168  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
169  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
170    
# Line 160  mwm_hide_decorations(void) Line 212  mwm_hide_decorations(void)
212                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
213  }  }
214    
215  static 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;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = (colour & 0xf800) >> 11;  
         rv.red = (rv.red * 0xff) / 0x1f;  
         rv.green = (colour & 0x07e0) >> 5;  
         rv.green = (rv.green * 0xff) / 0x3f;  
         rv.blue = (colour & 0x001f);  
         rv.blue = (rv.blue * 0xff) / 0x1f;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour24(uint32 colour)  
 {  
         PixelColour rv;  
         rv.blue = (colour & 0xff0000) >> 16;  
         rv.green = (colour & 0xff00) >> 8;  
         rv.red = (colour & 0xff);  
         return rv;  
220  }  }
221    
222  static uint32  #define SPLITCOLOUR16(colour, rv) \
223  make_colour16(PixelColour pc)  { \
224  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
225          pc.red = (pc.red * 0x1f) / 0xff;          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
226          pc.green = (pc.green * 0x3f) / 0xff;          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
227          pc.blue = (pc.blue * 0x1f) / 0xff;  } \
         return (pc.red << 11) | (pc.green << 5) | pc.blue;  
 }  
228    
229  static uint32  #define SPLITCOLOUR24(colour, rv) \
230  make_colour24(PixelColour pc)  { \
231  {          rv.blue = (colour & 0xff0000) >> 16; \
232          if (g_xserver_be)          rv.green = (colour & 0x00ff00) >> 8; \
233          {          rv.red = (colour & 0x0000ff); \
                 return pc.red | (pc.green << 8) | (pc.blue << 16);  
         }  
         else  
         {  
                 return (pc.red << 16) | (pc.green << 8) | pc.blue;  
         }  
234  }  }
235    
236  static uint32  #define MAKECOLOUR(pc) \
237  make_colour32(PixelColour pc)          ((pc.red >> g_red_shift_r) << g_red_shift_l) \
238  {                  | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
239          if (g_xserver_be)                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
         {  
                 return pc.red | (pc.green << 8) | (pc.blue << 16);  
         }  
         else  
         {  
                 return (pc.red << 16) | (pc.green << 8) | pc.blue;  
         }  
 }  
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 (g_server_bpp)          PixelColour pc;
257            switch (g_server_depth)
258          {          {
259                  case 15:                  case 15:
260                          switch (g_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 (g_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 (g_bpp)                          SPLITCOLOUR24(colour, pc);
267                          {                          break;
268                                  case 16:                  default:
269                                          colour = make_colour16(split_colour24(colour));                          /* Avoid warning */
270                                          break;                          pc.red = 0;
271                                  case 24:                          pc.green = 0;
272                                          colour = make_colour24(split_colour24(colour));                          pc.blue = 0;
                                         break;  
                                 case 32:  
                                         colour = make_colour32(split_colour24(colour));  
                                         break;  
                         }  
273                          break;                          break;
274          }          }
275          return colour;          return MAKECOLOUR(pc);
276    }
277    
278    /* indent is confused by UNROLL8 */
279    /* *INDENT-OFF* */
280    
281    /* repeat and unroll, similar to bitmap.c */
282    /* potentialy any of the following translate */
283    /* functions can use repeat but just doing */
284    /* the most common ones */
285    
286    #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) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
318  }  }
319    
320  static void  static void
321  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
322  {  {
323          uint16 value;          uint16 value;
324    
325          while (out < end)          if (g_compatible_depth)
326          {          {
327                  value = (uint16) g_colmap[*(data++)];                  /* *INDENT-OFF* */
328                                    REPEAT2
329                  if (g_xserver_be)                  (
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                          *(out++) = value >> 8;                          value = (uint16) g_colmap[*(data++)];
340                          *(out++) = value;                          BOUT16(out, value);
341                  }                  }
342                  else          }
343            else
344            {
345                    while (out < end)
346                  {                  {
347                          *(out++) = value;                          value = (uint16) g_colmap[*(data++)];
348                          *(out++) = value >> 8;                          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 = g_colmap[*(data++)];                  while (out < end)
                   
                 if (g_xserver_be)  
362                  {                  {
363                          *(out++) = value >> 16;                          value = g_colmap[*(data++)];
364                          *(out++) = value >> 8;                          BOUT24(out, value);
                         *(out++) = value;  
365                  }                  }
366                  else          }
367            else
368            {
369                    while (out < end)
370                  {                  {
371                          *(out++) = value;                          value = g_colmap[*(data++)];
372                          *(out++) = value >> 8;                          LOUT24(out, value);
                         *(out++) = value >> 16;  
373                  }                  }
374          }          }
375  }  }
376    
377  static void  static void
378  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
379  {  {
380          uint32 value;          uint32 value;
381    
382          while (out < end)          if (g_compatible_depth)
383          {          {
384                  value = g_colmap[*(data++)];                  /* *INDENT-OFF* */
385                    REPEAT4
386                  if (g_xserver_be)                  (
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                          *(out++) = value >> 24;                          value = g_colmap[*(data++)];
397                          *(out++) = value >> 16;                          BOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
398                  }                  }
399                  else          }
400            else
401            {
402                    while (out < end)
403                  {                  {
404                          *(out++) = value;                          value = g_colmap[*(data++)];
405                          *(out++) = value >> 8;                          LOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
406                  }                  }
407          }          }
408  }  }
409    
 /* todo the remaining translate function might need some big endian check ?? */  
   
410  static void  static void
411  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
412  {  {
413          uint16 pixel;          uint16 pixel;
414          uint16 value;          uint16 value;
415            PixelColour pc;
416    
417          while (out < end)          if (g_xserver_be)
418          {          {
419                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel);  
                 }  
   
                 value = make_colour16(split_colour15(pixel));  
   
                 if (g_xserver_be)  
420                  {                  {
421                          *(out++) = value >> 8;                          pixel = *(data++);
422                          *(out++) = value;                          if (g_host_be)
423                            {
424                                    BSWAP16(pixel);
425                            }
426                            SPLITCOLOUR15(pixel, pc);
427                            value = MAKECOLOUR(pc);
428                            BOUT16(out, value);
429                  }                  }
430                  else          }
431            else
432            {
433                    while (out < end)
434                  {                  {
435                          *(out++) = value;                          pixel = *(data++);
436                          *(out++) = value >> 8;                          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;          uint16 pixel;
452            PixelColour pc;
453    
454          while (out < end)          if (g_compatible_depth)
455          {          {
456                  pixel = *(data++);                  /* *INDENT-OFF* */
457                    REPEAT3
458                  if (g_host_be)                  (
459                  {                          pixel = *(data++);
460                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
461                  }                          *(out++) = pc.blue;
462                            *(out++) = pc.green;
463                  value = make_colour24(split_colour15(pixel));                          *(out++) = pc.red;
464                  if (g_xserver_be)                  )
465                    /* *INDENT-ON* */
466            }
467            else if (g_xserver_be)
468            {
469                    while (out < end)
470                  {                  {
471                          *(out++) = value >> 16;                          pixel = *(data++);
472                          *(out++) = value >> 8;                          if (g_host_be)
473                          *(out++) = value;                          {
474                                    BSWAP16(pixel);
475                            }
476                            SPLITCOLOUR15(pixel, pc);
477                            value = MAKECOLOUR(pc);
478                            BOUT24(out, value);
479                  }                  }
480                  else          }
481            else
482            {
483                    while (out < end)
484                  {                  {
485                          *(out++) = value;                          pixel = *(data++);
486                          *(out++) = value >> 8;                          if (g_host_be)
487                          *(out++) = value >> 16;                          {
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, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
499  {  {
500          uint16 pixel;          uint16 pixel;
501          uint32 value;          uint32 value;
502            PixelColour pc;
503    
504          while (out < end)          if (g_compatible_depth)
505          {          {
506                  pixel = *(data++);                  /* *INDENT-OFF* */
507                    REPEAT4
508                  if (g_host_be)                  (
509                  {                          pixel = *(data++);
510                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
511                  }                          *(out++) = pc.blue;
512                            *(out++) = pc.green;
513                  value = make_colour32(split_colour15(pixel));                          *(out++) = pc.red;
514                            *(out++) = 0;
515                  if (g_xserver_be)                  )
516                    /* *INDENT-ON* */
517            }
518            else if (g_xserver_be)
519            {
520                    while (out < end)
521                  {                  {
522                          *(out++) = value >> 24;                          pixel = *(data++);
523                          *(out++) = value >> 16;                          if (g_host_be)
524                          *(out++) = value >> 8;                          {
525                          *(out++) = value;                                  BSWAP16(pixel);
526                            }
527                            SPLITCOLOUR15(pixel, pc);
528                            value = MAKECOLOUR(pc);
529                            BOUT32(out, value);
530                  }                  }
531                  else          }
532            else
533            {
534                    while (out < end)
535                  {                  {
536                          *(out++) = value;                          pixel = *(data++);
537                          *(out++) = value >> 8;                          if (g_host_be)
538                          *(out++) = value >> 16;                          {
539                          *(out++) = value >> 24;                                  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            uint16 pixel;
552          uint16 value;          uint16 value;
553            PixelColour pc;
554    
555          if (g_xserver_be)          if (g_xserver_be)
556          {          {
557                  while (out < end)                  if (g_host_be)
558                  {                  {
559                          value = *data;                          while (out < end)
560                          BSWAP16(value);                          {
561                          *out = value;                                  pixel = *(data++);
562                          data++;                                  BSWAP16(pixel);
563                          out++;                                  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          else
580          {          {
581                  while (out < end)                  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                          *out = *data;                          while (out < end)
595                          out++;                          {
596                          data++;                                  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;          uint16 pixel;
610            PixelColour pc;
611    
612          while (out < end)          if (g_compatible_depth)
613            {
614                    /* *INDENT-OFF* */
615                    REPEAT3
616                    (
617                            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          {          {
                 pixel = *(data++);  
   
627                  if (g_host_be)                  if (g_host_be)
628                  {                  {
629                          BSWAP16(pixel);                          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
                 value = make_colour24(split_colour16(pixel));  
   
                 if (g_xserver_be)  
639                  {                  {
640                          *(out++) = value >> 16;                          while (out < end)
641                          *(out++) = value >> 8;                          {
642                          *(out++) = value;                                  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                  else
663                  {                  {
664                          *(out++) = value;                          while (out < end)
665                          *(out++) = value >> 8;                          {
666                          *(out++) = value >> 16;                                  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, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
677  {  {
678          uint16 pixel;          uint16 pixel;
679          uint32 value;          uint32 value;
680            PixelColour pc;
681    
682          while (out < end)          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          {          {
                 pixel = *(data++);  
   
698                  if (g_host_be)                  if (g_host_be)
699                  {                  {
700                  BSWAP16(pixel)}                          while (out < end)
701                            {
702                  value = make_colour32(split_colour16(pixel));                                  pixel = *(data++);
703                                    BSWAP16(pixel);
704                  if (g_xserver_be)                                  SPLITCOLOUR16(pixel, pc);
705                                    value = MAKECOLOUR(pc);
706                                    BOUT32(out, value);
707                            }
708                    }
709                    else
710                  {                  {
711                          *(out++) = value >> 24;                          while (out < end)
712                          *(out++) = value >> 16;                          {
713                          *(out++) = value >> 8;                                  pixel = *(data++);
714                          *(out++) = value;                                  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                  else
734                  {                  {
735                          *(out++) = value;                          while (out < end)
736                          *(out++) = value >> 8;                          {
737                          *(out++) = value >> 16;                                  pixel = *(data++);
738                          *(out++) = value >> 24;                                  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, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
748  {  {
749          uint32 pixel = 0;          uint32 pixel = 0;
750          uint16 value;          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                    SPLITCOLOUR24(pixel, pc);
759                  value = (uint16) make_colour16(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
760                  if (g_xserver_be)                  if (g_xserver_be)
761                  {                  {
762                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
763                  }                  }
764                  else                  else
765                  {                  {
766                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
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                  *(out++) = (*(data++));                  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                    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, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
806  {  {
807          while (out < end)          uint32 pixel;
808            uint32 value;
809            PixelColour pc;
810    
811            if (g_compatible_depth)
812          {          {
813                  if (g_xserver_be)                  /* *INDENT-OFF* */
814                  {  #ifdef NEED_ALIGN
815                          *(out++) = 0x00;                  REPEAT4
816                    (
817                          *(out++) = *(data++);                          *(out++) = *(data++);
818                          *(out++) = *(data++);                          *(out++) = *(data++);
819                          *(out++) = *(data++);                          *(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                  else          }
845            else
846            {
847                    while (out < end)
848                  {                  {
849                          *(out++) = *(data++);                          pixel = *(data++) << 16;
850                          *(out++) = *(data++);                          pixel |= *(data++) << 8;
851                          *(out++) = *(data++);                          pixel |= *(data++);
852                          *(out++) = 0x00;                          SPLITCOLOUR24(pixel, pc);
853                            value = MAKECOLOUR(pc);
854                            LOUT32(out, value);
855                  }                  }
856          }          }
857  }  }
# Line 617  translate24to32(uint8 * data, uint8 * ou Line 859  translate24to32(uint8 * data, uint8 * ou
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 * g_bpp / 8;          int size;
863          uint8 *out = (uint8 *) 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 (g_server_bpp)          switch (g_server_depth)
887          {          {
888                  case 24:                  case 24:
889                          switch (g_bpp)                          switch (g_bpp)
# Line 647  translate_image(int width, int height, u Line 909  translate_image(int width, int height, u
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,                                          translate16to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
913                                          break;                                          break;
914                          }                          }
915                          break;                          break;
# Line 712  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          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1010          if (g_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          g_x_socket = ConnectionNumber(g_display);          /* Search for best TrueColor visual */
1020          g_screen = DefaultScreenOfDisplay(g_display);          template.class = TrueColor;
1021          g_visual = DefaultVisualOfScreen(g_screen);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1022          g_depth = DefaultDepthOfScreen(g_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                            /* Prefer formats which have the most colour depth.
1090                               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                    g_owncolmap = False;
1118                    calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1119                    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                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1134                            XCloseDisplay(g_display);
1135                            XFree(pfm);
1136                            return False;
1137                    }
1138    
1139          pfm = XListPixmapFormats(g_display, &i);                  /* we use a colourmap, so the default visual should do */
1140          if (pfm != NULL)                  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                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1149                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1150                  {                  {
1151                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1152    
1153                            if (g_no_translate_image)
1154                          {                          {
1155                                  g_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 (g_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(g_display);  
1195                  return False;                  return False;
1196          }          }
1197    
1198          /* private colour map code only works for 8 bpp */          {
1199          if (g_owncolmap && (g_bpp > 8))                  uint16 endianess_test = 1;
1200                  g_owncolmap = False;                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1201            }
1202    
1203            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 (!select_visual())
1210                    return False;
1211    
1212            if (g_no_translate_image)
1213            {
1214                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1215            }
1216    
1217            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)          if (!g_owncolmap)
1227          {          {
1228                  g_xcolmap = DefaultColormapOfScreen(g_screen);                  g_xcolmap =
1229                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1230                                            AllocNone);
1231                  if (g_depth <= 8)                  if (g_depth <= 8)
1232                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");                          warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1233          }          }
1234    
1235          g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1236            {
1237          if (DoesBackingStore(g_screen) != Always)                  warning("External BackingStore not available. Using internal.\n");
1238                  g_ownbackstore = True;                  g_ownbackstore = True;
1239            }
         test = 1;  
         g_host_be = !(BOOL) (*(uint8 *) (&test));  
         g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);  
1240    
1241          /*          /*
1242           * Determine desktop size           * Determine desktop size
1243           */           */
1244          if (g_width < 0)          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 */                  /* Percent of screen */
1252                    if (-g_width >= 100)
1253                            g_using_full_workarea = True;
1254                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1255                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1256          }          }
# Line 786  ui_init(void) Line 1258  ui_init(void)
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                  {                  {
# Line 799  ui_init(void) Line 1272  ui_init(void)
1272                          g_height = 600;                          g_height = 600;
1273                  }                  }
1274          }          }
         else if (g_fullscreen)  
         {  
                 g_width = WidthOfScreen(g_screen);  
                 g_height = HeightOfScreen(g_screen);  
         }  
1275    
1276          /* make sure width is a multiple of 4 */          /* make sure width is a multiple of 4 */
1277          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1278    
         if (g_ownbackstore)  
         {  
                 g_backstore =  
                         XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,  
                                       g_depth);  
   
                 /* clear to prevent rubbish being exposed at startup */  
                 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));  
                 XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);  
         }  
   
1279          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1280    
1281          xkeymap_init();          xkeymap_init();
# Line 828  ui_init(void) Line 1285  ui_init(void)
1285    
1286          xclip_init();          xclip_init();
1287    
1288          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1289    
1290          return True;          return True;
1291  }  }
# Line 839  ui_deinit(void) Line 1296  ui_deinit(void)
1296          if (g_IM != NULL)          if (g_IM != NULL)
1297                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1298    
1299            if (g_null_cursor != NULL)
1300                    ui_destroy_cursor(g_null_cursor);
1301    
1302          XFreeModifiermap(g_mod_map);          XFreeModifiermap(g_mod_map);
1303    
1304          if (g_ownbackstore)          if (g_ownbackstore)
# Line 849  ui_deinit(void) Line 1309  ui_deinit(void)
1309          g_display = NULL;          g_display = NULL;
1310  }  }
1311    
 #define NULL_POINTER_MASK       "\x80"  
 #define NULL_POINTER_DATA       "\x0\x0\x0"  
           
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 865  ui_create_window(void) Line 1325  ui_create_window(void)
1325          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1326          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1327    
1328            /* Handle -x-y portion of geometry string */
1329            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1330                    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);          attribs.background_pixel = BlackPixelOfScreen(g_screen);
1335            attribs.border_pixel = WhitePixelOfScreen(g_screen);
1336          attribs.backing_store = g_ownbackstore ? NotUseful : Always;          attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1337          attribs.override_redirect = g_fullscreen;          attribs.override_redirect = g_fullscreen;
1338            attribs.colormap = g_xcolmap;
1339    
1340          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1341                                0, CopyFromParent, InputOutput, CopyFromParent,                                wndheight, 0, g_depth, InputOutput, g_visual,
1342                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);                                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            if (g_create_bitmap_gc == NULL)
1349                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1350    
1351            if ((g_ownbackstore) && (g_backstore == 0))
1352            {
1353                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1354    
1355                    /* 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);          XStoreName(g_display, g_wnd, g_title);
1361    
# Line 890  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                    if (g_pos)
1378                            sizehints->flags |= PPosition;
1379                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1380                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1381                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  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 (g_sendmotion)          if (g_sendmotion)
1394                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
# Line 927  ui_create_window(void) Line 1418  ui_create_window(void)
1418                  XMaskEvent(g_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          g_focused = False;          g_focused = False;
1424          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 937  ui_create_window(void) Line 1429  ui_create_window(void)
1429          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1430    
1431          /* create invisible 1x1 cursor to be used as null cursor */          /* create invisible 1x1 cursor to be used as null cursor */
1432          g_null_cursor = ui_create_cursor(0, 0, 1, 1, NULL_POINTER_MASK, NULL_POINTER_DATA);          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  {  {
         ui_destroy_cursor(g_null_cursor);  
           
1474          if (g_IC != NULL)          if (g_IC != NULL)
1475                  XDestroyIC(g_IC);                  XDestroyIC(g_IC);
1476    
# Line 978  xwin_toggle_fullscreen(void) Line 1502  xwin_toggle_fullscreen(void)
1502          }          }
1503  }  }
1504    
1505  /* Process all events in Xlib queue  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 win_button_size is nonzero, enable single app mode */
1522            if (xevent.xbutton.y < g_win_button_size)
1523            {
1524                    /*  Check from right to left: */
1525                    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 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(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1590          {          {
1591                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1592    
# Line 1004  xwin_process_events(void) Line 1596  xwin_process_events(void)
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 == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
# Line 1039  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;  
   
                                 save_remote_modifiers(tr.scancode);  
                                 ensure_remote_modifiers(ev_time, tr);  
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);  
                                 restore_remote_modifiers(ev_time, tr.scancode);  
   
1644                                  break;                                  break;
1645    
1646                          case KeyRelease:                          case KeyRelease:
# Line 1064  xwin_process_events(void) Line 1648  xwin_process_events(void)
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                                  g_last_gesturetime = xevent.xbutton.time;                                  handle_button_event(xevent, False);
                                 button = xkeymap_translate_button(xevent.xbutton.button);  
                                 if (button == 0)  
                                         break;  
   
                                 /* If win_button_size is nonzero, enable single app mode */  
                                 if (xevent.xbutton.y < g_win_button_size)  
                                 {  
                                         /* Stop moving window when button is released, regardless of cursor position */  
                                         if (g_moving_wnd && (xevent.type == ButtonRelease))  
                                                 g_moving_wnd = False;  
   
                                         /*  Check from right to left: */  
   
                                         if (xevent.xbutton.x >= g_width - g_win_button_size)  
                                         {  
                                                 /* The close button, continue */  
                                                 ;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 2)  
                                         {  
                                                 /* The maximize/restore button. Do not send to  
                                                    server.  It might be a good idea to change the  
                                                    cursor or give some other visible indication  
                                                    that rdesktop inhibited this click */  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 3)  
                                         {  
                                                 /* The minimize button. Iconify window. */  
                                                 XIconifyWindow(g_display, g_wnd,  
                                                                DefaultScreen(g_display));  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x <= g_win_button_size)  
                                         {  
                                                 /* The system menu. Ignore. */  
                                                 break;  
                                         }  
                                         else  
                                         {  
                                                 /* The title bar. */  
                                                 if ((xevent.type == ButtonPress) && !g_fullscreen  
                                                     && g_hide_decorations)  
                                                 {  
                                                         g_moving_wnd = True;  
                                                         g_move_x_offset = xevent.xbutton.x;  
                                                         g_move_y_offset = xevent.xbutton.y;  
                                                 }  
                                                 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:
# Line 1165  xwin_process_events(void) Line 1687  xwin_process_events(void)
1687                                  if (xevent.xfocus.mode == NotifyGrab)                                  if (xevent.xfocus.mode == NotifyGrab)
1688                                          break;                                          break;
1689                                  g_focused = True;                                  g_focused = True;
1690                                  XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,                                  reset_modifier_keys();
                                               &dummy, &dummy, &state);  
                                 reset_modifier_keys(state);  
1691                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
1692                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
1693                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
# Line 1237  xwin_process_events(void) Line 1757  xwin_process_events(void)
1757                          case PropertyNotify:                          case PropertyNotify:
1758                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1759                                  break;                                  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 1247  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 > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;          int n;
1777          fd_set rfds, wfds;          fd_set rfds, wfds;
1778            struct timeval tv;
1779            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 */
# Line 1267  ui_select(int rdp_socket) Line 1796  ui_select(int rdp_socket)
1796                  if (g_dsp_busy)                  if (g_dsp_busy)
1797                  {                  {
1798                          FD_SET(g_dsp_fd, &wfds);                          FD_SET(g_dsp_fd, &wfds);
1799                          n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;                          n = (g_dsp_fd > n) ? g_dsp_fd : n;
1800                  }                  }
1801  #endif  #endif
1802                    /* default timeout */
1803                    tv.tv_sec = 60;
1804                    tv.tv_usec = 0;
1805    
1806                  switch (select(n, &rfds, &wfds, NULL, NULL))                  /* add redirection handles */
1807                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1808    
1809                    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    
# Line 1304  ui_create_bitmap(int width, int height, Line 1846  ui_create_bitmap(int width, int height,
1846          uint8 *tdata;          uint8 *tdata;
1847          int bitmap_pad;          int bitmap_pad;
1848    
1849          if (g_server_bpp == 8)          if (g_server_depth == 8)
1850          {          {
1851                  bitmap_pad = 8;                  bitmap_pad = 8;
1852          }          }
# Line 1321  ui_create_bitmap(int width, int height, Line 1863  ui_create_bitmap(int width, int height,
1863          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1864                               (char *) tdata, width, height, bitmap_pad, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1865    
1866          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1867    
1868          XFree(image);          XFree(image);
1869          if (!g_owncolmap)          if (tdata != data)
1870                  xfree(tdata);                  xfree(tdata);
1871          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1872  }  }
# Line 1336  ui_paint_bitmap(int x, int y, int cx, in Line 1878  ui_paint_bitmap(int x, int y, int cx, in
1878          uint8 *tdata;          uint8 *tdata;
1879          int bitmap_pad;          int bitmap_pad;
1880    
1881          if (g_server_bpp == 8)          if (g_server_depth == 8)
1882          {          {
1883                  bitmap_pad = 8;                  bitmap_pad = 8;
1884          }          }
# Line 1363  ui_paint_bitmap(int x, int y, int cx, in Line 1905  ui_paint_bitmap(int x, int y, int cx, in
1905          }          }
1906    
1907          XFree(image);          XFree(image);
1908          if (!g_owncolmap)          if (tdata != data)
1909                  xfree(tdata);                  xfree(tdata);
1910  }  }
1911    
# Line 1379  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(g_display, g_wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1928          gc = XCreateGC(g_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(g_display, g_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);
# Line 1392  ui_create_glyph(int width, int height, u Line 1934  ui_create_glyph(int width, int height, u
1934          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1935          XInitImage(image);          XInitImage(image);
1936    
1937          XPutImage(g_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(g_display, gc);  
1940          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1941  }  }
1942    
# Line 1576  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 1689  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;                          break;
2233    
2234                  case 2: /* Hatch */                  case 2: /* Hatch */
# Line 1700  ui_patblt(uint8 opcode, Line 2239  ui_patblt(uint8 opcode,
2239                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2240                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2241                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2242                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2243                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2244                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2245                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1710  ui_patblt(uint8 opcode, Line 2249  ui_patblt(uint8 opcode,
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(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2255                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2256                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2257                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
                         FILL_RECTANGLE(x, y, cx, cy);  
   
2258                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2259                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2260                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1729  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 1737  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);
         XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
2279          if (g_ownbackstore)          if (g_ownbackstore)
2280                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);          {
2281                    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 1810  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 1834  ui_draw_glyph(int mixmode, Line 2534  ui_draw_glyph(int mixmode,
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 1884  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 1934  ui_draw_text(uint8 font, uint8 flags, in Line 2662  ui_draw_text(uint8 font, uint8 flags, in
2662                                  break;                                  break;
2663                  }                  }
2664          }          }
2665    
2666            XSetFillStyle(g_display, g_gc, FillSolid);
2667    
2668          if (g_ownbackstore)          if (g_ownbackstore)
2669          {          {
2670                  if (boxcx > 1)                  if (boxcx > 1)
# Line 1995  ui_desktop_restore(uint32 offset, int x, Line 2726  ui_desktop_restore(uint32 offset, int x,
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.521  
changed lines
  Added in v.1042

  ViewVC Help
Powered by ViewVC 1.1.26