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

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

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

sourceforge.net/trunk/rdesktop/xwin.c revision 800 by stargo, Thu Nov 18 11:18:49 2004 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1118 by astrand, Tue Mar 14 13:56:50 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 32  extern int g_width; Line 32  extern int g_width;
32  extern int g_height;  extern int g_height;
33  extern int g_xpos;  extern int g_xpos;
34  extern int g_ypos;  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 45  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    
52    /* SeamlessRDP support */
53    typedef struct _seamless_window
54    {
55            Window wnd;
56            unsigned long id;
57            int xoffset, yoffset;
58            int width, height;
59            unsigned int state;     /* normal/minimized/maximized */
60            struct _seamless_window *next;
61    } seamless_window;
62    static seamless_window *g_seamless_windows = NULL;
63    extern BOOL g_seamless_rdp;
64    
65  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
66  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
67  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
68  static GC g_gc = NULL;  static GC g_gc = NULL;
69  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
70  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
71    static XRectangle g_clip_rectangle;
72  static Visual *g_visual;  static Visual *g_visual;
73    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
74       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
75       as far as we're concerned. */
76  static int g_depth;  static int g_depth;
77    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
78       This may be larger than g_depth, in which case some of the bits would
79       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
80  static int g_bpp;  static int g_bpp;
81  static XIM g_IM;  static XIM g_IM;
82  static XIC g_IC;  static XIC g_IC;
# Line 60  static XModifierKeymap *g_mod_map; Line 84  static XModifierKeymap *g_mod_map;
84  static Cursor g_current_cursor;  static Cursor g_current_cursor;
85  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
86  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
87    extern Atom g_net_wm_state_atom;
88  static BOOL g_focused;  static BOOL g_focused;
89  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
90  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* Indicates that:
91       1) visual has 15, 16 or 24 depth and the same color channel masks
92          as its RDP equivalent (implies X server is LE),
93       2) host is LE
94       This will trigger an optimization whose real value is questionable.
95    */
96    static BOOL g_compatible_arch;
97    /* Indicates whether RDP's bitmaps and our XImages have the same
98       binary format. If so, we can avoid an expensive translation.
99       Note that this can be true when g_compatible_arch is false,
100       e.g.:
101      
102         RDP(LE) <-> host(BE) <-> X-Server(LE)
103        
104       ('host' is the machine running rdesktop; the host simply memcpy's
105        so its endianess doesn't matter)
106     */
107    static BOOL g_no_translate_image = False;
108    
109  /* endianness */  /* endianness */
110  static BOOL g_host_be;  static BOOL g_host_be;
# Line 78  static Pixmap g_backstore = 0; Line 120  static Pixmap g_backstore = 0;
120  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
121  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
122  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
123    static BOOL g_using_full_workarea = False;
124    
125  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
126  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 90  extern BOOL g_rdpsnd; Line 133  extern BOOL g_rdpsnd;
133  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
134  typedef struct  typedef struct
135  {  {
136          uint32 flags;          unsigned long flags;
137          uint32 functions;          unsigned long functions;
138          uint32 decorations;          unsigned long decorations;
139          sint32 inputMode;          long inputMode;
140          uint32 status;          unsigned long status;
141  }  }
142  PropMotifWmHints;  PropMotifWmHints;
143    
# Line 106  typedef struct Line 149  typedef struct
149  }  }
150  PixelColour;  PixelColour;
151    
152    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
153            do { \
154                    seamless_window *sw; \
155                    XRectangle rect; \
156                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
157                        rect.x = g_clip_rectangle.x - sw->xoffset; \
158                        rect.y = g_clip_rectangle.y - sw->yoffset; \
159                        rect.width = g_clip_rectangle.width; \
160                        rect.height = g_clip_rectangle.height; \
161                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
162                        func args; \
163                    } \
164                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
165            } while (0)
166    
167    static void
168    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
169    {
170            points[0].x -= xoffset;
171            points[0].y -= yoffset;
172            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
173            points[0].x += xoffset;
174            points[0].y += yoffset;
175    }
176    
177    static void
178    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
179    {
180            points[0].x -= xoffset;
181            points[0].y -= yoffset;
182            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
183            points[0].x += xoffset;
184            points[0].y += yoffset;
185    }
186    
187  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
188  { \  { \
189          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
190            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
191          if (g_ownbackstore) \          if (g_ownbackstore) \
192                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
193  }  }
# Line 119  PixelColour; Line 197  PixelColour;
197          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); \
198  }  }
199    
200    #define FILL_POLYGON(p,np)\
201    { \
202            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
203            if (g_ownbackstore) \
204                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
205            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
206    }
207    
208    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
209    { \
210            switch (m) \
211            { \
212                    case 0: /* Outline */ \
213                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
214                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
215                            if (g_ownbackstore) \
216                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
217                            break; \
218                    case 1: /* Filled */ \
219                            XFillArc(g_display, g_wnd, g_gc, x, y, \
220                                     cx, cy, 0, 360*64); \
221                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc, x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \
222                            if (g_ownbackstore) \
223                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
224                            break; \
225            } \
226    }
227    
228  /* colour maps */  /* colour maps */
229  extern BOOL g_owncolmap;  extern BOOL g_owncolmap;
230  static Colormap g_xcolmap;  static Colormap g_xcolmap;
231  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
232    
233  #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] )
234  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
235  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
236    
# Line 150  static int rop2_map[] = { Line 256  static int rop2_map[] = {
256  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
257  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
258    
259    static seamless_window *
260    seamless_get_window_by_id(unsigned long id)
261    {
262            seamless_window *sw;
263            for (sw = g_seamless_windows; sw; sw = sw->next)
264            {
265                    if (sw->id == id)
266                            return sw;
267            }
268            return NULL;
269    }
270    
271    
272    static seamless_window *
273    seamless_get_window_by_wnd(Window wnd)
274    {
275            seamless_window *sw;
276            for (sw = g_seamless_windows; sw; sw = sw->next)
277            {
278                    if (sw->wnd == wnd)
279                            return sw;
280            }
281            return NULL;
282    }
283    
284    
285  static void  static void
286  mwm_hide_decorations(void)  seamless_remove_window(seamless_window * win)
287    {
288            seamless_window *sw, **prevnext = &g_seamless_windows;
289            for (sw = g_seamless_windows; sw; sw = sw->next)
290            {
291                    if (sw == win)
292                    {
293                            *prevnext = sw->next;
294                            xfree(sw);
295                            return;
296                    }
297                    prevnext = &sw->next;
298            }
299            return;
300    }
301    
302    
303    static void
304    mwm_hide_decorations(Window wnd)
305  {  {
306          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
307          Atom hintsatom;          Atom hintsatom;
# Line 168  mwm_hide_decorations(void) Line 318  mwm_hide_decorations(void)
318                  return;                  return;
319          }          }
320    
321          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
322                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
323    
324  }  }
325    
326  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
327  split_colour15(uint32 colour)  { \
328  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
329          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
330          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7);          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
         rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7);  
         rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);  
         return rv;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7);  
         rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3);  
         rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);  
         return rv;  
 }  
   
 static PixelColour  
 split_colour24(uint32 colour)  
 {  
         PixelColour rv;  
         rv.blue = (colour & 0xff0000) >> 16;  
         rv.green = (colour & 0x00ff00) >> 8;  
         rv.red = (colour & 0x0000ff);  
         return rv;  
331  }  }
332    
333  static uint32  #define SPLITCOLOUR16(colour, rv) \
334  make_colour(PixelColour pc)  { \
335  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
336          return (((pc.red >> g_red_shift_r) << g_red_shift_l)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
337                  | ((pc.green >> g_green_shift_r) << g_green_shift_l)          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
338                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));  } \
339    
340    #define SPLITCOLOUR24(colour, rv) \
341    { \
342            rv.blue = (colour & 0xff0000) >> 16; \
343            rv.green = (colour & 0x00ff00) >> 8; \
344            rv.red = (colour & 0x0000ff); \
345  }  }
346    
347    #define MAKECOLOUR(pc) \
348            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
349                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
350                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
351    
352  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
353  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
354  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
355                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
356    
357    /* The following macros output the same octet sequences
358       on both BE and LE hosts: */
359    
360    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
361    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
362    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
363    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
364    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
365    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
366    
367  static uint32  static uint32
368  translate_colour(uint32 colour)  translate_colour(uint32 colour)
369  {  {
370          PixelColour pc;          PixelColour pc;
371          switch (g_server_bpp)          switch (g_server_depth)
372          {          {
373                  case 15:                  case 15:
374                          pc = split_colour15(colour);                          SPLITCOLOUR15(colour, pc);
375                          break;                          break;
376                  case 16:                  case 16:
377                          pc = split_colour16(colour);                          SPLITCOLOUR16(colour, pc);
378                          break;                          break;
379                  case 24:                  case 24:
380                          pc = split_colour24(colour);                          SPLITCOLOUR24(colour, pc);
381                            break;
382                    default:
383                            /* Avoid warning */
384                            pc.red = 0;
385                            pc.green = 0;
386                            pc.blue = 0;
387                          break;                          break;
388          }          }
389          return make_colour(pc);          return MAKECOLOUR(pc);
390  }  }
391    
392  /* indent is confused by UNROLL8 */  /* indent is confused by UNROLL8 */
# Line 251  translate_colour(uint32 colour) Line 406  translate_colour(uint32 colour)
406          while (out < end) \          while (out < end) \
407                  { stm } \                  { stm } \
408  }  }
409    /* 3 byte output repeat */
410    #define REPEAT3(stm) \
411    { \
412            while (out <= end - 8 * 3) \
413                    UNROLL8(stm) \
414            while (out < end) \
415                    { stm } \
416    }
417  /* 4 byte output repeat */  /* 4 byte output repeat */
418  #define REPEAT4(stm) \  #define REPEAT4(stm) \
419  { \  { \
# Line 259  translate_colour(uint32 colour) Line 422  translate_colour(uint32 colour)
422          while (out < end) \          while (out < end) \
423                  { stm } \                  { stm } \
424  }  }
425    /* *INDENT-ON* */
426    
427  static void  static void
428  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
429  {  {
430          while (out < end)          while (out < end)
431                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
432  }  }
433    
434  static void  static void
435  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
436  {  {
437          uint16 value;          uint16 value;
438    
439          if (g_arch_match)          if (g_compatible_arch)
440          {          {
441                    /* *INDENT-OFF* */
442                  REPEAT2                  REPEAT2
443                  (                  (
444                          *((uint16 *) out) = g_colmap[*(data++)];                          *((uint16 *) out) = g_colmap[*(data++)];
445                          out += 2;                          out += 2;
446                  )                  )
447                    /* *INDENT-ON* */
448          }          }
449          else if (g_xserver_be)          else if (g_xserver_be)
450          {          {
451                  while (out < end)                  while (out < end)
452                  {                  {
453                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
454                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
455                  }                  }
456          }          }
457          else          else
# Line 294  translate8to16(uint8 * data, uint8 * out Line 459  translate8to16(uint8 * data, uint8 * out
459                  while (out < end)                  while (out < end)
460                  {                  {
461                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
462                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
463                  }                  }
464          }          }
465  }  }
466    
467  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
468  static void  static void
469  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
470  {  {
471          uint32 value;          uint32 value;
472    
473          if (g_xserver_be)          if (g_compatible_arch)
474          {          {
475                  while (out < end)                  while (out < end)
476                  {                  {
477                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
478                          *(out++) = value >> 16;                          BOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
479                  }                  }
480          }          }
481          else          else
# Line 321  translate8to24(uint8 * data, uint8 * out Line 483  translate8to24(uint8 * data, uint8 * out
483                  while (out < end)                  while (out < end)
484                  {                  {
485                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
486                          *(out++) = value;                          LOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
487                  }                  }
488          }          }
489  }  }
490    
491  static void  static void
492  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
493  {  {
494          uint32 value;          uint32 value;
495    
496          if (g_arch_match)          if (g_compatible_arch)
497          {          {
498                    /* *INDENT-OFF* */
499                  REPEAT4                  REPEAT4
500                  (                  (
501                          *((uint32 *) out) = g_colmap[*(data++)];                          *((uint32 *) out) = g_colmap[*(data++)];
502                          out += 4;                          out += 4;
503                  )                  )
504                    /* *INDENT-ON* */
505          }          }
506          else if (g_xserver_be)          else if (g_xserver_be)
507          {          {
508                  while (out < end)                  while (out < end)
509                  {                  {
510                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
511                          *(out++) = value >> 24;                          BOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 8;  
                         *(out++) = value;  
512                  }                  }
513          }          }
514          else          else
# Line 357  translate8to32(uint8 * data, uint8 * out Line 516  translate8to32(uint8 * data, uint8 * out
516                  while (out < end)                  while (out < end)
517                  {                  {
518                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
519                          *(out++) = value;                          LOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
520                  }                  }
521          }          }
522  }  }
523    
 /* *INDENT-ON* */  
   
