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

Legend:
Removed from v.1022  
changed lines
  Added in v.1142

  ViewVC Help
Powered by ViewVC 1.1.26