/[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 867 by stargo, Wed Mar 23 12:25:54 2005 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 79  static Pixmap g_backstore = 0; Line 93  static Pixmap g_backstore = 0;
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 91  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 137  PixelColour; Line 152  PixelColour;
152                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
153                          break; \                          break; \
154                  case 1: /* Filled */ \                  case 1: /* Filled */ \
155                          XFillArc(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, \                          XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
                                  cx, cy, 0, 360*64); \  
156                          if (g_ownbackstore) \                          if (g_ownbackstore) \
157                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); \                                  XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
158                          break; \                          break; \
159          } \          } \
160  }  }
# 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 802  translate24to32(const uint8 * data, uint Line 822  translate24to32(const uint8 * data, uint
822  #else  #else
823                  REPEAT4                  REPEAT4
824                  (                  (
825                          *((uint32 *) out) = *((uint32 *) data);                   /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
826                          out += 4;                   *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
827                          data += 3;                   out += 4;
828                     data += 3;
829                  )                  )
830  #endif  #endif
831                  /* *INDENT-ON* */                  /* *INDENT-ON* */
# Line 842  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 859  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 957  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                            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          nvisuals--;                          /* Only care for visuals, for whose BPPs (not depths!)
1072          while (nvisuals >= 0)                             we have a translateXtoY function. */
1073          {                          BOOL can_translate_to_bpp = False;
1074                  if ((vmatches + nvisuals)->depth > g_depth)                          int j;
1075                  {                          for (j = 0; j < pixmap_formats_count; ++j)
1076                          g_depth = (vmatches + nvisuals)->depth;                          {
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 1091  ui_init(void) Line 1249  ui_init(void)
1249          else if (g_width < 0)          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 1098  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 1124  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 1227  ui_create_window(void) Line 1388  ui_create_window(void)
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 1341  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            int events = 0;
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 1364  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:                          case VisibilityNotify:
# Line 1402  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 1427  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 1598  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 1681  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 1713  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 2438  ui_draw_text(uint8 font, uint8 flags, ui Line 2603  ui_draw_text(uint8 font, uint8 flags, ui
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];

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

  ViewVC Help
Powered by ViewVC 1.1.26