524  static void  static void
525  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
526  {  {
527          uint16 pixel;          uint16 pixel;
528          uint16 value;          uint16 value;
529            PixelColour pc;
530    
531          while (out < end)          if (g_xserver_be)
532          {          {
533                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel);  
                 }  
   
                 value = make_colour(split_colour15(pixel));  
   
                 if (g_xserver_be)  
534                  {                  {
535                          *(out++) = value >> 8;                          pixel = *(data++);
536                          *(out++) = value;                          if (g_host_be)
537                            {
538                                    BSWAP16(pixel);
539                            }
540                            SPLITCOLOUR15(pixel, pc);
541                            value = MAKECOLOUR(pc);
542                            BOUT16(out, value);
543                  }                  }
544                  else          }
545            else
546            {
547                    while (out < end)
548                  {                  {
549                          *(out++) = value;                          pixel = *(data++);
550                          *(out++) = value >> 8;                          if (g_host_be)
551                            {
552                                    BSWAP16(pixel);
553                            }
554                            SPLITCOLOUR15(pixel, pc);
555                            value = MAKECOLOUR(pc);
556                            LOUT16(out, value);
557                  }                  }
558          }          }
559  }  }
560    
561  static void  static void
562  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
563  {  {
564          uint32 value;          uint32 value;
565          uint16 pixel;          uint16 pixel;
566            PixelColour pc;
567    
568          while (out < end)          if (g_compatible_arch)
569          {          {
570                  pixel = *(data++);                  /* *INDENT-OFF* */
571                    REPEAT3
572                  if (g_host_be)                  (
573                  {                          pixel = *(data++);
574                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
575                  }                          *(out++) = pc.blue;
576                            *(out++) = pc.green;
577                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
578                  if (g_xserver_be)                  )
579                    /* *INDENT-ON* */
580            }
581            else if (g_xserver_be)
582            {
583                    while (out < end)
584                  {                  {
585                          *(out++) = value >> 16;                          pixel = *(data++);
586                          *(out++) = value >> 8;                          if (g_host_be)
587                          *(out++) = value;                          {
588                                    BSWAP16(pixel);
589                            }
590                            SPLITCOLOUR15(pixel, pc);
591                            value = MAKECOLOUR(pc);
592                            BOUT24(out, value);
593                  }                  }
594                  else          }
595            else
596            {
597                    while (out < end)
598                  {                  {
599                          *(out++) = value;                          pixel = *(data++);
600                          *(out++) = value >> 8;                          if (g_host_be)
601                          *(out++) = value >> 16;                          {
602                                    BSWAP16(pixel);
603                            }
604                            SPLITCOLOUR15(pixel, pc);
605                            value = MAKECOLOUR(pc);
606                            LOUT24(out, value);
607                  }                  }
608          }          }
609  }  }
610    
611  static void  static void
612  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
613  {  {
614          uint16 pixel;          uint16 pixel;
615          uint32 value;          uint32 value;
616            PixelColour pc;
617    
618          while (out < end)          if (g_compatible_arch)
619          {          {
620                  pixel = *(data++);                  /* *INDENT-OFF* */
621                    REPEAT4
622                  if (g_host_be)                  (
623                  {                          pixel = *(data++);
624                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
625                  }                          *(out++) = pc.blue;
626                            *(out++) = pc.green;
627                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
628                            *(out++) = 0;
629                  if (g_xserver_be)                  )
630                    /* *INDENT-ON* */
631            }
632            else if (g_xserver_be)
633            {
634                    while (out < end)
635                  {                  {
636                          *(out++) = value >> 24;                          pixel = *(data++);
637                          *(out++) = value >> 16;                          if (g_host_be)
638                          *(out++) = value >> 8;                          {
639                          *(out++) = value;                                  BSWAP16(pixel);
640                            }
641                            SPLITCOLOUR15(pixel, pc);
642                            value = MAKECOLOUR(pc);
643                            BOUT32(out, value);
644                  }                  }
645                  else          }
646            else
647            {
648                    while (out < end)
649                  {                  {
650                          *(out++) = value;                          pixel = *(data++);
651                          *(out++) = value >> 8;                          if (g_host_be)
652                          *(out++) = value >> 16;                          {
653                          *(out++) = value >> 24;                                  BSWAP16(pixel);
654                            }
655                            SPLITCOLOUR15(pixel, pc);
656                            value = MAKECOLOUR(pc);
657                            LOUT32(out, value);
658                  }                  }
659          }          }
660  }  }
661    
662  static void  static void
663  translate16to16(uint16 * data, uint8 * out, uint8 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
664  {  {
665          uint16 pixel;          uint16 pixel;
666          uint16 value;          uint16 value;
667            PixelColour pc;
668    
669          while (out < end)          if (g_xserver_be)
670          {          {
                 pixel = *(data++);  
   
671                  if (g_host_be)                  if (g_host_be)
672                  {                  {
673                          BSWAP16(pixel);                          while (out < end)
674                            {
675                                    pixel = *(data++);
676                                    BSWAP16(pixel);
677                                    SPLITCOLOUR16(pixel, pc);
678                                    value = MAKECOLOUR(pc);
679                                    BOUT16(out, value);
680                            }
681                  }                  }
682                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
683                  {                  {
684                          *(out++) = value >> 8;                          while (out < end)
685                          *(out++) = value;                          {
686                                    pixel = *(data++);
687                                    SPLITCOLOUR16(pixel, pc);
688                                    value = MAKECOLOUR(pc);
689                                    BOUT16(out, value);
690                            }
691                    }
692            }
693            else
694            {
695                    if (g_host_be)
696                    {
697                            while (out < end)
698                            {
699                                    pixel = *(data++);
700                                    BSWAP16(pixel);
701                                    SPLITCOLOUR16(pixel, pc);
702                                    value = MAKECOLOUR(pc);
703                                    LOUT16(out, value);
704                            }
705                  }                  }
706                  else                  else
707                  {                  {
708                          *(out++) = value;                          while (out < end)
709                          *(out++) = value >> 8;                          {
710                                    pixel = *(data++);
711                                    SPLITCOLOUR16(pixel, pc);
712                                    value = MAKECOLOUR(pc);
713                                    LOUT16(out, value);
714                            }
715                  }                  }
716          }          }
717  }  }
718    
719  static void  static void
720  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
721  {  {
722          uint32 value;          uint32 value;
723          uint16 pixel;          uint16 pixel;
724            PixelColour pc;
725    
726          while (out < end)          if (g_compatible_arch)
727            {
728                    /* *INDENT-OFF* */
729                    REPEAT3
730                    (
731                            pixel = *(data++);
732                            SPLITCOLOUR16(pixel, pc);
733                            *(out++) = pc.blue;
734                            *(out++) = pc.green;
735                            *(out++) = pc.red;
736                    )
737                    /* *INDENT-ON* */
738            }
739            else if (g_xserver_be)
740          {          {
                 pixel = *(data++);  
   
741                  if (g_host_be)                  if (g_host_be)
742                  {                  {
743                          BSWAP16(pixel);                          while (out < end)
744                            {
745                                    pixel = *(data++);
746                                    BSWAP16(pixel);
747                                    SPLITCOLOUR16(pixel, pc);
748                                    value = MAKECOLOUR(pc);
749                                    BOUT24(out, value);
750                            }
751                  }                  }
752                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
753                  {                  {
754                          *(out++) = value >> 16;                          while (out < end)
755                          *(out++) = value >> 8;                          {
756                          *(out++) = value;                                  pixel = *(data++);
757                                    SPLITCOLOUR16(pixel, pc);
758                                    value = MAKECOLOUR(pc);
759                                    BOUT24(out, value);
760                            }
761                    }
762            }
763            else
764            {
765                    if (g_host_be)
766                    {
767                            while (out < end)
768                            {
769                                    pixel = *(data++);
770                                    BSWAP16(pixel);
771                                    SPLITCOLOUR16(pixel, pc);
772                                    value = MAKECOLOUR(pc);
773                                    LOUT24(out, value);
774                            }
775                  }                  }
776                  else                  else
777                  {                  {
778                          *(out++) = value;                          while (out < end)
779                          *(out++) = value >> 8;                          {
780                          *(out++) = value >> 16;                                  pixel = *(data++);
781                                    SPLITCOLOUR16(pixel, pc);
782                                    value = MAKECOLOUR(pc);
783                                    LOUT24(out, value);
784                            }
785                  }                  }
786          }          }
787  }  }
788    
789  static void  static void
790  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
791  {  {
792          uint16 pixel;          uint16 pixel;
793          uint32 value;          uint32 value;
794            PixelColour pc;
795    
796          while (out < end)          if (g_compatible_arch)
797            {
798                    /* *INDENT-OFF* */
799                    REPEAT4
800                    (
801                            pixel = *(data++);
802                            SPLITCOLOUR16(pixel, pc);
803                            *(out++) = pc.blue;
804                            *(out++) = pc.green;
805                            *(out++) = pc.red;
806                            *(out++) = 0;
807                    )
808                    /* *INDENT-ON* */
809            }
810            else if (g_xserver_be)
811          {          {
                 pixel = *(data++);  
   
812                  if (g_host_be)                  if (g_host_be)
813                  {                  {
814                          BSWAP16(pixel);                          while (out < end)
815                            {
816                                    pixel = *(data++);
817                                    BSWAP16(pixel);
818                                    SPLITCOLOUR16(pixel, pc);
819                                    value = MAKECOLOUR(pc);
820                                    BOUT32(out, value);
821                            }
822                  }                  }
823                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
824                  {                  {
825                          *(out++) = value >> 24;                          while (out < end)
826                          *(out++) = value >> 16;                          {
827                          *(out++) = value >> 8;                                  pixel = *(data++);
828                          *(out++) = value;                                  SPLITCOLOUR16(pixel, pc);
829                                    value = MAKECOLOUR(pc);
830                                    BOUT32(out, value);
831                            }
832                    }
833            }
834            else
835            {
836                    if (g_host_be)
837                    {
838                            while (out < end)
839                            {
840                                    pixel = *(data++);
841                                    BSWAP16(pixel);
842                                    SPLITCOLOUR16(pixel, pc);
843                                    value = MAKECOLOUR(pc);
844                                    LOUT32(out, value);
845                            }
846                  }                  }
847                  else                  else
848                  {                  {
849                          *(out++) = value;                          while (out < end)
850                          *(out++) = value >> 8;                          {
851                          *(out++) = value >> 16;                                  pixel = *(data++);
852                          *(out++) = value >> 24;                                  SPLITCOLOUR16(pixel, pc);
853                                    value = MAKECOLOUR(pc);
854                                    LOUT32(out, value);
855                            }
856                  }                  }
857          }          }
858  }  }
859    
860  static void  static void
861  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
862  {  {
863          uint32 pixel = 0;          uint32 pixel = 0;
864          uint16 value;          uint16 value;
865            PixelColour pc;
866    
867          while (out < end)          while (out < end)
868          {          {
869                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
870                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
871                  pixel |= *(data++);                  pixel |= *(data++);
872                    SPLITCOLOUR24(pixel, pc);
873                  value = (uint16) make_colour(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
874                  if (g_xserver_be)                  if (g_xserver_be)
875                  {                  {
876                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
877                  }                  }
878                  else                  else
879                  {                  {
880                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
881                  }                  }
882          }          }
883  }  }
884    
885  static void  static void
886  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
887  {  {
888          uint32 pixel;          uint32 pixel;
889          uint32 value;          uint32 value;
890            PixelColour pc;
891    
892          while (out < end)          if (g_xserver_be)
893          {          {
894                  pixel = *(data++) << 16;                  while (out < end)
                 pixel |= *(data++) << 8;  
                 pixel |= *(data++);  
   
                 value = make_colour(split_colour24(pixel));  
   
                 if (g_xserver_be)  
895                  {                  {
896                          *(out++) = value >> 16;                          pixel = *(data++) << 16;
897                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
898                          *(out++) = value;                          pixel |= *(data++);
899                            SPLITCOLOUR24(pixel, pc);
900                            value = MAKECOLOUR(pc);
901                            BOUT24(out, value);
902                  }                  }
903                  else          }
904            else
905            {
906                    while (out < end)
907                  {                  {
908                          *(out++) = value;                          pixel = *(data++) << 16;
909                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
910                          *(out++) = value >> 16;                          pixel |= *(data++);
911                            SPLITCOLOUR24(pixel, pc);
912                            value = MAKECOLOUR(pc);
913                            LOUT24(out, value);
914                  }                  }
915          }          }
916  }  }
917    
918  static void  static void
919  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
920  {  {
921          uint32 pixel;          uint32 pixel;
922          uint32 value;          uint32 value;
923            PixelColour pc;
924    
925          while (out < end)          if (g_compatible_arch)
926          {          {
927                  pixel = *(data++) << 16;                  /* *INDENT-OFF* */
928                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
929                  pixel |= *(data++);                  REPEAT4
930                    (
931                  value = make_colour(split_colour24(pixel));                          *(out++) = *(data++);
932                            *(out++) = *(data++);
933                  if (g_xserver_be)                          *(out++) = *(data++);
934                            *(out++) = 0;
935                    )
936    #else
937                    REPEAT4
938                    (
939                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
940                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
941                     out += 4;
942                     data += 3;
943                    )
944    #endif
945                    /* *INDENT-ON* */
946            }
947            else if (g_xserver_be)
948            {
949                    while (out < end)
950                  {                  {
951                          *(out++) = value >> 24;                          pixel = *(data++) << 16;
952                          *(out++) = value >> 16;                          pixel |= *(data++) << 8;
953                          *(out++) = value >> 8;                          pixel |= *(data++);
954                          *(out++) = value;                          SPLITCOLOUR24(pixel, pc);
955                            value = MAKECOLOUR(pc);
956                            BOUT32(out, value);
957                  }                  }
958                  else          }
959            else
960            {
961                    while (out < end)
962                  {                  {
963                          *(out++) = value;                          pixel = *(data++) << 16;
964                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
965                          *(out++) = value >> 16;                          pixel |= *(data++);
966                          *(out++) = value >> 24;                          SPLITCOLOUR24(pixel, pc);
967                            value = MAKECOLOUR(pc);
968                            LOUT32(out, value);
969                  }                  }
970          }          }
971  }  }
# Line 651  translate_image(int width, int height, u Line 977  translate_image(int width, int height, u
977          uint8 *out;          uint8 *out;
978          uint8 *end;          uint8 *end;
979    
980          /* if server and xserver bpp match, */          /*
981          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
982          /* just return data */             and arch(endian) matches, no need to translate:
983          if (g_arch_match)             just return data.
984               Note: select_visual should've already ensured g_no_translate
985               is only set for compatible depths, but the RDP depth might've
986               changed during connection negotiations.
987             */
988            if (g_no_translate_image)
989          {          {
990                  if (g_depth == 15 && g_server_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
991                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
992                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
993                          return data;                          return data;
994          }          }
995    
# Line 666  translate_image(int width, int height, u Line 997  translate_image(int width, int height, u
997          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
998          end = out + size;          end = out + size;
999    
1000          switch (g_server_bpp)          switch (g_server_depth)
1001          {          {
1002                  case 24:                  case 24:
1003                          switch (g_bpp)                          switch (g_bpp)
# Line 764  calculate_shifts(uint32 mask, int *shift Line 1095  calculate_shifts(uint32 mask, int *shift
1095          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
1096  }  }
1097    
1098  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1099  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1100     */
1101    static unsigned
1102    calculate_mask_weight(uint32 mask)
1103    {
1104            unsigned weight = 0;
1105            do
1106            {
1107                    weight += (mask & 1);
1108            }
1109            while (mask >>= 1);
1110            return weight;
1111    }
1112    
1113    static BOOL
1114    select_visual()
1115  {  {
         XVisualInfo vi;  
1116          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1117          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1118          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1119          XVisualInfo template;          XVisualInfo template;
1120          Bool TrueColorVisual = False;          int i;
1121            unsigned red_weight, blue_weight, green_weight;
1122    
1123          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1124          if (g_display == NULL)  
1125            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1126            if (pfm == NULL)
1127          {          {
1128                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1129                    XCloseDisplay(g_display);
1130                  return False;                  return False;
1131          }          }
1132    
1133          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 */  
1134          template.class = TrueColor;          template.class = TrueColor;
1135          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1136            g_visual = NULL;
1137            g_no_translate_image = False;
1138            g_compatible_arch = False;
1139            if (vmatches != NULL)
1140            {
1141                    for (i = 0; i < visuals_count; ++i)
1142                    {
1143                            XVisualInfo *visual_info = &vmatches[i];
1144    
1145                            /* Try to find a no-translation visual that'll
1146                               allow us to use RDP bitmaps directly as ZPixmaps. */
1147                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1148                                                   /* R5G5B5 */
1149                                                   (visual_info->red_mask == 0x7c00) &&
1150                                                   (visual_info->green_mask == 0x3e0) &&
1151                                                   (visual_info->blue_mask == 0x1f)) ||
1152                                                  ((visual_info->depth == 16) &&
1153                                                   /* R5G6B5 */
1154                                                   (visual_info->red_mask == 0xf800) &&
1155                                                   (visual_info->green_mask == 0x7e0) &&
1156                                                   (visual_info->blue_mask == 0x1f)) ||
1157                                                  ((visual_info->depth == 24) &&
1158                                                   /* R8G8B8 */
1159                                                   (visual_info->red_mask == 0xff0000) &&
1160                                                   (visual_info->green_mask == 0xff00) &&
1161                                                   (visual_info->blue_mask == 0xff))))
1162                            {
1163                                    g_visual = visual_info->visual;
1164                                    g_depth = visual_info->depth;
1165                                    g_compatible_arch = !g_host_be;
1166                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1167                                    if (g_no_translate_image)
1168                                            /* We found the best visual */
1169                                            break;
1170                            }
1171                            else
1172                            {
1173                                    g_compatible_arch = False;
1174                            }
1175    
1176          nvisuals--;                          if (visual_info->depth > 24)
1177          while (nvisuals >= 0)                          {
1178          {                                  /* Avoid 32-bit visuals and likes like the plague.
1179                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1180                  {                                     (e.g. nvidia's Composite 32-bit visual).
1181                          g_depth = (vmatches + nvisuals)->depth;                                     Most implementation offer a 24-bit visual anyway. */
1182                                    continue;
1183                            }
1184    
1185                            /* Only care for visuals, for whose BPPs (not depths!)
1186                               we have a translateXtoY function. */
1187                            BOOL can_translate_to_bpp = False;
1188                            int j;
1189                            for (j = 0; j < pixmap_formats_count; ++j)
1190                            {
1191                                    if (pfm[j].depth == visual_info->depth)
1192                                    {
1193                                            if ((pfm[j].bits_per_pixel == 16) ||
1194                                                (pfm[j].bits_per_pixel == 24) ||
1195                                                (pfm[j].bits_per_pixel == 32))
1196                                            {
1197                                                    can_translate_to_bpp = True;
1198                                            }
1199                                            break;
1200                                    }
1201                            }
1202    
1203                            /* Prefer formats which have the most colour depth.
1204                               We're being truly aristocratic here, minding each
1205                               weight on its own. */
1206                            if (can_translate_to_bpp)
1207                            {
1208                                    unsigned vis_red_weight =
1209                                            calculate_mask_weight(visual_info->red_mask);
1210                                    unsigned vis_green_weight =
1211                                            calculate_mask_weight(visual_info->green_mask);
1212                                    unsigned vis_blue_weight =
1213                                            calculate_mask_weight(visual_info->blue_mask);
1214                                    if ((vis_red_weight >= red_weight)
1215                                        && (vis_green_weight >= green_weight)
1216                                        && (vis_blue_weight >= blue_weight))
1217                                    {
1218                                            red_weight = vis_red_weight;
1219                                            green_weight = vis_green_weight;
1220                                            blue_weight = vis_blue_weight;
1221                                            g_visual = visual_info->visual;
1222                                            g_depth = visual_info->depth;
1223                                    }
1224                            }
1225                  }                  }
1226                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1227          }          }
1228    
1229          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)))  
1230          {          {
1231                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1232                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1233                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1234                    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;  
                 }  
1235          }          }
1236          else          else
1237          {          {
1238                  /* need a truecolour visual */                  template.class = PseudoColor;
1239                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1240                  {                  template.colormap_size = 256;
1241                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1242                            XGetVisualInfo(g_display,
1243                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1244                                           &template, &visuals_count);
1245                    if (vmatches == NULL)
1246                    {
1247                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1248                            XCloseDisplay(g_display);
1249                            XFree(pfm);
1250                          return False;                          return False;
1251                  }                  }
1252    
1253                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1254                  g_owncolmap = False;                  g_owncolmap = True;
1255                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1256                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
                 calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);  
   
                 /* if RGB video and averything is little endian */  
                 if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask)  
                         if (!g_xserver_be && !g_host_be)  
                                 g_arch_match = True;  
