/[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 991 by astrand, Fri Aug 26 07:01:02 2005 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1144 by ossman_, Thu Mar 16 10:14:18 2006 UTC
# Line 38  extern BOOL g_fullscreen; Line 38  extern BOOL g_fullscreen;
38  extern BOOL g_grab_keyboard;  extern BOOL g_grab_keyboard;
39  extern BOOL g_hide_decorations;  extern BOOL g_hide_decorations;
40  extern char g_title[];  extern char g_title[];
41  extern int g_server_bpp;  /* Color depth of the RDP session.
42       As of RDP 5.1, it may be 8, 15, 16 or 24. */
43    extern int g_server_depth;
44  extern int g_win_button_size;  extern int g_win_button_size;
45    
46  Display *g_display;  Display *g_display;
# Line 46  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            unsigned long parent;
58            int xoffset, yoffset;
59            int width, height;
60            int state;              /* normal/minimized/maximized. */
61            unsigned int desktop;
62            struct _seamless_window *next;
63    } seamless_window;
64    static seamless_window *g_seamless_windows = NULL;
65    extern BOOL g_seamless_rdp;
66    
67  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
68  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
69  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
70  static GC g_gc = NULL;  static GC g_gc = NULL;
71  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
72  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
73    static XRectangle g_clip_rectangle;
74  static Visual *g_visual;  static Visual *g_visual;
75    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
76       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
77       as far as we're concerned. */
78  static int g_depth;  static int g_depth;
79    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
80       This may be larger than g_depth, in which case some of the bits would
81       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
82  static int g_bpp;  static int g_bpp;
83  static XIM g_IM;  static XIM g_IM;
84  static XIC g_IC;  static XIC g_IC;
# Line 61  static XModifierKeymap *g_mod_map; Line 86  static XModifierKeymap *g_mod_map;
86  static Cursor g_current_cursor;  static Cursor g_current_cursor;
87  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
88  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
89    extern Atom g_net_wm_state_atom;
90    extern Atom g_net_wm_desktop_atom;
91  static BOOL g_focused;  static BOOL g_focused;
92  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
93  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* Indicates that:
94       1) visual has 15, 16 or 24 depth and the same color channel masks
95          as its RDP equivalent (implies X server is LE),
96       2) host is LE
97       This will trigger an optimization whose real value is questionable.
98    */
99    static BOOL g_compatible_arch;
100    /* Indicates whether RDP's bitmaps and our XImages have the same
101       binary format. If so, we can avoid an expensive translation.
102       Note that this can be true when g_compatible_arch is false,
103       e.g.:
104      
105         RDP(LE) <-> host(BE) <-> X-Server(LE)
106        
107       ('host' is the machine running rdesktop; the host simply memcpy's
108        so its endianess doesn't matter)
109     */
110    static BOOL g_no_translate_image = False;
111    
112  /* endianness */  /* endianness */
113  static BOOL g_host_be;  static BOOL g_host_be;
# Line 92  extern BOOL g_rdpsnd; Line 136  extern BOOL g_rdpsnd;
136  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
137  typedef struct  typedef struct
138  {  {
139          uint32 flags;          unsigned long flags;
140          uint32 functions;          unsigned long functions;
141          uint32 decorations;          unsigned long decorations;
142          sint32 inputMode;          long inputMode;
143          uint32 status;          unsigned long status;
144  }  }
145  PropMotifWmHints;  PropMotifWmHints;
146    
# Line 108  typedef struct Line 152  typedef struct
152  }  }
153  PixelColour;  PixelColour;
154    
155    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
156            do { \
157                    seamless_window *sw; \
158                    XRectangle rect; \
159                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
160                        rect.x = g_clip_rectangle.x - sw->xoffset; \
161                        rect.y = g_clip_rectangle.y - sw->yoffset; \
162                        rect.width = g_clip_rectangle.width; \
163                        rect.height = g_clip_rectangle.height; \
164                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
165                        func args; \
166                    } \
167                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
168            } while (0)
169    
170    static void
171    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
172    {
173            points[0].x -= xoffset;
174            points[0].y -= yoffset;
175            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
176            points[0].x += xoffset;
177            points[0].y += yoffset;
178    }
179    
180    static void
181    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
182    {
183            points[0].x -= xoffset;
184            points[0].y -= yoffset;
185            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
186            points[0].x += xoffset;
187            points[0].y += yoffset;
188    }
189    
190  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
191  { \  { \
192          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
193            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
194          if (g_ownbackstore) \          if (g_ownbackstore) \
195                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
196  }  }
# Line 126  PixelColour; Line 205  PixelColour;
205          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
206          if (g_ownbackstore) \          if (g_ownbackstore) \
207                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
208            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
209  }  }
210    
211  #define DRAW_ELLIPSE(x,y,cx,cy,m)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 134  PixelColour; Line 214  PixelColour;
214          { \          { \
215                  case 0: /* Outline */ \                  case 0: /* Outline */ \
216                          XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
217                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
218                          if (g_ownbackstore) \                          if (g_ownbackstore) \
219                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
220                          break; \                          break; \
221                  case 1: /* Filled */ \                  case 1: /* Filled */ \
222                          XFillArc(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, \                          XFillArc(g_display, g_wnd, g_gc, x, y, \
223                                   cx, cy, 0, 360*64); \                                   cx, cy, 0, 360*64); \
224                            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)); \
225                          if (g_ownbackstore) \                          if (g_ownbackstore) \
226                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); \                                  XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
227                          break; \                          break; \
228          } \          } \
229  }  }
# Line 151  extern BOOL g_owncolmap; Line 233  extern BOOL g_owncolmap;
233  static Colormap g_xcolmap;  static Colormap g_xcolmap;
234  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
235    
236  #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] )
237  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
238  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
239    
# Line 177  static int rop2_map[] = { Line 259  static int rop2_map[] = {
259  #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]); }
260  #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); }
261    
262    static seamless_window *
263    seamless_get_window_by_id(unsigned long id)
264    {
265            seamless_window *sw;
266            for (sw = g_seamless_windows; sw; sw = sw->next)
267            {
268                    if (sw->id == id)
269                            return sw;
270            }
271            return NULL;
272    }
273    
274    
275    static seamless_window *
276    seamless_get_window_by_wnd(Window wnd)
277    {
278            seamless_window *sw;
279            for (sw = g_seamless_windows; sw; sw = sw->next)
280            {
281                    if (sw->wnd == wnd)
282                            return sw;
283            }
284            return NULL;
285    }
286    
287    
288  static void  static void
289  mwm_hide_decorations(void)  seamless_remove_window(seamless_window * win)
290    {
291            seamless_window *sw, **prevnext = &g_seamless_windows;
292            for (sw = g_seamless_windows; sw; sw = sw->next)
293            {
294                    if (sw == win)
295                    {
296                            *prevnext = sw->next;
297                            xfree(sw);
298                            return;
299                    }
300                    prevnext = &sw->next;
301            }
302            return;
303    }
304    
305    
306    /* Move all windows except wnd to new desktop */
307    static void
308    seamless_all_to_desktop(Window wnd, unsigned int desktop)
309    {
310            seamless_window *sw;
311            for (sw = g_seamless_windows; sw; sw = sw->next)
312            {
313                    if (sw->wnd == wnd)
314                            continue;
315                    if (sw->desktop != desktop)
316                    {
317                            ewmh_move_to_desktop(sw->wnd, desktop);
318                            sw->desktop = desktop;
319                    }
320            }
321    }
322    
323    
324    static void
325    mwm_hide_decorations(Window wnd)
326  {  {
327          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
328          Atom hintsatom;          Atom hintsatom;
# Line 195  mwm_hide_decorations(void) Line 339  mwm_hide_decorations(void)
339                  return;                  return;
340          }          }
341    
342          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
343                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
344    
345  }  }
346    
347  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 230  mwm_hide_decorations(void) Line 375  mwm_hide_decorations(void)
375  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
376                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
377    
378    /* The following macros output the same octet sequences
379       on both BE and LE hosts: */
380    
381  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
382  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
383  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
# Line 241  static uint32 Line 389  static uint32
389  translate_colour(uint32 colour)  translate_colour(uint32 colour)
390  {  {
391          PixelColour pc;          PixelColour pc;
392          switch (g_server_bpp)          switch (g_server_depth)
393          {          {
394                  case 15:                  case 15:
395                          SPLITCOLOUR15(colour, pc);                          SPLITCOLOUR15(colour, pc);
# Line 252  translate_colour(uint32 colour) Line 400  translate_colour(uint32 colour)
400                  case 24:                  case 24:
401                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
402                          break;                          break;
403                    default:
404                            /* Avoid warning */
405                            pc.red = 0;
406                            pc.green = 0;
407                            pc.blue = 0;
408                            break;
409          }          }
410          return MAKECOLOUR(pc);          return MAKECOLOUR(pc);
411  }  }
# Line 303  translate8to16(const uint8 * data, uint8 Line 457  translate8to16(const uint8 * data, uint8
457  {  {
458          uint16 value;          uint16 value;
459    
460          if (g_arch_match)          if (g_compatible_arch)
461          {          {
462                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
463                  REPEAT2                  REPEAT2
# Line 337  translate8to24(const uint8 * data, uint8 Line 491  translate8to24(const uint8 * data, uint8
491  {  {
492          uint32 value;          uint32 value;
493    
494          if (g_xserver_be)          if (g_compatible_arch)
495          {          {
496                  while (out < end)                  while (out < end)
497                  {                  {
# Line 360  translate8to32(const uint8 * data, uint8 Line 514  translate8to32(const uint8 * data, uint8
514  {  {
515          uint32 value;          uint32 value;
516    
517          if (g_arch_match)          if (g_compatible_arch)
518          {          {
519                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
520                  REPEAT4                  REPEAT4
# Line 432  translate15to24(const uint16 * data, uin Line 586  translate15to24(const uint16 * data, uin
586          uint16 pixel;          uint16 pixel;
587          PixelColour pc;          PixelColour pc;
588    
589          if (g_arch_match)          if (g_compatible_arch)
590          {          {
591                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
592                  REPEAT3                  REPEAT3
# Line 482  translate15to32(const uint16 * data, uin Line 636  translate15to32(const uint16 * data, uin
636          uint32 value;          uint32 value;
637          PixelColour pc;          PixelColour pc;
638    
639          if (g_arch_match)          if (g_compatible_arch)
640          {          {
641                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
642                  REPEAT4                  REPEAT4
# Line 590  translate16to24(const uint16 * data, uin Line 744  translate16to24(const uint16 * data, uin
744          uint16 pixel;          uint16 pixel;
745          PixelColour pc;          PixelColour pc;
746    
747          if (g_arch_match)          if (g_compatible_arch)
748          {          {
749                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
750                  REPEAT3                  REPEAT3
# Line 660  translate16to32(const uint16 * data, uin Line 814  translate16to32(const uint16 * data, uin
814          uint32 value;          uint32 value;
815          PixelColour pc;          PixelColour pc;
816    
817          if (g_arch_match)          if (g_compatible_arch)
818          {          {
819                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
820                  REPEAT4                  REPEAT4
# Line 789  translate24to32(const uint8 * data, uint Line 943  translate24to32(const uint8 * data, uint
943          uint32 value;          uint32 value;
944          PixelColour pc;          PixelColour pc;
945    
946          if (g_arch_match)          if (g_compatible_arch)
947          {          {
948                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
949  #ifdef NEED_ALIGN  #ifdef NEED_ALIGN
# Line 803  translate24to32(const uint8 * data, uint Line 957  translate24to32(const uint8 * data, uint
957  #else  #else
958                  REPEAT4                  REPEAT4
959                  (                  (
960                          *((uint32 *) out) = *((uint32 *) data);                   /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
961                          out += 4;                   *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
962                          data += 3;                   out += 4;
963                     data += 3;
964                  )                  )
965  #endif  #endif
966                  /* *INDENT-ON* */                  /* *INDENT-ON* */
# Line 843  translate_image(int width, int height, u Line 998  translate_image(int width, int height, u
998          uint8 *out;          uint8 *out;
999          uint8 *end;          uint8 *end;
1000    
1001          /* if server and xserver bpp match, */          /*
1002          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
1003          /* just return data */             and arch(endian) matches, no need to translate:
1004          if (g_arch_match)             just return data.
1005               Note: select_visual should've already ensured g_no_translate
1006               is only set for compatible depths, but the RDP depth might've
1007               changed during connection negotiations.
1008             */
1009            if (g_no_translate_image)
1010          {          {
1011                  if (g_depth == 15 && g_server_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
1012                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
1013                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
                         return data;  
                 if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)  
1014                          return data;                          return data;
1015          }          }
1016    
# Line 860  translate_image(int width, int height, u Line 1018  translate_image(int width, int height, u
1018          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
1019          end = out + size;          end = out + size;
1020    
1021          switch (g_server_bpp)          switch (g_server_depth)
1022          {          {
1023                  case 24:                  case 24:
1024                          switch (g_bpp)                          switch (g_bpp)
# Line 958  calculate_shifts(uint32 mask, int *shift Line 1116  calculate_shifts(uint32 mask, int *shift
1116          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
1117  }  }
1118    
1119  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1120  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1121     */
1122    static unsigned
1123    calculate_mask_weight(uint32 mask)
1124    {
1125            unsigned weight = 0;
1126            do
1127            {
1128                    weight += (mask & 1);
1129            }
1130            while (mask >>= 1);
1131            return weight;
1132    }
1133    
1134    static BOOL
1135    select_visual()
1136  {  {
         XVisualInfo vi;  
1137          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1138          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1139          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1140          XVisualInfo template;          XVisualInfo template;
1141          Bool TrueColorVisual = False;          int i;
1142            unsigned red_weight, blue_weight, green_weight;
1143    
1144          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1145          if (g_display == NULL)  
1146            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1147            if (pfm == NULL)
1148          {          {
1149                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1150                    XCloseDisplay(g_display);
1151                  return False;                  return False;
1152          }          }
1153    
1154          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 */  
1155          template.class = TrueColor;          template.class = TrueColor;
1156          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1157            g_visual = NULL;
1158            g_no_translate_image = False;
1159            g_compatible_arch = False;
1160            if (vmatches != NULL)
1161            {
1162                    for (i = 0; i < visuals_count; ++i)
1163                    {
1164                            XVisualInfo *visual_info = &vmatches[i];
1165    
1166                            /* Try to find a no-translation visual that'll
1167                               allow us to use RDP bitmaps directly as ZPixmaps. */
1168                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1169                                                   /* R5G5B5 */
1170                                                   (visual_info->red_mask == 0x7c00) &&
1171                                                   (visual_info->green_mask == 0x3e0) &&
1172                                                   (visual_info->blue_mask == 0x1f)) ||
1173                                                  ((visual_info->depth == 16) &&
1174                                                   /* R5G6B5 */
1175                                                   (visual_info->red_mask == 0xf800) &&
1176                                                   (visual_info->green_mask == 0x7e0) &&
1177                                                   (visual_info->blue_mask == 0x1f)) ||
1178                                                  ((visual_info->depth == 24) &&
1179                                                   /* R8G8B8 */
1180                                                   (visual_info->red_mask == 0xff0000) &&
1181                                                   (visual_info->green_mask == 0xff00) &&
1182                                                   (visual_info->blue_mask == 0xff))))
1183                            {
1184                                    g_visual = visual_info->visual;
1185                                    g_depth = visual_info->depth;
1186                                    g_compatible_arch = !g_host_be;
1187                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1188                                    if (g_no_translate_image)
1189                                            /* We found the best visual */
1190                                            break;
1191                            }
1192                            else
1193                            {
1194                                    g_compatible_arch = False;
1195                            }
1196    
1197          nvisuals--;                          if (visual_info->depth > 24)
1198          while (nvisuals >= 0)                          {
1199          {                                  /* Avoid 32-bit visuals and likes like the plague.
1200                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1201                  {                                     (e.g. nvidia's Composite 32-bit visual).
1202                          g_depth = (vmatches + nvisuals)->depth;                                     Most implementation offer a 24-bit visual anyway. */
1203                                    continue;
1204                            }
1205    
1206                            /* Only care for visuals, for whose BPPs (not depths!)
1207                               we have a translateXtoY function. */
1208                            BOOL can_translate_to_bpp = False;
1209                            int j;
1210                            for (j = 0; j < pixmap_formats_count; ++j)
1211                            {
1212                                    if (pfm[j].depth == visual_info->depth)
1213                                    {
1214                                            if ((pfm[j].bits_per_pixel == 16) ||
1215                                                (pfm[j].bits_per_pixel == 24) ||
1216                                                (pfm[j].bits_per_pixel == 32))
1217                                            {
1218                                                    can_translate_to_bpp = True;
1219                                            }
1220                                            break;
1221                                    }
1222                            }
1223    
1224                            /* Prefer formats which have the most colour depth.
1225                               We're being truly aristocratic here, minding each
1226                               weight on its own. */
1227                            if (can_translate_to_bpp)
1228                            {
1229                                    unsigned vis_red_weight =
1230                                            calculate_mask_weight(visual_info->red_mask);
1231                                    unsigned vis_green_weight =
1232                                            calculate_mask_weight(visual_info->green_mask);
1233                                    unsigned vis_blue_weight =
1234                                            calculate_mask_weight(visual_info->blue_mask);
1235                                    if ((vis_red_weight >= red_weight)
1236                                        && (vis_green_weight >= green_weight)
1237                                        && (vis_blue_weight >= blue_weight))
1238                                    {
1239                                            red_weight = vis_red_weight;
1240                                            green_weight = vis_green_weight;
1241                                            blue_weight = vis_blue_weight;
1242                                            g_visual = visual_info->visual;
1243                                            g_depth = visual_info->depth;
1244                                    }
1245                            }
1246                  }                  }
1247                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1248          }          }
1249    
1250          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)))  
1251          {          {
1252                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1253                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1254                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1255                    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;  
                 }  
1256          }          }
1257          else          else
1258          {          {
1259                  /* need a truecolour visual */                  template.class = PseudoColor;
1260                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1261                  {                  template.colormap_size = 256;
1262                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1263                            XGetVisualInfo(g_display,
1264                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1265                                           &template, &visuals_count);
1266                    if (vmatches == NULL)
1267                    {
1268                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1269                            XCloseDisplay(g_display);
1270                            XFree(pfm);
1271                          return False;                          return False;
1272                  }                  }
1273    
1274                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1275                  g_owncolmap = False;                  g_owncolmap = True;
1276                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1277                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
1278                  calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);          }
1279    
1280                  /* if RGB video and everything is little endian */          g_bpp = 0;
1281                  if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&          for (i = 0; i < pixmap_formats_count; ++i)
1282                      !g_xserver_be && !g_host_be)          {
1283                    XPixmapFormatValues *pf = &pfm[i];
1284                    if (pf->depth == g_depth)
1285                  {                  {
1286                          if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&                          g_bpp = pf->bits_per_pixel;
1287                                                g_blue_shift_l == 0))  
1288                            if (g_no_translate_image)
1289                          {                          {
1290                                  g_arch_match = True;                                  switch (g_server_depth)
1291                                    {
1292                                            case 15:
1293                                            case 16:
1294                                                    if (g_bpp != 16)
1295                                                            g_no_translate_image = False;
1296                                                    break;
1297                                            case 24:
1298                                                    /* Yes, this will force image translation
1299                                                       on most modern servers which use 32 bits
1300                                                       for R8G8B8. */
1301                                                    if (g_bpp != 24)
1302                                                            g_no_translate_image = False;
1303                                                    break;
1304                                            default:
1305                                                    g_no_translate_image = False;
1306                                                    break;
1307                                    }
1308                          }                          }
                 }  
1309    
1310                  if (g_arch_match)                          /* Pixmap formats list is a depth-to-bpp mapping --
1311                  {                             there's just a single entry for every depth,
1312                          DEBUG(("Architectures match, enabling little endian optimisations.\n"));                             so we can safely break here */
1313                            break;
1314                  }                  }
1315          }          }
1316            XFree(pfm);
1317            pfm = NULL;
1318            return True;
1319    }
1320    
1321          pfm = XListPixmapFormats(g_display, &i);  BOOL
1322          if (pfm != NULL)  ui_init(void)
1323    {
1324            int screen_num;
1325    
1326            g_display = XOpenDisplay(NULL);
1327            if (g_display == NULL)
1328          {          {
1329                  /* Use maximum bpp for this depth - this is generally                  error("Failed to open display: %s\n", XDisplayName(NULL));
1330                     desirable, e.g. 24 bits->32 bits. */                  return False;
                 while (i--)  
                 {  
                         if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))  
                         {  
                                 g_bpp = pfm[i].bits_per_pixel;  
                         }  
                 }  
                 XFree(pfm);  
1331          }          }
1332    
         if (g_bpp < 8)  
1333          {          {
1334                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1335                  XCloseDisplay(g_display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1336            }
1337    
1338            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1339            screen_num = DefaultScreen(g_display);
1340            g_x_socket = ConnectionNumber(g_display);
1341            g_screen = ScreenOfDisplay(g_display, screen_num);
1342            g_depth = DefaultDepthOfScreen(g_screen);
1343    
1344            if (!select_visual())
1345                  return False;                  return False;
1346    
1347            if (g_no_translate_image)
1348            {
1349                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1350            }
1351    
1352            if (g_server_depth > g_bpp)
1353            {
1354                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1355                            g_server_depth, g_bpp);
1356          }          }
1357    
1358            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1359                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1360    
1361          if (!g_owncolmap)          if (!g_owncolmap)
1362          {          {
1363                  g_xcolmap =                  g_xcolmap =
1364                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1365                                          AllocNone);                                          AllocNone);
1366                  if (g_depth <= 8)                  if (g_depth <= 8)
1367                          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);
1368          }          }
1369    
1370          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1371          {          {
1372                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1373                  g_ownbackstore = True;                  g_ownbackstore = True;
1374          }          }
1375    
# Line 1088  ui_init(void) Line 1380  ui_init(void)
1380          {          {
1381                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1382                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1383                    g_using_full_workarea = True;
1384          }          }
1385          else if (g_width < 0)          else if (g_width < 0)
1386          {          {
# Line 1101  ui_init(void) Line 1394  ui_init(void)
1394          {          {
1395                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1396                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
                 g_using_full_workarea = True;  
   
1397                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1398                  {                  {
1399                          g_width = cx;                          g_width = cx;
1400                          g_height = cy;                          g_height = cy;
1401                            g_using_full_workarea = True;
1402                  }                  }
1403                  else                  else
1404                  {                  {
1405                          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");
1406                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1407                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1408                  }                  }
1409          }          }
1410    
# Line 1127  ui_init(void) Line 1419  ui_init(void)
1419                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1420    
1421          xclip_init();          xclip_init();
1422            ewmh_init();
1423            if (g_seamless_rdp)
1424                    seamless_init();
1425    
1426          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));
1427    
1428          return True;          return True;
1429  }  }
# Line 1152  ui_deinit(void) Line 1447  ui_deinit(void)
1447          g_display = NULL;          g_display = NULL;
1448  }  }
1449    
1450    
1451    static void
1452    get_window_attribs(XSetWindowAttributes * attribs)
1453    {
1454            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1455            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1456            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1457            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1458            attribs->override_redirect = g_fullscreen;
1459            attribs->colormap = g_xcolmap;
1460    }
1461    
1462    static void
1463    get_input_mask(long *input_mask)
1464    {
1465            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1466                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1467    
1468            if (g_sendmotion)
1469                    *input_mask |= PointerMotionMask;
1470            if (g_ownbackstore)
1471                    *input_mask |= ExposureMask;
1472            if (g_fullscreen || g_grab_keyboard)
1473                    *input_mask |= EnterWindowMask;
1474            if (g_grab_keyboard)
1475                    *input_mask |= LeaveWindowMask;
1476    }
1477    
1478  BOOL  BOOL
1479  ui_create_window(void)  ui_create_window(void)
1480  {  {
# Line 1174  ui_create_window(void) Line 1497  ui_create_window(void)
1497          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1498                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1499    
1500          attribs.background_pixel = BlackPixelOfScreen(g_screen);          get_window_attribs(&attribs);
         attribs.border_pixel = WhitePixelOfScreen(g_screen);  
         attribs.backing_store = g_ownbackstore ? NotUseful : Always;  
         attribs.override_redirect = g_fullscreen;  
         attribs.colormap = g_xcolmap;  
1501    
1502          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1503                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1186  ui_create_window(void) Line 1505  ui_create_window(void)
1505                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1506    
1507          if (g_gc == NULL)          if (g_gc == NULL)
1508            {
1509                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1510                    ui_reset_clip();
1511            }
1512    
1513          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1514                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 1203  ui_create_window(void) Line 1525  ui_create_window(void)
1525          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1526    
1527          if (g_hide_decorations)          if (g_hide_decorations)
1528                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1529    
1530          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1531          if (classhints != NULL)          if (classhints != NULL)
# Line 1230  ui_create_window(void) Line 1552  ui_create_window(void)
1552                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1553          }          }
1554    
1555          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          get_input_mask(&input_mask);
                 VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;  
   
         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;  
1556    
1557          if (g_IM != NULL)          if (g_IM != NULL)
1558          {          {
# Line 1253  ui_create_window(void) Line 1565  ui_create_window(void)
1565          }          }
1566    
1567          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1568          XMapWindow(g_display, g_wnd);          if (!g_seamless_rdp)
   
         /* wait for VisibilityNotify */  
         do  
1569          {          {
1570                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMapWindow(g_display, g_wnd);
1571                    /* wait for VisibilityNotify */
1572                    do
1573                    {
1574                            XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1575                    }
1576                    while (xevent.type != VisibilityNotify);
1577                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1578          }          }
         while (xevent.type != VisibilityNotify);  
         g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;  
1579    
1580          g_focused = False;          g_focused = False;
1581          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1325  xwin_toggle_fullscreen(void) Line 1639  xwin_toggle_fullscreen(void)
1639  {  {
1640          Pixmap contents = 0;          Pixmap contents = 0;
1641    
1642            if (g_seamless_rdp)
1643                    /* Turn off SeamlessRDP mode */
1644                    ui_seamless_toggle();
1645    
1646          if (!g_ownbackstore)          if (!g_ownbackstore)
1647          {          {
1648                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1413  handle_button_event(XEvent xevent, BOOL Line 1731  handle_button_event(XEvent xevent, BOOL
1731                  }                  }
1732          }          }
1733    
1734          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1735                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1736                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1737                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1738            }
1739            else
1740            {
1741                    /* SeamlessRDP */
1742                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1743                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1744            }
1745  }  }
1746    
1747  /* Process events in Xlib queue  /* Process events in Xlib queue
# Line 1428  xwin_process_events(void) Line 1755  xwin_process_events(void)
1755          char str[256];          char str[256];
1756          Status status;          Status status;
1757          int events = 0;          int events = 0;
1758            seamless_window *sw;
1759    
1760          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1761          {          {
# Line 1442  xwin_process_events(void) Line 1770  xwin_process_events(void)
1770                  switch (xevent.type)                  switch (xevent.type)
1771                  {                  {
1772                          case VisibilityNotify:                          case VisibilityNotify:
1773                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1774                                            g_Unobscured =
1775                                                    xevent.xvisibility.state == VisibilityUnobscured;
1776    
1777                                  break;                                  break;
1778                          case ClientMessage:                          case ClientMessage:
1779                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1522  xwin_process_events(void) Line 1853  xwin_process_events(void)
1853                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1854                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1855                                                         CurrentTime);                                                         CurrentTime);
1856                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1857                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1858                                    {
1859                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1860                                                           xevent.xmotion.x, xevent.xmotion.y);
1861                                    }
1862                                    else
1863                                    {
1864                                            /* SeamlessRDP */
1865                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1866                                                           xevent.xmotion.x_root,
1867                                                           xevent.xmotion.y_root);
1868                                    }
1869                                  break;                                  break;
1870    
1871                          case FocusIn:                          case FocusIn:
# Line 1566  xwin_process_events(void) Line 1908  xwin_process_events(void)
1908                                  break;                                  break;
1909    
1910                          case Expose:                          case Expose:
1911                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
1912                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1913                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1914                                            xevent.xexpose.height,                                                    g_gc,
1915                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1916                                                      xevent.xexpose.width, xevent.xexpose.height,
1917                                                      xevent.xexpose.x, xevent.xexpose.y);
1918                                    }
1919                                    else
1920                                    {
1921                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1922                                            if (sw)
1923                                                    XCopyArea(g_display, g_backstore,
1924                                                              xevent.xexpose.window, g_gc,
1925                                                              xevent.xexpose.x + sw->xoffset,
1926                                                              xevent.xexpose.y + sw->yoffset,
1927                                                              xevent.xexpose.width,
1928                                                              xevent.xexpose.height, xevent.xexpose.x,
1929                                                              xevent.xexpose.y);
1930                                            else
1931                                            {
1932                                                    error("Expose for unknown window 0x%lx\n",
1933                                                          xevent.xexpose.window);
1934                                            }
1935                                    }
1936    
1937                                  break;                                  break;
1938    
1939                          case MappingNotify:                          case MappingNotify:
# Line 1599  xwin_process_events(void) Line 1962  xwin_process_events(void)
1962                                  break;                                  break;
1963                          case PropertyNotify:                          case PropertyNotify:
1964                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1965                                    if (xevent.xproperty.window == g_wnd)
1966                                            break;
1967                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
1968                                            break;
1969    
1970                                    /* seamless */
1971                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
1972                                    if (!sw)
1973                                            break;
1974    
1975                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
1976                                        && (xevent.xproperty.state == PropertyNewValue))
1977                                    {
1978                                            sw->state = ewmh_get_window_state(sw->wnd);
1979                                            seamless_send_state(sw->id, sw->state, 0);
1980                                    }
1981    
1982                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
1983                                        && (xevent.xproperty.state == PropertyNewValue))
1984                                    {
1985                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
1986                                            seamless_all_to_desktop(sw->wnd, sw->desktop);
1987                                    }
1988    
1989                                  break;                                  break;
1990                          case MapNotify:                          case MapNotify:
1991                                  rdp_send_client_window_status(1);                                  if (!g_seamless_rdp)
1992                                            rdp_send_client_window_status(1);
1993                                  break;                                  break;
1994                          case UnmapNotify:                          case UnmapNotify:
1995                                  rdp_send_client_window_status(0);                                  if (!g_seamless_rdp)
1996                                            rdp_send_client_window_status(0);
1997                                  break;                                  break;
1998                  }                  }
1999          }          }
# Line 1689  ui_create_bitmap(int width, int height, Line 2078  ui_create_bitmap(int width, int height,
2078          uint8 *tdata;          uint8 *tdata;
2079          int bitmap_pad;          int bitmap_pad;
2080    
2081          if (g_server_bpp == 8)          if (g_server_depth == 8)
2082          {          {
2083                  bitmap_pad = 8;                  bitmap_pad = 8;
2084          }          }
# Line 1721  ui_paint_bitmap(int x, int y, int cx, in Line 2110  ui_paint_bitmap(int x, int y, int cx, in
2110          uint8 *tdata;          uint8 *tdata;
2111          int bitmap_pad;          int bitmap_pad;
2112    
2113          if (g_server_bpp == 8)          if (g_server_depth == 8)
2114          {          {
2115                  bitmap_pad = 8;                  bitmap_pad = 8;
2116          }          }
# Line 1741  ui_paint_bitmap(int x, int y, int cx, in Line 2130  ui_paint_bitmap(int x, int y, int cx, in
2130          {          {
2131                  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);
2132                  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);
2133                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2134                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2135                                             x - sw->xoffset, y - sw->yoffset));
2136          }          }
2137          else          else
2138          {          {
2139                  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);
2140                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2141                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2142                                             x - sw->xoffset, y - sw->yoffset));
2143          }          }
2144    
2145          XFree(image);          XFree(image);
# Line 1865  ui_set_cursor(HCURSOR cursor) Line 2260  ui_set_cursor(HCURSOR cursor)
2260  {  {
2261          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2262          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2263            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2264  }  }
2265    
2266  void  void
# Line 2006  ui_set_colourmap(HCOLOURMAP map) Line 2402  ui_set_colourmap(HCOLOURMAP map)
2402                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2403          }          }
2404          else          else
2405            {
2406                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2407                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2408            }
2409  }  }
2410    
2411  void  void
2412  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2413  {  {
2414          XRectangle rect;          g_clip_rectangle.x = x;
2415            g_clip_rectangle.y = y;
2416          rect.x = x;          g_clip_rectangle.width = cx;
2417          rect.y = y;          g_clip_rectangle.height = cy;
2418          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);  
2419  }  }
2420    
2421  void  void
2422  ui_reset_clip(void)  ui_reset_clip(void)
2423  {  {
2424          XRectangle rect;          g_clip_rectangle.x = 0;
2425            g_clip_rectangle.y = 0;
2426          rect.x = 0;          g_clip_rectangle.width = g_width;
2427          rect.y = 0;          g_clip_rectangle.height = g_height;
2428          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);  
2429  }  }
2430    
2431  void  void
# Line 2111  ui_patblt(uint8 opcode, Line 2506  ui_patblt(uint8 opcode,
2506    
2507          if (g_ownbackstore)          if (g_ownbackstore)
2508                  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);
2509            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2510                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2511                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2512  }  }
2513    
2514  void  void
# Line 2121  ui_screenblt(uint8 opcode, Line 2519  ui_screenblt(uint8 opcode,
2519          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2520          if (g_ownbackstore)          if (g_ownbackstore)
2521          {          {
2522                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2523                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2524                          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);  
                 }  
