/[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 1041 by astrand, Tue Jan 24 12:25:49 2006 UTC revision 1042 by astrand, Tue Jan 24 12:40:24 2006 UTC
# Line 38  extern BOOL g_fullscreen; Line 38  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 53  static GC g_gc = NULL; Line 55  static GC g_gc = NULL;
55  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
56  static GC g_create_glyph_gc = NULL;  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;
# Line 63  static HCURSOR g_null_cursor = NULL; Line 71  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  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* 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;
# Line 150  extern BOOL g_owncolmap; Line 164  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 : 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 240  static uint32 Line 254  static uint32
254  translate_colour(uint32 colour)  translate_colour(uint32 colour)
255  {  {
256          PixelColour pc;          PixelColour pc;
257          switch (g_server_bpp)          switch (g_server_depth)
258          {          {
259                  case 15:                  case 15:
260                          SPLITCOLOUR15(colour, pc);                          SPLITCOLOUR15(colour, pc);
# Line 251  translate_colour(uint32 colour) Line 265  translate_colour(uint32 colour)
265                  case 24:                  case 24:
266                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
267                          break;                          break;
268                    default:
269                            /* Avoid warning */
270                            pc.red = 0;
271                            pc.green = 0;
272                            pc.blue = 0;
273                            break;
274          }          }
275          return MAKECOLOUR(pc);          return MAKECOLOUR(pc);
276  }  }
# Line 302  translate8to16(const uint8 * data, uint8 Line 322  translate8to16(const uint8 * data, uint8
322  {  {
323          uint16 value;          uint16 value;
324    
325          if (g_arch_match)          if (g_compatible_depth)
326          {          {
327                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
328                  REPEAT2                  REPEAT2
# Line 336  translate8to24(const uint8 * data, uint8 Line 356  translate8to24(const uint8 * data, uint8
356  {  {
357          uint32 value;          uint32 value;
358    
359          if (g_xserver_be)          if (g_compatible_depth)
360          {          {
361                  while (out < end)                  while (out < end)
362                  {                  {
# Line 359  translate8to32(const uint8 * data, uint8 Line 379  translate8to32(const uint8 * data, uint8
379  {  {
380          uint32 value;          uint32 value;
381    
382          if (g_arch_match)          if (g_compatible_depth)
383          {          {
384                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
385                  REPEAT4                  REPEAT4
# Line 431  translate15to24(const uint16 * data, uin Line 451  translate15to24(const uint16 * data, uin
451          uint16 pixel;          uint16 pixel;
452          PixelColour pc;          PixelColour pc;
453    
454          if (g_arch_match)          if (g_compatible_depth)
455          {          {
456                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
457                  REPEAT3                  REPEAT3
# Line 481  translate15to32(const uint16 * data, uin Line 501  translate15to32(const uint16 * data, uin
501          uint32 value;          uint32 value;
502          PixelColour pc;          PixelColour pc;
503    
504          if (g_arch_match)          if (g_compatible_depth)
505          {          {
506                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
507                  REPEAT4                  REPEAT4
# Line 589  translate16to24(const uint16 * data, uin Line 609  translate16to24(const uint16 * data, uin
609          uint16 pixel;          uint16 pixel;
610          PixelColour pc;          PixelColour pc;
611    
612          if (g_arch_match)          if (g_compatible_depth)
613          {          {
614                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
615                  REPEAT3                  REPEAT3
# Line 659  translate16to32(const uint16 * data, uin Line 679  translate16to32(const uint16 * data, uin
679          uint32 value;          uint32 value;
680          PixelColour pc;          PixelColour pc;
681    
682          if (g_arch_match)          if (g_compatible_depth)
683          {          {
684                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
685                  REPEAT4                  REPEAT4
# Line 788  translate24to32(const uint8 * data, uint Line 808  translate24to32(const uint8 * data, uint
808          uint32 value;          uint32 value;
809          PixelColour pc;          PixelColour pc;
810    
811          if (g_arch_match)          if (g_compatible_depth)
812          {          {
813                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
814  #ifdef NEED_ALIGN  #ifdef NEED_ALIGN
# Line 843  translate_image(int width, int height, u Line 863  translate_image(int width, int height, u
863          uint8 *out;          uint8 *out;
864          uint8 *end;          uint8 *end;
865    
866          /* if server and xserver bpp match, */          /*
867          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
868          /* just return data */             and arch(endian) matches, no need to translate:
869          if (g_arch_match)             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_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
877                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
878                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
                         return data;  
                 if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)  
879                          return data;                          return data;
880          }          }
881    
# Line 860  translate_image(int width, int height, u Line 883  translate_image(int width, int height, u
883          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
884          end = out + size;          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 958  calculate_shifts(uint32 mask, int *shift Line 981  calculate_shifts(uint32 mask, int *shift
981          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
982  }  }
983    
984  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
985  ui_init(void)     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  {  {
         XVisualInfo vi;  
1002          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1003          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1004          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1005          XVisualInfo template;          XVisualInfo template;
1006          Bool TrueColorVisual = False;          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          screen_num = DefaultScreen(g_display);          /* Search for best TrueColor visual */
         g_x_socket = ConnectionNumber(g_display);  
         g_screen = ScreenOfDisplay(g_display, screen_num);  
         g_depth = DefaultDepthOfScreen(g_screen);  
   
         /* Search for best TrueColor depth */  
1020          template.class = TrueColor;          template.class = TrueColor;
1021          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1022            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          nvisuals--;                          if (visual_info->depth > 24)
1063          while (nvisuals >= 0)                          {
1064          {                                  /* Avoid 32-bit visuals and likes like the plague.
1065                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1066                  {                                     (e.g. nvidia's Composite 32-bit visual).
1067                          g_depth = (vmatches + nvisuals)->depth;                                     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                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1113          }          }
1114    
1115          test = 1;          if (g_visual != NULL)
         g_host_be = !(BOOL) (*(uint8 *) (&test));  
         g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);  
   
         if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))  
1116          {          {
1117                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1118                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1119                  g_depth = DefaultDepthOfScreen(g_screen);                  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);
                 /* Do not allocate colours on a TrueColor visual */  
                 if (g_visual->class == TrueColor)  
                 {  
                         g_owncolmap = False;  
                 }  
1121          }          }
1122          else          else
1123          {          {
1124                  /* need a truecolour visual */                  template.class = PseudoColor;
1125                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1126                  {                  template.colormap_size = 256;
1127                          error("The display does not support true colour - high colour support unavailable.\n");                  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;                          return False;
1137                  }                  }
1138    
1139                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1140                  g_owncolmap = False;                  g_owncolmap = True;
1141                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1142                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
1143                  calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);          }
1144    
1145                  /* if RGB video and everything is little endian */          g_bpp = 0;
1146                  if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&          for (i = 0; i < pixmap_formats_count; ++i)
1147                      !g_xserver_be && !g_host_be)          {
1148                    XPixmapFormatValues *pf = &pfm[i];
1149                    if (pf->depth == g_depth)
1150                  {                  {
1151                          if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&                          g_bpp = pf->bits_per_pixel;
1152                                                g_blue_shift_l == 0))  
1153                            if (g_no_translate_image)
1154                          {                          {
1155                                  g_arch_match = True;                                  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                  if (g_arch_match)                          /* Pixmap formats list is a depth-to-bpp mapping --
1176                  {                             there's just a single entry for every depth,
1177                          DEBUG(("Architectures match, enabling little endian optimisations.\n"));                             so we can safely break here */
1178                            break;
1179                  }                  }
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          pfm = XListPixmapFormats(g_display, &i);          g_display = XOpenDisplay(NULL);
1192          if (pfm != NULL)          if (g_display == NULL)
1193          {          {
1194                  /* Use maximum bpp for this depth - this is generally                  error("Failed to open display: %s\n", XDisplayName(NULL));
1195                     desirable, e.g. 24 bits->32 bits. */                  return False;
                 while (i--)  
                 {  
                         if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))  
                         {  
                                 g_bpp = pfm[i].bits_per_pixel;  
                         }  
                 }  
                 XFree(pfm);  
1196          }          }
1197    
         if (g_bpp < 8)  
1198          {          {
1199                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1200                  XCloseDisplay(g_display);                  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;                  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 =                  g_xcolmap =
1229                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1230                                          AllocNone);                                          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          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1236          {          {
1237                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1238                  g_ownbackstore = True;                  g_ownbackstore = True;
1239          }          }
1240    
# Line 1128  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 1689  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 1721  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          }          }

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

  ViewVC Help
Powered by ViewVC 1.1.26