1257          }          }
1258    
1259          pfm = XListPixmapFormats(g_display, &i);          g_bpp = 0;
1260          if (pfm != NULL)          for (i = 0; i < pixmap_formats_count; ++i)
1261          {          {
1262                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1263                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1264                  {                  {
1265                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1266    
1267                            if (g_no_translate_image)
1268                          {                          {
1269                                  g_bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1270                                    {
1271                                            case 15:
1272                                            case 16:
1273                                                    if (g_bpp != 16)
1274                                                            g_no_translate_image = False;
1275                                                    break;
1276                                            case 24:
1277                                                    /* Yes, this will force image translation
1278                                                       on most modern servers which use 32 bits
1279                                                       for R8G8B8. */
1280                                                    if (g_bpp != 24)
1281                                                            g_no_translate_image = False;
1282                                                    break;
1283                                            default:
1284                                                    g_no_translate_image = False;
1285                                                    break;
1286                                    }
1287                          }                          }
1288    
1289                            /* Pixmap formats list is a depth-to-bpp mapping --
1290                               there's just a single entry for every depth,
1291                               so we can safely break here */
1292                            break;
1293                  }                  }
                 XFree(pfm);  
1294          }          }
1295            XFree(pfm);
1296            pfm = NULL;
1297            return True;
1298    }
1299    
1300    BOOL
1301    ui_init(void)
1302    {
1303            int screen_num;
1304    
1305          if (g_bpp < 8)          g_display = XOpenDisplay(NULL);
1306            if (g_display == NULL)
1307          {          {
1308                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
1309                  XCloseDisplay(g_display);                  return False;
1310            }
1311    
1312            {
1313                    uint16 endianess_test = 1;
1314                    g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1315            }
1316    
1317            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1318            screen_num = DefaultScreen(g_display);
1319            g_x_socket = ConnectionNumber(g_display);
1320            g_screen = ScreenOfDisplay(g_display, screen_num);
1321            g_depth = DefaultDepthOfScreen(g_screen);
1322    
1323            if (!select_visual())
1324                  return False;                  return False;
1325    
1326            if (g_no_translate_image)
1327            {
1328                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1329            }
1330    
1331            if (g_server_depth > g_bpp)
1332            {
1333                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1334                            g_server_depth, g_bpp);
1335          }          }
1336    
1337            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1338                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1339    
1340          if (!g_owncolmap)          if (!g_owncolmap)
1341          {          {
1342                  g_xcolmap =                  g_xcolmap =
1343                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1344                                          AllocNone);                                          AllocNone);
1345                  if (g_depth <= 8)                  if (g_depth <= 8)
1346                          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);
1347          }          }
1348    
1349          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1350          {          {
1351                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1352                  g_ownbackstore = True;                  g_ownbackstore = True;
1353          }          }
1354    
# Line 883  ui_init(void) Line 1359  ui_init(void)
1359          {          {
1360                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1361                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1362                    g_using_full_workarea = True;
1363          }          }
1364          else if (g_width < 0)          else if (g_width < 0)
1365          {          {
1366                  /* Percent of screen */                  /* Percent of screen */
1367                    if (-g_width >= 100)
1368                            g_using_full_workarea = True;
1369                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1370                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1371          }          }
# Line 894  ui_init(void) Line 1373  ui_init(void)
1373          {          {
1374                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1375                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1376                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1377                  {                  {
1378                          g_width = cx;                          g_width = cx;
1379                          g_height = cy;                          g_height = cy;
1380                            g_using_full_workarea = True;
1381                  }                  }
1382                  else                  else
1383                  {                  {
1384                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1385                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1386                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1387                  }                  }
1388          }          }
1389    
# Line 919  ui_init(void) Line 1398  ui_init(void)
1398                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1399    
1400          xclip_init();          xclip_init();
1401            ewmh_init();
1402            if (g_seamless_rdp)
1403                    seamless_init();
1404    
1405          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));
1406    
1407          return True;          return True;
1408  }  }
# Line 944  ui_deinit(void) Line 1426  ui_deinit(void)
1426          g_display = NULL;          g_display = NULL;
1427  }  }
1428    
1429    
1430    static void
1431    get_window_attribs(XSetWindowAttributes * attribs)
1432    {
1433            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1434            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1435            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1436            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1437            attribs->override_redirect = g_fullscreen;
1438            attribs->colormap = g_xcolmap;
1439    }
1440    
1441    static void
1442    get_input_mask(long *input_mask)
1443    {
1444            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1445                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1446    
1447            if (g_sendmotion)
1448                    *input_mask |= PointerMotionMask;
1449            if (g_ownbackstore)
1450                    *input_mask |= ExposureMask;
1451            if (g_fullscreen || g_grab_keyboard)
1452                    *input_mask |= EnterWindowMask;
1453            if (g_grab_keyboard)
1454                    *input_mask |= LeaveWindowMask;
1455    }
1456    
1457  BOOL  BOOL
1458  ui_create_window(void)  ui_create_window(void)
1459  {  {
# Line 960  ui_create_window(void) Line 1470  ui_create_window(void)
1470          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1471          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1472    
1473          attribs.background_pixel = BlackPixelOfScreen(g_screen);          /* Handle -x-y portion of geometry string */
1474          attribs.border_pixel = WhitePixelOfScreen(g_screen);          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1475          attribs.backing_store = g_ownbackstore ? NotUseful : Always;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1476          attribs.override_redirect = g_fullscreen;          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1477          attribs.colormap = g_xcolmap;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1478    
1479          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth, wndheight,          get_window_attribs(&attribs);
1480                                0, g_depth, InputOutput, g_visual,  
1481                                CWBackPixel | CWBackingStore | CWOverrideRedirect |          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1482                                CWColormap | CWBorderPixel, &attribs);                                wndheight, 0, g_depth, InputOutput, g_visual,
1483                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1484                                  CWBorderPixel, &attribs);
1485    
1486          if (g_gc == NULL)          if (g_gc == NULL)
1487            {
1488                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1489                    ui_reset_clip();
1490            }
1491    
1492          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1493                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 989  ui_create_window(void) Line 1504  ui_create_window(void)
1504          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1505    
1506          if (g_hide_decorations)          if (g_hide_decorations)
1507                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1508    
1509          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1510          if (classhints != NULL)          if (classhints != NULL)
# Line 1003  ui_create_window(void) Line 1518  ui_create_window(void)
1518          if (sizehints)          if (sizehints)
1519          {          {
1520                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1521                    if (g_pos)
1522                            sizehints->flags |= PPosition;
1523                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1524                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1525                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
# Line 1014  ui_create_window(void) Line 1531  ui_create_window(void)
1531                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1532          }          }
1533    
1534          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          get_input_mask(&input_mask);
                 VisibilityChangeMask | FocusChangeMask;  
   
         if (g_sendmotion)  
                 input_mask |= PointerMotionMask;  
         if (g_ownbackstore)  
                 input_mask |= ExposureMask;  
         if (g_fullscreen || g_grab_keyboard)  
                 input_mask |= EnterWindowMask;  
         if (g_grab_keyboard)  
                 input_mask |= LeaveWindowMask;  