2525          }          }
2526          else          else
2527          {          {
2528                  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);
2529          }          }
2530    
2531            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2532                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2533                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2534    
2535          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2536  }  }
2537    
# Line 2148  ui_memblt(uint8 opcode, Line 2542  ui_memblt(uint8 opcode,
2542  {  {
2543          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2544          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);
2545            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2546                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2547                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2548          if (g_ownbackstore)          if (g_ownbackstore)
2549                  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);
2550          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2194  ui_line(uint8 opcode, Line 2591  ui_line(uint8 opcode,
2591          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2592          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2593          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2594            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2595                                                startx - sw->xoffset, starty - sw->yoffset,
2596                                                endx - sw->xoffset, endy - sw->yoffset));
2597          if (g_ownbackstore)          if (g_ownbackstore)
2598                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2599          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2291  ui_polyline(uint8 opcode, Line 2691  ui_polyline(uint8 opcode,
2691          if (g_ownbackstore)          if (g_ownbackstore)
2692                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2693                             CoordModePrevious);                             CoordModePrevious);
2694    
2695            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2696                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2697    
2698          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2699  }  }
2700    
# Line 2446  ui_draw_text(uint8 font, uint8 flags, ui Line 2850  ui_draw_text(uint8 font, uint8 flags, ui
2850                  switch (text[i])                  switch (text[i])
2851                  {                  {
2852                          case 0xff:                          case 0xff:
2853                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2854                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2855                                  {                                  {
2856                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2857                                          exit(1);                                          for (j = 0; j < length; j++)
2858                                                    fprintf(stderr, "%02x ", text[j]);
2859                                            fprintf(stderr, "\n");
2860                                            i = length = 0;
2861                                            break;
2862                                  }                                  }
2863                                    cache_put_text(text[i + 1], text, text[i + 2]);
2864                                    i += 3;
2865                                    length -= i;
2866                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2867                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2868                                  i = 0;                                  i = 0;
2869                                  break;                                  break;
2870    
2871                          case 0xfe:                          case 0xfe:
2872                                    /* At least one byte needs to follow */
2873                                    if (i + 2 > length)
2874                                    {
2875                                            warning("Skipping short 0xfe command:");
2876                                            for (j = 0; j < length; j++)
2877                                                    fprintf(stderr, "%02x ", text[j]);
2878                                            fprintf(stderr, "\n");
2879                                            i = length = 0;
2880                                            break;
2881                                    }
2882                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2883                                  if (entry != NULL)                                  if (entry->data != NULL)
2884                                  {                                  {
2885                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2886                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2887                                          {                                          {
2888                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2889                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2496  ui_draw_text(uint8 font, uint8 flags, ui Line 2915  ui_draw_text(uint8 font, uint8 flags, ui
2915          if (g_ownbackstore)          if (g_ownbackstore)
2916          {          {
2917                  if (boxcx > 1)                  if (boxcx > 1)
2918                    {
2919                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2920                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2921                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2922                                                    (g_display, g_backstore, sw->wnd, g_gc,
2923                                                     boxx, boxy,
2924                                                     boxcx, boxcy,
2925                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2926                    }
2927                  else                  else
2928                    {
2929                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2930                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2931                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2932                                                    (g_display, g_backstore, sw->wnd, g_gc,
2933                                                     clipx, clipy,
2934                                                     clipcx, clipcy, clipx - sw->xoffset,
2935                                                     clipy - sw->yoffset));
2936                    }
2937          }          }
2938  }  }
2939    
# Line 2546  ui_desktop_restore(uint32 offset, int x, Line 2979  ui_desktop_restore(uint32 offset, int x,
2979          {          {
2980                  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);
2981                  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);
2982                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2983                                            (g_display, g_backstore, sw->wnd, g_gc,
2984                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2985          }          }
2986          else          else
2987          {          {
2988                  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);
2989                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2990                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2991                                             x - sw->xoffset, y - sw->yoffset));
2992          }          }
2993    
2994          XFree(image);          XFree(image);
# Line 2565  void Line 3004  void
3004  ui_end_update(void)  ui_end_update(void)
3005  {  {
3006  }  }
3007    
3008    void
3009    ui_seamless_toggle()
3010    {
3011            if (g_seamless_rdp)
3012            {
3013                    /* Deactivate */
3014                    while (g_seamless_windows)
3015                    {
3016                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3017                            seamless_remove_window(g_seamless_windows);
3018                    }
3019                    XMapWindow(g_display, g_wnd);
3020            }
3021            else
3022            {
3023                    /* Activate */
3024                    if (g_win_button_size)
3025                    {
3026                            error("SeamlessRDP mode cannot be activated when using single application mode\n");
3027                            return;
3028                    }
3029                    if (!g_using_full_workarea)
3030                    {
3031                            error("SeamlessRDP mode requires a session that covers the whole screen");
3032                            return;
3033                    }
3034    
3035                    XUnmapWindow(g_display, g_wnd);
3036                    seamless_send_sync();
3037            }
3038    
3039            g_seamless_rdp = !g_seamless_rdp;
3040    }
3041    
3042    void
3043    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3044    {
3045            Window wnd;
3046            XSetWindowAttributes attribs;
3047            XClassHint *classhints;
3048            XSizeHints *sizehints;
3049            long input_mask;
3050            seamless_window *sw, *sw_parent;
3051    
3052            /* Ignore CREATEs for existing windows */
3053            sw = seamless_get_window_by_id(id);
3054            if (sw)
3055                    return;
3056    
3057            get_window_attribs(&attribs);
3058            attribs.override_redirect = False;
3059    
3060            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3061                                InputOutput, g_visual,
3062                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3063                                CWBorderPixel, &attribs);
3064    
3065            XStoreName(g_display, wnd, "SeamlessRDP");
3066            ewmh_set_wm_name(wnd, "SeamlessRDP");
3067    
3068            mwm_hide_decorations(wnd);
3069    
3070            classhints = XAllocClassHint();
3071            if (classhints != NULL)
3072            {
3073                    classhints->res_name = "rdesktop";
3074                    classhints->res_class = "SeamlessRDP";
3075                    XSetClassHint(g_display, wnd, classhints);
3076                    XFree(classhints);
3077            }
3078    
3079            /* WM_NORMAL_HINTS */
3080            sizehints = XAllocSizeHints();
3081            if (sizehints != NULL)
3082            {
3083                    sizehints->flags = USPosition;
3084                    XSetWMNormalHints(g_display, wnd, sizehints);
3085                    XFree(sizehints);
3086            }
3087    
3088            /* Set WM_TRANSIENT_FOR, if necessary */
3089            if ((parent != 0x00000000) && (parent != 0xFFFFFFFF))
3090            {
3091                    sw_parent = seamless_get_window_by_id(parent);
3092                    if (sw_parent)
3093                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3094                    else
3095                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3096            }
3097    
3098    
3099            /* FIXME: Support for Input Context:s */
3100    
3101            get_input_mask(&input_mask);
3102            input_mask |= PropertyChangeMask;
3103    
3104            XSelectInput(g_display, wnd, input_mask);
3105    
3106            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3107               seamless window, we could try to close the window on the
3108               serverside, instead of terminating rdesktop */
3109            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3110    
3111            sw = malloc(sizeof(seamless_window));
3112            sw->wnd = wnd;
3113            sw->id = id;
3114            sw->parent = parent;
3115            sw->xoffset = 0;
3116            sw->yoffset = 0;
3117            sw->width = 0;
3118            sw->height = 0;
3119            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3120            sw->desktop = 0;
3121            sw->next = g_seamless_windows;
3122            g_seamless_windows = sw;
3123    }
3124    
3125    
3126    void
3127    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3128    {
3129            seamless_window *sw;
3130    
3131            sw = seamless_get_window_by_id(id);
3132            if (!sw)
3133            {
3134                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3135                    return;
3136            }
3137    
3138            XDestroyWindow(g_display, sw->wnd);
3139            seamless_remove_window(sw);
3140    }
3141    
3142    
3143    void
3144    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3145    {
3146            seamless_window *sw;
3147    
3148            sw = seamless_get_window_by_id(id);
3149            if (!sw)
3150            {
3151                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3152                    return;
3153            }
3154    
3155            if (!width || !height)
3156                    /* X11 windows must be at least 1x1 */
3157                    return;
3158    
3159            /* About MAX and MIN: Windows allows moving a window outside
3160               the desktop. This happens, for example, when maximizing an
3161               application. In this case, the position is set to something
3162               like -4,-4,1288,1032. Many WMs does not allow windows
3163               outside the desktop, however. Therefore, clip the window
3164               ourselves. */
3165            sw->xoffset = MAX(0, x);
3166            sw->yoffset = MAX(0, y);
3167            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3168            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3169    
3170            /* If we move the window in a maximized state, then KDE won't
3171               accept restoration */
3172            switch (sw->state)
3173            {
3174                    case SEAMLESSRDP_MINIMIZED:
3175                    case SEAMLESSRDP_MAXIMIZED:
3176                            return;
3177            }
3178    
3179            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3180            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3181    }
3182    
3183    
3184    void
3185    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3186    {
3187            seamless_window *sw;
3188    
3189            sw = seamless_get_window_by_id(id);
3190            if (!sw)
3191            {
3192                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3193                    return;
3194            }
3195    
3196            /* FIXME: Might want to convert the name for non-EWMH WMs */
3197            XStoreName(g_display, sw->wnd, title);
3198            ewmh_set_wm_name(sw->wnd, title);
3199    }
3200    
3201    
3202    void
3203    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3204    {
3205            seamless_window *sw;
3206    
3207            sw = seamless_get_window_by_id(id);
3208            if (!sw)
3209            {
3210                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3211                    return;
3212            }
3213    
3214            switch (state)
3215            {
3216                    case SEAMLESSRDP_NORMAL:
3217                    case SEAMLESSRDP_MAXIMIZED:
3218                            ewmh_change_state(sw->wnd, state);
3219                            XMapWindow(g_display, sw->wnd);
3220                            break;
3221                    case SEAMLESSRDP_MINIMIZED:
3222                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3223                               the Window Manager should probably just ignore the request, since
3224                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3225                               such as minimization, rather than an independent state." Besides,
3226                               XIconifyWindow is easier. */
3227                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3228                            {
3229                                    XWMHints *hints;
3230                                    hints = XAllocWMHints();
3231                                    hints->flags = StateHint;
3232                                    hints->initial_state = IconicState;
3233                                    XSetWMHints(g_display, sw->wnd, hints);
3234                                    XFree(hints);
3235                                    XMapWindow(g_display, sw->wnd);
3236                            }
3237                            else
3238                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3239                            break;
3240                    default:
3241                            warning("SeamlessRDP: Invalid state %d\n", state);
3242                            break;
3243            }
3244    
3245            /* Handle popups without parents through some ewm hints */
3246            if ((sw->state == SEAMLESSRDP_NOTYETMAPPED) && (sw->parent == 0xFFFFFFFF))
3247                    ewmh_set_window_popup(sw->wnd);
3248    
3249            sw->state = state;
3250    }
3251    
3252    
3253    void
3254    ui_seamless_syncbegin(unsigned long flags)
3255    {
3256            /* Destroy all seamless windows */
3257            while (g_seamless_windows)
3258            {
3259                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3260                    seamless_remove_window(g_seamless_windows);
3261            }
3262    }

Legend:
Removed from v.991  
changed lines
  Added in v.1144

  ViewVC Help
Powered by ViewVC 1.1.26