1535    
1536          if (g_IM != NULL)          if (g_IM != NULL)
1537          {          {
# Line 1037  ui_create_window(void) Line 1544  ui_create_window(void)
1544          }          }
1545    
1546          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1547          XMapWindow(g_display, g_wnd);          if (!g_seamless_rdp)
   
         /* wait for VisibilityNotify */  
         do  
1548          {          {
1549                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMapWindow(g_display, g_wnd);
1550                    /* wait for VisibilityNotify */
1551                    do
1552                    {
1553                            XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1554                    }
1555                    while (xevent.type != VisibilityNotify);
1556                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1557          }          }
         while (xevent.type != VisibilityNotify);  
         g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;  
1558    
1559          g_focused = False;          g_focused = False;
1560          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1109  xwin_toggle_fullscreen(void) Line 1618  xwin_toggle_fullscreen(void)
1618  {  {
1619          Pixmap contents = 0;          Pixmap contents = 0;
1620    
1621            if (g_seamless_rdp)
1622                    /* Turn off SeamlessRDP mode */
1623                    ui_seamless_toggle();
1624    
1625          if (!g_ownbackstore)          if (!g_ownbackstore)
1626          {          {
1627                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1129  xwin_toggle_fullscreen(void) Line 1642  xwin_toggle_fullscreen(void)
1642          }          }
1643  }  }
1644    
1645  /* Process all events in Xlib queue  static void
1646    handle_button_event(XEvent xevent, BOOL down)
1647    {
1648            uint16 button, flags = 0;
1649            g_last_gesturetime = xevent.xbutton.time;
1650            button = xkeymap_translate_button(xevent.xbutton.button);
1651            if (button == 0)
1652                    return;
1653    
1654            if (down)
1655                    flags = MOUSE_FLAG_DOWN;
1656    
1657            /* Stop moving window when button is released, regardless of cursor position */
1658            if (g_moving_wnd && (xevent.type == ButtonRelease))
1659                    g_moving_wnd = False;
1660    
1661            /* If win_button_size is nonzero, enable single app mode */
1662            if (xevent.xbutton.y < g_win_button_size)
1663            {
1664                    /*  Check from right to left: */
1665                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1666                    {
1667                            /* The close button, continue */
1668                            ;
1669                    }
1670                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1671                    {
1672                            /* The maximize/restore button. Do not send to
1673                               server.  It might be a good idea to change the
1674                               cursor or give some other visible indication
1675                               that rdesktop inhibited this click */
1676                            if (xevent.type == ButtonPress)
1677                                    return;
1678                    }
1679                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1680                    {
1681                            /* The minimize button. Iconify window. */
1682                            if (xevent.type == ButtonRelease)
1683                            {
1684                                    /* Release the mouse button outside the minimize button, to prevent the
1685                                       actual minimazation to happen */
1686                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1687                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1688                                    return;
1689                            }
1690                    }
1691                    else if (xevent.xbutton.x <= g_win_button_size)
1692                    {
1693                            /* The system menu. Ignore. */
1694                            if (xevent.type == ButtonPress)
1695                                    return;
1696                    }
1697                    else
1698                    {
1699                            /* The title bar. */
1700                            if (xevent.type == ButtonPress)
1701                            {
1702                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1703                                    {
1704                                            g_moving_wnd = True;
1705                                            g_move_x_offset = xevent.xbutton.x;
1706                                            g_move_y_offset = xevent.xbutton.y;
1707                                    }
1708                                    return;
1709                            }
1710                    }
1711            }
1712    
1713            if (xevent.xmotion.window == g_wnd)
1714            {
1715                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1716                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1717            }
1718            else
1719            {
1720                    /* SeamlessRDP */
1721                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1722                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1723            }
1724    }
1725    
1726    /* Process events in Xlib queue
1727     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1728  static int  static int
1729  xwin_process_events(void)  xwin_process_events(void)
1730  {  {
1731          XEvent xevent;          XEvent xevent;
1732          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1733          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1734          char str[256];          char str[256];
1735          Status status;          Status status;
1736            int events = 0;
1737            seamless_window *sw;
1738    
1739          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1740          {          {
1741                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1742    
# Line 1152  xwin_process_events(void) Line 1746  xwin_process_events(void)
1746                          continue;                          continue;
1747                  }                  }
1748    
                 flags = 0;  
   
1749                  switch (xevent.type)                  switch (xevent.type)
1750                  {                  {
1751                          case VisibilityNotify:                          case VisibilityNotify:
1752                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1753                                            g_Unobscured =
1754                                                    xevent.xvisibility.state == VisibilityUnobscured;
1755    
1756                                  break;                                  break;
1757                          case ClientMessage:                          case ClientMessage:
1758                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1190  xwin_process_events(void) Line 1785  xwin_process_events(void)
1785                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1786                                  }                                  }
1787    
1788                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1789                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1790    
1791                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1792                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1793                                          break;                                          break;
1794    
1795                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1796                                                             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);  
   
1797                                  break;                                  break;
1798    
1799                          case KeyRelease:                          case KeyRelease:
# Line 1215  xwin_process_events(void) Line 1801  xwin_process_events(void)
1801                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1802                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1803    
1804                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1805                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1806    
1807                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1808                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1809                                          break;                                          break;
1810    
1811                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1812                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1813                                  break;                                  break;
1814    
1815                          case ButtonPress:                          case ButtonPress:
1816                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1817                                  /* fall through */                                  break;
1818    
1819                          case ButtonRelease:                          case ButtonRelease:
1820                                  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);  
1821                                  break;                                  break;
1822    
1823                          case MotionNotify:                          case MotionNotify:
# Line 1308  xwin_process_events(void) Line 1832  xwin_process_events(void)
1832                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1833                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1834                                                         CurrentTime);                                                         CurrentTime);
1835                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1836                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1837                                    {
1838                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1839                                                           xevent.xmotion.x, xevent.xmotion.y);
1840                                    }
1841                                    else
1842                                    {
1843                                            /* SeamlessRDP */
1844                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1845                                                           xevent.xmotion.x_root,
1846                                                           xevent.xmotion.y_root);
1847                                    }
1848                                  break;                                  break;
1849    
1850                          case FocusIn:                          case FocusIn:
# Line 1352  xwin_process_events(void) Line 1887  xwin_process_events(void)
1887                                  break;                                  break;
1888    
1889                          case Expose:                          case Expose:
1890                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
1891                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1892                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1893                                            xevent.xexpose.height,                                                    g_gc,
1894                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1895                                                      xevent.xexpose.width, xevent.xexpose.height,
1896                                                      xevent.xexpose.x, xevent.xexpose.y);
1897                                    }
1898                                    else
1899                                    {
1900                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1901                                            if (sw)
1902                                                    XCopyArea(g_display, g_backstore,
1903                                                              xevent.xexpose.window, g_gc,
1904                                                              xevent.xexpose.x + sw->xoffset,
1905                                                              xevent.xexpose.y + sw->yoffset,
1906                                                              xevent.xexpose.width,
1907                                                              xevent.xexpose.height, xevent.xexpose.x,
1908                                                              xevent.xexpose.y);
1909                                            else
1910                                            {
1911                                                    error("Expose for unknown window 0x%lx\n",
1912                                                          xevent.xexpose.window);
1913                                            }
1914                                    }
1915    
1916                                  break;                                  break;
1917    
1918                          case MappingNotify:                          case MappingNotify:
# Line 1385  xwin_process_events(void) Line 1941  xwin_process_events(void)
1941                                  break;                                  break;
1942                          case PropertyNotify:                          case PropertyNotify:
1943                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1944                                    if (xevent.xproperty.window == g_wnd)
1945                                            break;
1946                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
1947                                            break;
1948    
1949                                    /* seamless */
1950                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
1951                                    if (!sw)
1952                                            break;
1953    
1954                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
1955                                        && (xevent.xproperty.state == PropertyNewValue))
1956                                    {
1957                                            sw->state = ewmh_get_window_state(sw->wnd);
1958                                            seamless_send_state(sw->id, sw->state, 0);
1959                                    }
1960                                    break;
1961                            case MapNotify:
1962                                    if (!g_seamless_rdp)
1963                                            rdp_send_client_window_status(1);
1964                                    break;
1965                            case UnmapNotify:
1966                                    if (!g_seamless_rdp)
1967                                            rdp_send_client_window_status(0);
1968                                  break;                                  break;
1969                  }                  }
1970          }          }
# Line 1469  ui_create_bitmap(int width, int height, Line 2049  ui_create_bitmap(int width, int height,
2049          uint8 *tdata;          uint8 *tdata;
2050          int bitmap_pad;          int bitmap_pad;
2051    
2052          if (g_server_bpp == 8)          if (g_server_depth == 8)
2053          {          {
2054                  bitmap_pad = 8;                  bitmap_pad = 8;
2055          }          }
# Line 1501  ui_paint_bitmap(int x, int y, int cx, in Line 2081  ui_paint_bitmap(int x, int y, int cx, in
2081          uint8 *tdata;          uint8 *tdata;
2082          int bitmap_pad;          int bitmap_pad;
2083    
2084          if (g_server_bpp == 8)          if (g_server_depth == 8)
2085          {          {
2086                  bitmap_pad = 8;                  bitmap_pad = 8;
2087          }          }
# Line 1521  ui_paint_bitmap(int x, int y, int cx, in Line 2101  ui_paint_bitmap(int x, int y, int cx, in
2101          {          {
2102                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2103                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2104                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2105                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2106                                             x - sw->xoffset, y - sw->yoffset));
2107          }          }
2108          else          else
2109          {          {
2110                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2111                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2112                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2113                                             x - sw->xoffset, y - sw->yoffset));
2114          }          }
2115    
2116          XFree(image);          XFree(image);
# Line 1645  ui_set_cursor(HCURSOR cursor) Line 2231  ui_set_cursor(HCURSOR cursor)
2231  {  {
2232          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2233          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2234            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2235  }  }
2236    
2237  void  void
# Line 1786  ui_set_colourmap(HCOLOURMAP map) Line 2373  ui_set_colourmap(HCOLOURMAP map)
2373                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2374          }          }
2375          else          else
2376            {
2377                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2378                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2379            }
2380  }  }
2381    
2382  void  void
2383  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2384  {  {
2385          XRectangle rect;          g_clip_rectangle.x = x;
2386            g_clip_rectangle.y = y;
2387          rect.x = x;          g_clip_rectangle.width = cx;
2388          rect.y = y;          g_clip_rectangle.height = cy;
2389          rect.width = cx;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = cy;  
         XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);  
2390  }  }
2391    
2392  void  void
2393  ui_reset_clip(void)  ui_reset_clip(void)
2394  {  {
2395          XRectangle rect;          g_clip_rectangle.x = 0;
2396            g_clip_rectangle.y = 0;
2397          rect.x = 0;          g_clip_rectangle.width = g_width;
2398          rect.y = 0;          g_clip_rectangle.height = g_height;
2399          rect.width = g_width;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = g_height;  
         XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);  
2400  }  }
2401    
2402  void  void
# Line 1891  ui_patblt(uint8 opcode, Line 2477  ui_patblt(uint8 opcode,
2477    
2478          if (g_ownbackstore)          if (g_ownbackstore)
2479                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2480            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2481                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2482                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2483  }  }
2484    
2485  void  void
# Line 1901  ui_screenblt(uint8 opcode, Line 2490  ui_screenblt(uint8 opcode,
2490          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2491          if (g_ownbackstore)          if (g_ownbackstore)
2492          {          {
2493                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2494                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2495                          XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                         XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,  
                                   y);  
                 }  
                 else  
                 {  
                         XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
                         XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,  
                                   y);  
                 }  
2496          }          }
2497          else          else
2498          {          {
2499                  XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2500          }          }
2501    
2502            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2503                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2504                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2505    
2506          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2507  }  }
2508    
# Line 1928  ui_memblt(uint8 opcode, Line 2513  ui_memblt(uint8 opcode,
2513  {  {
2514          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2515          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2516            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2517                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2518                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2519          if (g_ownbackstore)          if (g_ownbackstore)
2520                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2521          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1974  ui_line(uint8 opcode, Line 2562  ui_line(uint8 opcode,
2562          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2563          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2564          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2565            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2566                                                startx - sw->xoffset, starty - sw->yoffset,
2567                                                endx - sw->xoffset, endy - sw->yoffset));
2568          if (g_ownbackstore)          if (g_ownbackstore)
2569                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2570          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1988  ui_rect( Line 2579  ui_rect(
2579          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2580  }  }
2581    
2582    void
2583    ui_polygon(uint8 opcode,
2584               /* mode */ uint8 fillmode,
2585               /* dest */ POINT * point, int npoints,
2586               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2587    {
2588            uint8 style, i, ipattern[8];
2589            Pixmap fill;
2590    
2591            SET_FUNCTION(opcode);
2592    
2593            switch (fillmode)
2594            {
2595                    case ALTERNATE:
2596                            XSetFillRule(g_display, g_gc, EvenOddRule);
2597                            break;
2598                    case WINDING:
2599                            XSetFillRule(g_display, g_gc, WindingRule);
2600                            break;
2601                    default:
2602                            unimpl("fill mode %d\n", fillmode);
2603            }
2604    
2605            if (brush)
2606                    style = brush->style;
2607            else
2608                    style = 0;
2609    
2610            switch (style)
2611            {
2612                    case 0: /* Solid */
2613                            SET_FOREGROUND(fgcolour);
2614                            FILL_POLYGON((XPoint *) point, npoints);
2615                            break;
2616    
2617                    case 2: /* Hatch */
2618                            fill = (Pixmap) ui_create_glyph(8, 8,
2619                                                            hatch_patterns + brush->pattern[0] * 8);
2620                            SET_FOREGROUND(fgcolour);
2621                            SET_BACKGROUND(bgcolour);
2622                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2623                            XSetStipple(g_display, g_gc, fill);
2624                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2625                            FILL_POLYGON((XPoint *) point, npoints);
2626                            XSetFillStyle(g_display, g_gc, FillSolid);
2627                            XSetTSOrigin(g_display, g_gc, 0, 0);
2628                            ui_destroy_glyph((HGLYPH) fill);
2629                            break;
2630    
2631                    case 3: /* Pattern */
2632                            for (i = 0; i != 8; i++)
2633                                    ipattern[7 - i] = brush->pattern[i];
2634                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2635                            SET_FOREGROUND(bgcolour);
2636                            SET_BACKGROUND(fgcolour);
2637                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2638                            XSetStipple(g_display, g_gc, fill);
2639                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2640                            FILL_POLYGON((XPoint *) point, npoints);
2641                            XSetFillStyle(g_display, g_gc, FillSolid);
2642                            XSetTSOrigin(g_display, g_gc, 0, 0);
2643                            ui_destroy_glyph((HGLYPH) fill);
2644                            break;
2645    
2646                    default:
2647                            unimpl("brush %d\n", brush->style);
2648            }
2649    
2650            RESET_FUNCTION(opcode);
2651    }
2652    
2653    void
2654    ui_polyline(uint8 opcode,
2655                /* dest */ POINT * points, int npoints,
2656                /* pen */ PEN * pen)
2657    {
2658            /* TODO: set join style */
2659            SET_FUNCTION(opcode);
2660            SET_FOREGROUND(pen->colour);
2661            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2662            if (g_ownbackstore)
2663                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2664                               CoordModePrevious);
2665    
2666            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2667                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2668    
2669            RESET_FUNCTION(opcode);
2670    }
2671    
2672    void
2673    ui_ellipse(uint8 opcode,
2674               /* mode */ uint8 fillmode,
2675               /* dest */ int x, int y, int cx, int cy,
2676               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2677    {
2678            uint8 style, i, ipattern[8];
2679            Pixmap fill;
2680    
2681            SET_FUNCTION(opcode);
2682    
2683            if (brush)
2684                    style = brush->style;
2685            else
2686                    style = 0;
2687    
2688            switch (style)
2689            {
2690                    case 0: /* Solid */
2691                            SET_FOREGROUND(fgcolour);
2692                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2693                            break;
2694    
2695                    case 2: /* Hatch */
2696                            fill = (Pixmap) ui_create_glyph(8, 8,
2697                                                            hatch_patterns + brush->pattern[0] * 8);
2698                            SET_FOREGROUND(fgcolour);
2699                            SET_BACKGROUND(bgcolour);
2700                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2701                            XSetStipple(g_display, g_gc, fill);
2702                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2703                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2704                            XSetFillStyle(g_display, g_gc, FillSolid);
2705                            XSetTSOrigin(g_display, g_gc, 0, 0);
2706                            ui_destroy_glyph((HGLYPH) fill);
2707                            break;
2708    
2709                    case 3: /* Pattern */
2710                            for (i = 0; i != 8; i++)
2711                                    ipattern[7 - i] = brush->pattern[i];
2712                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2713                            SET_FOREGROUND(bgcolour);
2714                            SET_BACKGROUND(fgcolour);
2715                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2716                            XSetStipple(g_display, g_gc, fill);
2717                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2718                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2719                            XSetFillStyle(g_display, g_gc, FillSolid);
2720                            XSetTSOrigin(g_display, g_gc, 0, 0);
2721                            ui_destroy_glyph((HGLYPH) fill);
2722                            break;
2723    
2724                    default:
2725                            unimpl("brush %d\n", brush->style);
2726            }
2727    
2728            RESET_FUNCTION(opcode);
2729    }
2730    
2731  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2732  void  void
2733  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 2043  ui_draw_glyph(int mixmode, Line 2783  ui_draw_glyph(int mixmode,
2783  }  }
2784    
2785  void  void
2786  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,
2787               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2788               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2789               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2790  {  {
2791            /* TODO: use brush appropriately */
2792    
2793          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2794          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
2795          DATABLOB *entry;          DATABLOB *entry;
# Line 2079  ui_draw_text(uint8 font, uint8 flags, in Line 2821  ui_draw_text(uint8 font, uint8 flags, in
2821                  switch (text[i])                  switch (text[i])
2822                  {                  {
2823                          case 0xff:                          case 0xff:
2824                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2825                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2826                                  {                                  {
2827                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2828                                          exit(1);                                          for (j = 0; j < length; j++)
2829                                                    fprintf(stderr, "%02x ", text[j]);
2830                                            fprintf(stderr, "\n");
2831                                            i = length = 0;
2832                                            break;
2833                                  }                                  }
2834                                    cache_put_text(text[i + 1], text, text[i + 2]);
2835                                    i += 3;
2836                                    length -= i;
2837                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2838                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2839                                  i = 0;                                  i = 0;
2840                                  break;                                  break;
2841    
2842                          case 0xfe:                          case 0xfe:
2843                                    /* At least one byte needs to follow */
2844                                    if (i + 2 > length)
2845                                    {
2846                                            warning("Skipping short 0xfe command:");
2847                                            for (j = 0; j < length; j++)
2848                                                    fprintf(stderr, "%02x ", text[j]);
2849                                            fprintf(stderr, "\n");
2850                                            i = length = 0;
2851                                            break;
2852                                    }
2853                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2854                                  if (entry != NULL)                                  if (entry->data != NULL)
2855                                  {                                  {
2856                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2857                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2858                                          {                                          {
2859                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2860                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2129  ui_draw_text(uint8 font, uint8 flags, in Line 2886  ui_draw_text(uint8 font, uint8 flags, in
2886          if (g_ownbackstore)          if (g_ownbackstore)
2887          {          {
2888                  if (boxcx > 1)                  if (boxcx > 1)
2889                    {
2890                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2891                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2892                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2893                                                    (g_display, g_backstore, sw->wnd, g_gc,
2894                                                     boxx, boxy,
2895                                                     boxcx, boxcy,
2896                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2897                    }
2898                  else                  else
2899                    {
2900                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2901                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2902                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2903                                                    (g_display, g_backstore, sw->wnd, g_gc,
2904                                                     clipx, clipy,
2905                                                     clipcx, clipcy, clipx - sw->xoffset,
2906                                                     clipy - sw->yoffset));
2907                    }
2908          }          }
2909  }  }
2910    
# Line 2179  ui_desktop_restore(uint32 offset, int x, Line 2950  ui_desktop_restore(uint32 offset, int x,
2950          {          {
2951                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2952                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2953                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2954                                            (g_display, g_backstore, sw->wnd, g_gc,
2955                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2956          }          }
2957          else          else
2958          {          {
2959                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2960                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2961                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2962                                             x - sw->xoffset, y - sw->yoffset));
2963          }          }
2964    
2965          XFree(image);          XFree(image);
# Line 2198  void Line 2975  void
2975  ui_end_update(void)  ui_end_update(void)
2976  {  {
2977  }  }
2978    
2979    void
2980    ui_seamless_toggle()
2981    {
2982            if (g_seamless_rdp)
2983            {
2984                    /* Deactivate */
2985                    while (g_seamless_windows)
2986                    {
2987                            XDestroyWindow(g_display, g_seamless_windows->wnd);
2988                            seamless_remove_window(g_seamless_windows);
2989                    }
2990                    XMapWindow(g_display, g_wnd);
2991            }
2992            else
2993            {
2994                    /* Activate */
2995                    if (g_win_button_size)
2996                    {
2997                            error("SeamlessRDP mode cannot be activated when using single application mode\n");
2998                            return;
2999                    }
3000                    if (!g_using_full_workarea)
3001                    {
3002                            error("SeamlessRDP mode requires a session that covers the whole screen");
3003                            return;
3004                    }
3005    
3006                    XUnmapWindow(g_display, g_wnd);
3007                    seamless_send_sync();
3008            }
3009    
3010            g_seamless_rdp = !g_seamless_rdp;
3011    }
3012    
3013    void
3014    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3015    {
3016            Window wnd;
3017            XSetWindowAttributes attribs;
3018            XClassHint *classhints;
3019            long input_mask;
3020            seamless_window *sw, *sw_parent;
3021    
3022            get_window_attribs(&attribs);
3023    
3024            attribs.override_redirect = False;
3025    
3026            /* FIXME: Do not assume that -1, -1 is outside screen Consider
3027               wait with showing the window until STATE and others have
3028               been recieved. */
3029            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, 0,
3030                                InputOutput, g_visual,
3031                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3032                                CWBorderPixel, &attribs);
3033    
3034            XStoreName(g_display, wnd, "rdesktop-seamless");
3035    
3036            mwm_hide_decorations(wnd);
3037    
3038            classhints = XAllocClassHint();
3039            if (classhints != NULL)
3040            {
3041                    classhints->res_name = classhints->res_class = "rdesktop";
3042                    XSetClassHint(g_display, wnd, classhints);
3043                    XFree(classhints);
3044            }
3045    
3046            /* Set WM_TRANSIENT_FOR, if necessary */
3047            if (parent)
3048            {
3049                    sw_parent = seamless_get_window_by_id(parent);
3050                    if (sw_parent)
3051                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3052                    else
3053                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3054            }
3055    
3056            /* FIXME: Support for Input Context:s */
3057    
3058            get_input_mask(&input_mask);
3059            input_mask |= PropertyChangeMask;
3060    
3061            XSelectInput(g_display, wnd, input_mask);
3062    
3063            XMapWindow(g_display, wnd);
3064    
3065            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3066               seamless window, we could try to close the window on the
3067               serverside, instead of terminating rdesktop */
3068            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3069    
3070            sw = malloc(sizeof(seamless_window));
3071            sw->wnd = wnd;
3072            sw->id = id;
3073            sw->xoffset = 0;
3074            sw->yoffset = 0;
3075            sw->width = 0;
3076            sw->height = 0;
3077            sw->next = g_seamless_windows;
3078            g_seamless_windows = sw;
3079    }
3080    
3081    
3082    void
3083    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3084    {
3085            seamless_window *sw;
3086    
3087            sw = seamless_get_window_by_id(id);
3088            if (!sw)
3089            {
3090                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3091                    return;
3092            }
3093    
3094            XDestroyWindow(g_display, sw->wnd);
3095            seamless_remove_window(sw);
3096    }
3097    
3098    
3099    void
3100    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3101    {
3102            seamless_window *sw;
3103    
3104            sw = seamless_get_window_by_id(id);
3105            if (!sw)
3106            {
3107                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3108                    return;
3109            }
3110    
3111            if (!width || !height)
3112                    /* X11 windows must be at least 1x1 */
3113                    return;
3114    
3115            /* About MAX and MIN: Windows allows moving a window outside
3116               the desktop. This happens, for example, when maximizing an
3117               application. In this case, the position is set to something
3118               like -4,-4,1288,1032. Many WMs does not allow windows
3119               outside the desktop, however. Therefore, clip the window
3120               ourselves. */
3121            sw->xoffset = MAX(0, x);
3122            sw->yoffset = MAX(0, y);
3123            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3124            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3125    
3126            /* If we move the window in a maximized state, then KDE won't
3127               accept restoration */
3128            if (sw->state != SEAMLESSRDP_NORMAL)
3129                    return;
3130    
3131            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3132            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3133    }
3134    
3135    
3136    void
3137    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3138    {
3139            seamless_window *sw;
3140    
3141            sw = seamless_get_window_by_id(id);
3142            if (!sw)
3143            {
3144                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3145                    return;
3146            }
3147    
3148            XStoreName(g_display, sw->wnd, title);
3149    }
3150    
3151    
3152    void
3153    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3154    {
3155            seamless_window *sw;
3156    
3157            sw = seamless_get_window_by_id(id);
3158            if (!sw)
3159            {
3160                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3161                    return;
3162            }
3163    
3164            sw->state = state;
3165    
3166            switch (state)
3167            {
3168                    case SEAMLESSRDP_NORMAL:
3169                    case SEAMLESSRDP_MAXIMIZED:
3170                            ewmh_change_state(sw->wnd, state);
3171                            break;
3172                    case SEAMLESSRDP_MINIMIZED:
3173                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3174                               the Window Manager should probably just ignore the request, since
3175                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3176                               such as minimization, rather than an independent state." Besides,
3177                               XIconifyWindow is easier. */
3178                            XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3179                            break;
3180                    default:
3181                            warning("SeamlessRDP: Invalid state %d\n", state);
3182                            break;
3183            }
3184    }

Legend:
Removed from v.800  
changed lines
  Added in v.1118

  ViewVC Help
Powered by ViewVC 1.1.26