/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/xwin.c

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

revision 828 by stargo, Sun Mar 6 21:11:18 2005 UTC revision 1417 by jsorg71, Thu Aug 30 04:47:36 2007 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2005     Copyright (C) Matthew Chapman 1999-2007
5       Copyright 2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
6    
7     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 20  Line 21 
21    
22  #include <X11/Xlib.h>  #include <X11/Xlib.h>
23  #include <X11/Xutil.h>  #include <X11/Xutil.h>
24    #include <X11/Xproto.h>
25  #include <unistd.h>  #include <unistd.h>
26  #include <sys/time.h>  #include <sys/time.h>
27  #include <time.h>  #include <time.h>
# Line 32  extern int g_width; Line 34  extern int g_width;
34  extern int g_height;  extern int g_height;
35  extern int g_xpos;  extern int g_xpos;
36  extern int g_ypos;  extern int g_ypos;
37  extern BOOL g_sendmotion;  extern int g_pos;
38  extern BOOL g_fullscreen;  extern RD_BOOL g_sendmotion;
39  extern BOOL g_grab_keyboard;  extern RD_BOOL g_fullscreen;
40  extern BOOL g_hide_decorations;  extern RD_BOOL g_grab_keyboard;
41    extern RD_BOOL g_hide_decorations;
42  extern char g_title[];  extern char g_title[];
43  extern int g_server_bpp;  /* Color depth of the RDP session.
44       As of RDP 5.1, it may be 8, 15, 16 or 24. */
45    extern int g_server_depth;
46  extern int g_win_button_size;  extern int g_win_button_size;
47    
48  Display *g_display;  Display *g_display;
# Line 45  Time g_last_gesturetime; Line 50  Time g_last_gesturetime;
50  static int g_x_socket;  static int g_x_socket;
51  static Screen *g_screen;  static Screen *g_screen;
52  Window g_wnd;  Window g_wnd;
53    
54    /* SeamlessRDP support */
55    typedef struct _seamless_group
56    {
57            Window wnd;
58            unsigned long id;
59            unsigned int refcnt;
60    } seamless_group;
61    typedef struct _seamless_window
62    {
63            Window wnd;
64            unsigned long id;
65            unsigned long behind;
66            seamless_group *group;
67            int xoffset, yoffset;
68            int width, height;
69            int state;              /* normal/minimized/maximized. */
70            unsigned int desktop;
71            struct timeval *position_timer;
72    
73            RD_BOOL outstanding_position;
74            unsigned int outpos_serial;
75            int outpos_xoffset, outpos_yoffset;
76            int outpos_width, outpos_height;
77    
78            unsigned int icon_size;
79            unsigned int icon_offset;
80            char icon_buffer[32 * 32 * 4];
81    
82            struct _seamless_window *next;
83    } seamless_window;
84    static seamless_window *g_seamless_windows = NULL;
85    static unsigned long g_seamless_focused = 0;
86    static RD_BOOL g_seamless_started = False;      /* Server end is up and running */
87    static RD_BOOL g_seamless_active = False;       /* We are currently in seamless mode */
88    static RD_BOOL g_seamless_hidden = False;       /* Desktop is hidden on server */
89    extern RD_BOOL g_seamless_rdp;
90    
91  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
92  BOOL g_enable_compose = False;  RD_BOOL g_enable_compose = False;
93  BOOL g_Unobscured;              /* used for screenblt */  RD_BOOL g_Unobscured;           /* used for screenblt */
94  static GC g_gc = NULL;  static GC g_gc = NULL;
95  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
96  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
97    static XRectangle g_clip_rectangle;
98  static Visual *g_visual;  static Visual *g_visual;
99    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
100       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
101       as far as we're concerned. */
102  static int g_depth;  static int g_depth;
103    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
104       This may be larger than g_depth, in which case some of the bits would
105       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
106  static int g_bpp;  static int g_bpp;
107  static XIM g_IM;  static XIM g_IM;
108  static XIC g_IC;  static XIC g_IC;
109  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
110    /* Maps logical (xmodmap -pp) pointing device buttons (0-based) back
111       to physical (1-based) indices. */
112    static unsigned char g_pointer_log_to_phys_map[16];
113  static Cursor g_current_cursor;  static Cursor g_current_cursor;
114  static HCURSOR g_null_cursor = NULL;  static RD_HCURSOR g_null_cursor = NULL;
115  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
116  static BOOL g_focused;  extern Atom g_net_wm_state_atom;
117  static BOOL g_mouse_in_wnd;  extern Atom g_net_wm_desktop_atom;
118  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  static RD_BOOL g_focused;
119    static RD_BOOL g_mouse_in_wnd;
120    /* Indicates that:
121       1) visual has 15, 16 or 24 depth and the same color channel masks
122          as its RDP equivalent (implies X server is LE),
123       2) host is LE
124       This will trigger an optimization whose real value is questionable.
125    */
126    static RD_BOOL g_compatible_arch;
127    /* Indicates whether RDP's bitmaps and our XImages have the same
128       binary format. If so, we can avoid an expensive translation.
129       Note that this can be true when g_compatible_arch is false,
130       e.g.:
131      
132         RDP(LE) <-> host(BE) <-> X-Server(LE)
133        
134       ('host' is the machine running rdesktop; the host simply memcpy's
135        so its endianess doesn't matter)
136     */
137    static RD_BOOL g_no_translate_image = False;
138    
139  /* endianness */  /* endianness */
140  static BOOL g_host_be;  static RD_BOOL g_host_be;
141  static BOOL g_xserver_be;  static RD_BOOL g_xserver_be;
142  static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;  static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
143  static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;  static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
144    
145  /* software backing store */  /* software backing store */
146  extern BOOL g_ownbackstore;  extern RD_BOOL g_ownbackstore;
147  static Pixmap g_backstore = 0;  static Pixmap g_backstore = 0;
148    
149  /* Moving in single app mode */  /* Moving in single app mode */
150  static BOOL g_moving_wnd;  static RD_BOOL g_moving_wnd;
151  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
152  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
153    static RD_BOOL g_using_full_workarea = False;
154    
155  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
156  extern int g_dsp_fd;  extern RD_BOOL g_rdpsnd;
 extern BOOL g_dsp_busy;  
 extern BOOL g_rdpsnd;  
157  #endif  #endif
158    
159  /* MWM decorations */  /* MWM decorations */
# Line 90  extern BOOL g_rdpsnd; Line 161  extern BOOL g_rdpsnd;
161  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
162  typedef struct  typedef struct
163  {  {
164          uint32 flags;          unsigned long flags;
165          uint32 functions;          unsigned long functions;
166          uint32 decorations;          unsigned long decorations;
167          sint32 inputMode;          long inputMode;
168          uint32 status;          unsigned long status;
169  }  }
170  PropMotifWmHints;  PropMotifWmHints;
171    
# Line 106  typedef struct Line 177  typedef struct
177  }  }
178  PixelColour;  PixelColour;
179    
180    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
181            do { \
182                    seamless_window *sw; \
183                    XRectangle rect; \
184                    if (!g_seamless_windows) break; \
185                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
186                        rect.x = g_clip_rectangle.x - sw->xoffset; \
187                        rect.y = g_clip_rectangle.y - sw->yoffset; \
188                        rect.width = g_clip_rectangle.width; \
189                        rect.height = g_clip_rectangle.height; \
190                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
191                        func args; \
192                    } \
193                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
194            } while (0)
195    
196    static void
197    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
198    {
199            points[0].x -= xoffset;
200            points[0].y -= yoffset;
201            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
202            points[0].x += xoffset;
203            points[0].y += yoffset;
204    }
205    
206    static void
207    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
208    {
209            points[0].x -= xoffset;
210            points[0].y -= yoffset;
211            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
212            points[0].x += xoffset;
213            points[0].y += yoffset;
214    }
215    
216  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
217  { \  { \
218          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
219            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
220          if (g_ownbackstore) \          if (g_ownbackstore) \
221                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
222  }  }
# Line 119  PixelColour; Line 226  PixelColour;
226          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
227  }  }
228    
229    #define FILL_POLYGON(p,np)\
230    { \
231            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
232            if (g_ownbackstore) \
233                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
234            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
235    }
236    
237    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
238    { \
239            switch (m) \
240            { \
241                    case 0: /* Outline */ \
242                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
243                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
244                            if (g_ownbackstore) \
245                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
246                            break; \
247                    case 1: /* Filled */ \
248                            XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
249                            ON_ALL_SEAMLESS_WINDOWS(XFillArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
250                            if (g_ownbackstore) \
251                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
252                            break; \
253            } \
254    }
255    
256  /* colour maps */  /* colour maps */
257  extern BOOL g_owncolmap;  extern RD_BOOL g_owncolmap;
258  static Colormap g_xcolmap;  static Colormap g_xcolmap;
259  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
260    
261  #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] )
262  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
263  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
264    
# Line 150  static int rop2_map[] = { Line 284  static int rop2_map[] = {
284  #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]); }
285  #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); }
286    
287    static seamless_window *
288    sw_get_window_by_id(unsigned long id)
289    {
290            seamless_window *sw;
291            for (sw = g_seamless_windows; sw; sw = sw->next)
292            {
293                    if (sw->id == id)
294                            return sw;
295            }
296            return NULL;
297    }
298    
299    
300    static seamless_window *
301    sw_get_window_by_wnd(Window wnd)
302    {
303            seamless_window *sw;
304            for (sw = g_seamless_windows; sw; sw = sw->next)
305            {
306                    if (sw->wnd == wnd)
307                            return sw;
308            }
309            return NULL;
310    }
311    
312    
313  static void  static void
314  mwm_hide_decorations(void)  sw_remove_window(seamless_window * win)
315    {
316            seamless_window *sw, **prevnext = &g_seamless_windows;
317            for (sw = g_seamless_windows; sw; sw = sw->next)
318            {
319                    if (sw == win)
320                    {
321                            *prevnext = sw->next;
322                            sw->group->refcnt--;
323                            if (sw->group->refcnt == 0)
324                            {
325                                    XDestroyWindow(g_display, sw->group->wnd);
326                                    xfree(sw->group);
327                            }
328                            xfree(sw->position_timer);
329                            xfree(sw);
330                            return;
331                    }
332                    prevnext = &sw->next;
333            }
334            return;
335    }
336    
337    
338    /* Move all windows except wnd to new desktop */
339    static void
340    sw_all_to_desktop(Window wnd, unsigned int desktop)
341    {
342            seamless_window *sw;
343            for (sw = g_seamless_windows; sw; sw = sw->next)
344            {
345                    if (sw->wnd == wnd)
346                            continue;
347                    if (sw->desktop != desktop)
348                    {
349                            ewmh_move_to_desktop(sw->wnd, desktop);
350                            sw->desktop = desktop;
351                    }
352            }
353    }
354    
355    
356    /* Send our position */
357    static void
358    sw_update_position(seamless_window * sw)
359    {
360            XWindowAttributes wa;
361            int x, y;
362            Window child_return;
363            unsigned int serial;
364    
365            XGetWindowAttributes(g_display, sw->wnd, &wa);
366            XTranslateCoordinates(g_display, sw->wnd, wa.root,
367                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
368    
369            serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
370    
371            sw->outstanding_position = True;
372            sw->outpos_serial = serial;
373    
374            sw->outpos_xoffset = x;
375            sw->outpos_yoffset = y;
376            sw->outpos_width = wa.width;
377            sw->outpos_height = wa.height;
378    }
379    
380    
381    /* Check if it's time to send our position */
382    static void
383    sw_check_timers()
384    {
385            seamless_window *sw;
386            struct timeval now;
387    
388            gettimeofday(&now, NULL);
389            for (sw = g_seamless_windows; sw; sw = sw->next)
390            {
391                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
392                    {
393                            timerclear(sw->position_timer);
394                            sw_update_position(sw);
395                    }
396            }
397    }
398    
399    
400    static void
401    sw_restack_window(seamless_window * sw, unsigned long behind)
402    {
403            seamless_window *sw_above;
404    
405            /* Remove window from stack */
406            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
407            {
408                    if (sw_above->behind == sw->id)
409                            break;
410            }
411    
412            if (sw_above)
413                    sw_above->behind = sw->behind;
414    
415            /* And then add it at the new position */
416            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
417            {
418                    if (sw_above->behind == behind)
419                            break;
420            }
421    
422            if (sw_above)
423                    sw_above->behind = sw->id;
424    
425            sw->behind = behind;
426    }
427    
428    
429    static void
430    sw_handle_restack(seamless_window * sw)
431    {
432            Status status;
433            Window root, parent, *children;
434            unsigned int nchildren, i;
435            seamless_window *sw_below;
436    
437            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
438                                &root, &parent, &children, &nchildren);
439            if (!status || !nchildren)
440                    return;
441    
442            sw_below = NULL;
443    
444            i = 0;
445            while (children[i] != sw->wnd)
446            {
447                    i++;
448                    if (i >= nchildren)
449                            goto end;
450            }
451    
452            for (i++; i < nchildren; i++)
453            {
454                    sw_below = sw_get_window_by_wnd(children[i]);
455                    if (sw_below)
456                            break;
457            }
458    
459            if (!sw_below && !sw->behind)
460                    goto end;
461            if (sw_below && (sw_below->id == sw->behind))
462                    goto end;
463    
464            if (sw_below)
465            {
466                    seamless_send_zchange(sw->id, sw_below->id, 0);
467                    sw_restack_window(sw, sw_below->id);
468            }
469            else
470            {
471                    seamless_send_zchange(sw->id, 0, 0);
472                    sw_restack_window(sw, 0);
473            }
474    
475          end:
476            XFree(children);
477    }
478    
479    
480    static seamless_group *
481    sw_find_group(unsigned long id, RD_BOOL dont_create)
482    {
483            seamless_window *sw;
484            seamless_group *sg;
485            XSetWindowAttributes attribs;
486    
487            for (sw = g_seamless_windows; sw; sw = sw->next)
488            {
489                    if (sw->group->id == id)
490                            return sw->group;
491            }
492    
493            if (dont_create)
494                    return NULL;
495    
496            sg = xmalloc(sizeof(seamless_group));
497    
498            sg->wnd =
499                    XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0,
500                                  CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
501    
502            sg->id = id;
503            sg->refcnt = 0;
504    
505            return sg;
506    }
507    
508    
509    static void
510    mwm_hide_decorations(Window wnd)
511  {  {
512          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
513          Atom hintsatom;          Atom hintsatom;
# Line 168  mwm_hide_decorations(void) Line 524  mwm_hide_decorations(void)
524                  return;                  return;
525          }          }
526    
527          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
528                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
529    
530  }  }
531    
532  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 203  mwm_hide_decorations(void) Line 560  mwm_hide_decorations(void)
560  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
561                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
562    
563    /* The following macros output the same octet sequences
564       on both BE and LE hosts: */
565    
566  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
567  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
568  #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 214  static uint32 Line 574  static uint32
574  translate_colour(uint32 colour)  translate_colour(uint32 colour)
575  {  {
576          PixelColour pc;          PixelColour pc;
577          switch (g_server_bpp)          switch (g_server_depth)
578          {          {
579                  case 15:                  case 15:
580                          SPLITCOLOUR15(colour, pc);                          SPLITCOLOUR15(colour, pc);
# Line 223  translate_colour(uint32 colour) Line 583  translate_colour(uint32 colour)
583                          SPLITCOLOUR16(colour, pc);                          SPLITCOLOUR16(colour, pc);
584                          break;                          break;
585                  case 24:                  case 24:
586                    case 32:
587                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
588                          break;                          break;
589                    default:
590                            /* Avoid warning */
591                            pc.red = 0;
592                            pc.green = 0;
593                            pc.blue = 0;
594                            break;
595          }          }
596          return MAKECOLOUR(pc);          return MAKECOLOUR(pc);
597  }  }
# Line 276  translate8to16(const uint8 * data, uint8 Line 643  translate8to16(const uint8 * data, uint8
643  {  {
644          uint16 value;          uint16 value;
645    
646          if (g_arch_match)          if (g_compatible_arch)
647          {          {
648                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
649                  REPEAT2                  REPEAT2
# Line 310  translate8to24(const uint8 * data, uint8 Line 677  translate8to24(const uint8 * data, uint8
677  {  {
678          uint32 value;          uint32 value;
679    
680          if (g_xserver_be)          if (g_compatible_arch)
681          {          {
682                  while (out < end)                  while (out < end)
683                  {                  {
# Line 333  translate8to32(const uint8 * data, uint8 Line 700  translate8to32(const uint8 * data, uint8
700  {  {
701          uint32 value;          uint32 value;
702    
703          if (g_arch_match)          if (g_compatible_arch)
704          {          {
705                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
706                  REPEAT4                  REPEAT4
# Line 405  translate15to24(const uint16 * data, uin Line 772  translate15to24(const uint16 * data, uin
772          uint16 pixel;          uint16 pixel;
773          PixelColour pc;          PixelColour pc;
774    
775          if (g_arch_match)          if (g_compatible_arch)
776          {          {
777                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
778                  REPEAT3                  REPEAT3
# Line 455  translate15to32(const uint16 * data, uin Line 822  translate15to32(const uint16 * data, uin
822          uint32 value;          uint32 value;
823          PixelColour pc;          PixelColour pc;
824    
825          if (g_arch_match)          if (g_compatible_arch)
826          {          {
827                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
828                  REPEAT4                  REPEAT4
# Line 563  translate16to24(const uint16 * data, uin Line 930  translate16to24(const uint16 * data, uin
930          uint16 pixel;          uint16 pixel;
931          PixelColour pc;          PixelColour pc;
932    
933          if (g_arch_match)          if (g_compatible_arch)
934          {          {
935                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
936                  REPEAT3                  REPEAT3
# Line 633  translate16to32(const uint16 * data, uin Line 1000  translate16to32(const uint16 * data, uin
1000          uint32 value;          uint32 value;
1001          PixelColour pc;          PixelColour pc;
1002    
1003          if (g_arch_match)          if (g_compatible_arch)
1004          {          {
1005                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
1006                  REPEAT4                  REPEAT4
# Line 762  translate24to32(const uint8 * data, uint Line 1129  translate24to32(const uint8 * data, uint
1129          uint32 value;          uint32 value;
1130          PixelColour pc;          PixelColour pc;
1131    
1132          if (g_arch_match)          if (g_compatible_arch)
1133          {          {
1134                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
1135  #ifdef NEED_ALIGN  #ifdef NEED_ALIGN
# Line 776  translate24to32(const uint8 * data, uint Line 1143  translate24to32(const uint8 * data, uint
1143  #else  #else
1144                  REPEAT4                  REPEAT4
1145                  (                  (
1146                          *((uint32 *) out) = *((uint32 *) data);                   /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
1147                          out += 4;                   *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
1148                          data += 3;                   out += 4;
1149                     data += 3;
1150                  )                  )
1151  #endif  #endif
1152                  /* *INDENT-ON* */                  /* *INDENT-ON* */
# Line 816  translate_image(int width, int height, u Line 1184  translate_image(int width, int height, u
1184          uint8 *out;          uint8 *out;
1185          uint8 *end;          uint8 *end;
1186    
1187          /* if server and xserver bpp match, */          /*
1188          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
1189          /* just return data */             and arch(endian) matches, no need to translate:
1190          if (g_arch_match)             just return data.
1191               Note: select_visual should've already ensured g_no_translate
1192               is only set for compatible depths, but the RDP depth might've
1193               changed during connection negotiations.
1194             */
1195    
1196            /* todo */
1197            if (g_server_depth == 32 && g_depth == 24)
1198          {          {
1199                  if (g_depth == 15 && g_server_bpp == 15)                  return data;
1200                          return data;          }
1201                  if (g_depth == 16 && g_server_bpp == 16)  
1202                          return data;          if (g_no_translate_image)
1203                  if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)          {
1204                    if ((g_depth == 15 && g_server_depth == 15) ||
1205                        (g_depth == 16 && g_server_depth == 16) ||
1206                        (g_depth == 24 && g_server_depth == 24))
1207                          return data;                          return data;
1208          }          }
1209    
# Line 833  translate_image(int width, int height, u Line 1211  translate_image(int width, int height, u
1211          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
1212          end = out + size;          end = out + size;
1213    
1214          switch (g_server_bpp)          switch (g_server_depth)
1215          {          {
1216                  case 24:                  case 24:
1217                          switch (g_bpp)                          switch (g_bpp)
# Line 898  translate_image(int width, int height, u Line 1276  translate_image(int width, int height, u
1276          return out;          return out;
1277  }  }
1278    
1279  BOOL  static void
1280    xwin_refresh_pointer_map(void)
1281    {
1282            unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)];
1283            int i, pointer_buttons;
1284    
1285            pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map));
1286            for (i = 0; i < pointer_buttons; ++i)
1287            {
1288                    /* This might produce multiple logical buttons mapping
1289                       to a single physical one, but hey, that's
1290                       life... */
1291                    g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
1292            }
1293    }
1294    
1295    RD_BOOL
1296  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1297  {  {
1298          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
# Line 931  calculate_shifts(uint32 mask, int *shift Line 1325  calculate_shifts(uint32 mask, int *shift
1325          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
1326  }  }
1327    
1328  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1329  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1330     */
1331    static unsigned
1332    calculate_mask_weight(uint32 mask)
1333    {
1334            unsigned weight = 0;
1335            do
1336            {
1337                    weight += (mask & 1);
1338            }
1339            while (mask >>= 1);
1340            return weight;
1341    }
1342    
1343    static RD_BOOL
1344    select_visual(int screen_num)
1345  {  {
         XVisualInfo vi;  
1346          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1347          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1348          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1349          XVisualInfo template;          XVisualInfo template;
1350          Bool TrueColorVisual = False;          int i;
1351            unsigned red_weight, blue_weight, green_weight;
1352    
1353          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1354          if (g_display == NULL)  
1355            if (g_server_depth == -1)
1356          {          {
1357                  error("Failed to open display: %s\n", XDisplayName(NULL));                  g_server_depth = DisplayPlanes(g_display, DefaultScreen(g_display));
                 return False;  
1358          }          }
1359    
1360          screen_num = DefaultScreen(g_display);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1361          g_x_socket = ConnectionNumber(g_display);          if (pfm == NULL)
1362          g_screen = ScreenOfDisplay(g_display, screen_num);          {
1363          g_depth = DefaultDepthOfScreen(g_screen);                  error("Unable to get list of pixmap formats from display.\n");
1364                    XCloseDisplay(g_display);
1365                    return False;
1366            }
1367    
1368          /* Search for best TrueColor depth */          /* Search for best TrueColor visual */
1369          template.class = TrueColor;          template.class = TrueColor;
1370          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          template.screen = screen_num;
1371            vmatches =
1372                    XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template,
1373                                   &visuals_count);
1374            g_visual = NULL;
1375            g_no_translate_image = False;
1376            g_compatible_arch = False;
1377            if (vmatches != NULL)
1378            {
1379                    for (i = 0; i < visuals_count; ++i)
1380                    {
1381                            XVisualInfo *visual_info = &vmatches[i];
1382                            RD_BOOL can_translate_to_bpp = False;
1383                            int j;
1384    
1385                            /* Try to find a no-translation visual that'll
1386                               allow us to use RDP bitmaps directly as ZPixmaps. */
1387                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1388                                                   /* R5G5B5 */
1389                                                   (visual_info->red_mask == 0x7c00) &&
1390                                                   (visual_info->green_mask == 0x3e0) &&
1391                                                   (visual_info->blue_mask == 0x1f)) ||
1392                                                  ((visual_info->depth == 16) &&
1393                                                   /* R5G6B5 */
1394                                                   (visual_info->red_mask == 0xf800) &&
1395                                                   (visual_info->green_mask == 0x7e0) &&
1396                                                   (visual_info->blue_mask == 0x1f)) ||
1397                                                  ((visual_info->depth == 24) &&
1398                                                   /* R8G8B8 */
1399                                                   (visual_info->red_mask == 0xff0000) &&
1400                                                   (visual_info->green_mask == 0xff00) &&
1401                                                   (visual_info->blue_mask == 0xff))))
1402                            {
1403                                    g_visual = visual_info->visual;
1404                                    g_depth = visual_info->depth;
1405                                    g_compatible_arch = !g_host_be;
1406                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1407                                    if (g_no_translate_image)
1408                                            /* We found the best visual */
1409                                            break;
1410                            }
1411                            else
1412                            {
1413                                    g_compatible_arch = False;
1414                            }
1415    
1416                            if (visual_info->depth > 24)
1417                            {
1418                                    /* Avoid 32-bit visuals and likes like the plague.
1419                                       They're either untested or proven to work bad
1420                                       (e.g. nvidia's Composite 32-bit visual).
1421                                       Most implementation offer a 24-bit visual anyway. */
1422                                    continue;
1423                            }
1424    
1425          nvisuals--;                          /* Only care for visuals, for whose BPPs (not depths!)
1426          while (nvisuals >= 0)                             we have a translateXtoY function. */
1427          {                          for (j = 0; j < pixmap_formats_count; ++j)
1428                  if ((vmatches + nvisuals)->depth > g_depth)                          {
1429                  {                                  if (pfm[j].depth == visual_info->depth)
1430                          g_depth = (vmatches + nvisuals)->depth;                                  {
1431                                            if ((pfm[j].bits_per_pixel == 16) ||
1432                                                (pfm[j].bits_per_pixel == 24) ||
1433                                                (pfm[j].bits_per_pixel == 32))
1434                                            {
1435                                                    can_translate_to_bpp = True;
1436                                            }
1437                                            break;
1438                                    }
1439                            }
1440    
1441                            /* Prefer formats which have the most colour depth.
1442                               We're being truly aristocratic here, minding each
1443                               weight on its own. */
1444                            if (can_translate_to_bpp)
1445                            {
1446                                    unsigned vis_red_weight =
1447                                            calculate_mask_weight(visual_info->red_mask);
1448                                    unsigned vis_green_weight =
1449                                            calculate_mask_weight(visual_info->green_mask);
1450                                    unsigned vis_blue_weight =
1451                                            calculate_mask_weight(visual_info->blue_mask);
1452                                    if ((vis_red_weight >= red_weight)
1453                                        && (vis_green_weight >= green_weight)
1454                                        && (vis_blue_weight >= blue_weight))
1455                                    {
1456                                            red_weight = vis_red_weight;
1457                                            green_weight = vis_green_weight;
1458                                            blue_weight = vis_blue_weight;
1459                                            g_visual = visual_info->visual;
1460                                            g_depth = visual_info->depth;
1461                                    }
1462                            }
1463                  }                  }
1464                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1465          }          }
1466    
1467          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)))  
1468          {          {
1469                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1470                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1471                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1472                    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;  
                 }  
1473          }          }
1474          else          else
1475          {          {
1476                  /* need a truecolour visual */                  template.class = PseudoColor;
1477                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1478                  {                  template.colormap_size = 256;
1479                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1480                            XGetVisualInfo(g_display,
1481                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1482                                           &template, &visuals_count);
1483                    if (vmatches == NULL)
1484                    {
1485                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1486                            XCloseDisplay(g_display);
1487                            XFree(pfm);
1488                          return False;                          return False;
1489                  }                  }
1490    
1491                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1492                  g_owncolmap = False;                  g_owncolmap = True;
1493                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1494                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
1495                  calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);          }
1496    
1497                  /* if RGB video and everything is little endian */          g_bpp = 0;
1498                  if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&          for (i = 0; i < pixmap_formats_count; ++i)
1499                      !g_xserver_be && !g_host_be)          {
1500                    XPixmapFormatValues *pf = &pfm[i];
1501                    if (pf->depth == g_depth)
1502                  {                  {
1503                          if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&                          g_bpp = pf->bits_per_pixel;
1504                                                g_blue_shift_l == 0))  
1505                            if (g_no_translate_image)
1506                          {                          {
1507                                  g_arch_match = True;                                  switch (g_server_depth)
1508                                    {
1509                                            case 15:
1510                                            case 16:
1511                                                    if (g_bpp != 16)
1512                                                            g_no_translate_image = False;
1513                                                    break;
1514                                            case 24:
1515                                                    /* Yes, this will force image translation
1516                                                       on most modern servers which use 32 bits
1517                                                       for R8G8B8. */
1518                                                    if (g_bpp != 24)
1519                                                            g_no_translate_image = False;
1520                                                    break;
1521                                            default:
1522                                                    g_no_translate_image = False;
1523                                                    break;
1524                                    }
1525                          }                          }
                 }  
1526    
1527                  if (g_arch_match)                          /* Pixmap formats list is a depth-to-bpp mapping --
1528                  {                             there's just a single entry for every depth,
1529                          DEBUG(("Architectures match, enabling little endian optimisations.\n"));                             so we can safely break here */
1530                            break;
1531                  }                  }
1532          }          }
1533            XFree(pfm);
1534            pfm = NULL;
1535            return True;
1536    }
1537    
1538    static XErrorHandler g_old_error_handler;
1539    
1540          pfm = XListPixmapFormats(g_display, &i);  static int
1541          if (pfm != NULL)  error_handler(Display * dpy, XErrorEvent * eev)
1542    {
1543            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1544          {          {
1545                  /* Use maximum bpp for this depth - this is generally                  fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1546                     desirable, e.g. 24 bits->32 bits. */                  fprintf(stderr,
1547                  while (i--)                          "This is most likely caused by a broken window manager (commonly KWin).\n");
1548                  {                  return 0;
                         if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))  
                         {  
                                 g_bpp = pfm[i].bits_per_pixel;  
                         }  
                 }  
                 XFree(pfm);  
1549          }          }
1550    
1551          if (g_bpp < 8)          return g_old_error_handler(dpy, eev);
1552    }
1553    
1554    RD_BOOL
1555    ui_init(void)
1556    {
1557            int screen_num;
1558    
1559            g_display = XOpenDisplay(NULL);
1560            if (g_display == NULL)
1561          {          {
1562                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
1563                  XCloseDisplay(g_display);                  return False;
1564            }
1565    
1566            {
1567                    uint16 endianess_test = 1;
1568                    g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test));
1569            }
1570    
1571            g_old_error_handler = XSetErrorHandler(error_handler);
1572            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1573            screen_num = DefaultScreen(g_display);
1574            g_x_socket = ConnectionNumber(g_display);
1575            g_screen = ScreenOfDisplay(g_display, screen_num);
1576            g_depth = DefaultDepthOfScreen(g_screen);
1577    
1578            if (!select_visual(screen_num))
1579                  return False;                  return False;
1580    
1581            if (g_no_translate_image)
1582            {
1583                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1584            }
1585    
1586            if (g_server_depth > g_bpp)
1587            {
1588                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1589                            g_server_depth, g_bpp);
1590          }          }
1591    
1592            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1593                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1594    
1595          if (!g_owncolmap)          if (!g_owncolmap)
1596          {          {
1597                  g_xcolmap =                  g_xcolmap =
1598                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1599                                          AllocNone);                                          AllocNone);
1600                  if (g_depth <= 8)                  if (g_depth <= 8)
1601                          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);
1602          }          }
1603    
1604          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1605          {          {
1606                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1607                  g_ownbackstore = True;                  g_ownbackstore = True;
1608          }          }
1609    
# Line 1061  ui_init(void) Line 1614  ui_init(void)
1614          {          {
1615                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1616                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1617                    g_using_full_workarea = True;
1618          }          }
1619          else if (g_width < 0)          else if (g_width < 0)
1620          {          {
1621                  /* Percent of screen */                  /* Percent of screen */
1622                    if (-g_width >= 100)
1623                            g_using_full_workarea = True;
1624                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1625                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1626          }          }
# Line 1072  ui_init(void) Line 1628  ui_init(void)
1628          {          {
1629                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1630                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1631                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1632                  {                  {
1633                          g_width = cx;                          g_width = cx;
1634                          g_height = cy;                          g_height = cy;
1635                            g_using_full_workarea = True;
1636                  }                  }
1637                  else                  else
1638                  {                  {
1639                          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");
1640                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1641                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1642                  }                  }
1643          }          }
1644    
# Line 1090  ui_init(void) Line 1646  ui_init(void)
1646          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1647    
1648          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1649            xwin_refresh_pointer_map();
1650    
1651          xkeymap_init();          xkeymap_init();
1652    
# Line 1097  ui_init(void) Line 1654  ui_init(void)
1654                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1655    
1656          xclip_init();          xclip_init();
1657            ewmh_init();
1658            if (g_seamless_rdp)
1659                    seamless_init();
1660    
1661          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));
1662    
1663          return True;          return True;
1664  }  }
# Line 1106  ui_init(void) Line 1666  ui_init(void)
1666  void  void
1667  ui_deinit(void)  ui_deinit(void)
1668  {  {
1669            while (g_seamless_windows)
1670            {
1671                    XDestroyWindow(g_display, g_seamless_windows->wnd);
1672                    sw_remove_window(g_seamless_windows);
1673            }
1674    
1675            xclip_deinit();
1676    
1677          if (g_IM != NULL)          if (g_IM != NULL)
1678                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1679    
# Line 1122  ui_deinit(void) Line 1690  ui_deinit(void)
1690          g_display = NULL;          g_display = NULL;
1691  }  }
1692    
1693  BOOL  
1694    static void
1695    get_window_attribs(XSetWindowAttributes * attribs)
1696    {
1697            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1698            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1699            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1700            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1701            attribs->override_redirect = g_fullscreen;
1702            attribs->colormap = g_xcolmap;
1703    }
1704    
1705    static void
1706    get_input_mask(long *input_mask)
1707    {
1708            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1709                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1710    
1711            if (g_sendmotion)
1712                    *input_mask |= PointerMotionMask;
1713            if (g_ownbackstore)
1714                    *input_mask |= ExposureMask;
1715            if (g_fullscreen || g_grab_keyboard)
1716                    *input_mask |= EnterWindowMask;
1717            if (g_grab_keyboard)
1718                    *input_mask |= LeaveWindowMask;
1719    }
1720    
1721    RD_BOOL
1722  ui_create_window(void)  ui_create_window(void)
1723  {  {
1724          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
# Line 1138  ui_create_window(void) Line 1734  ui_create_window(void)
1734          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1735          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1736    
1737          attribs.background_pixel = BlackPixelOfScreen(g_screen);          /* Handle -x-y portion of geometry string */
1738          attribs.border_pixel = WhitePixelOfScreen(g_screen);          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1739          attribs.backing_store = g_ownbackstore ? NotUseful : Always;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1740          attribs.override_redirect = g_fullscreen;          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1741          attribs.colormap = g_xcolmap;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1742    
1743            get_window_attribs(&attribs);
1744    
1745          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,
1746                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1150  ui_create_window(void) Line 1748  ui_create_window(void)
1748                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1749    
1750          if (g_gc == NULL)          if (g_gc == NULL)
1751            {
1752                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1753                    ui_reset_clip();
1754            }
1755    
1756          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1757                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 1165  ui_create_window(void) Line 1766  ui_create_window(void)
1766          }          }
1767    
1768          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1769            ewmh_set_wm_name(g_wnd, g_title);
1770    
1771          if (g_hide_decorations)          if (g_hide_decorations)
1772                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1773    
1774          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1775          if (classhints != NULL)          if (classhints != NULL)
# Line 1181  ui_create_window(void) Line 1783  ui_create_window(void)
1783          if (sizehints)          if (sizehints)
1784          {          {
1785                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1786                    if (g_pos)
1787                            sizehints->flags |= PPosition;
1788                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1789                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1790                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
# Line 1192  ui_create_window(void) Line 1796  ui_create_window(void)
1796                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1797          }          }
1798    
1799          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          get_input_mask(&input_mask);
                 VisibilityChangeMask | FocusChangeMask;  
   
         if (g_sendmotion)  
                 input_mask |= PointerMotionMask;  
         if (g_ownbackstore)  
                 input_mask |= ExposureMask;  
         if (g_fullscreen || g_grab_keyboard)  
                 input_mask |= EnterWindowMask;  
         if (g_grab_keyboard)  
                 input_mask |= LeaveWindowMask;  
1800    
1801          if (g_IM != NULL)          if (g_IM != NULL)
1802          {          {
# Line 1287  xwin_toggle_fullscreen(void) Line 1881  xwin_toggle_fullscreen(void)
1881  {  {
1882          Pixmap contents = 0;          Pixmap contents = 0;
1883    
1884            if (g_seamless_active)
1885                    /* Turn off SeamlessRDP mode */
1886                    ui_seamless_toggle();
1887    
1888          if (!g_ownbackstore)          if (!g_ownbackstore)
1889          {          {
1890                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1307  xwin_toggle_fullscreen(void) Line 1905  xwin_toggle_fullscreen(void)
1905          }          }
1906  }  }
1907    
1908  /* Process all events in Xlib queue  static void
1909    handle_button_event(XEvent xevent, RD_BOOL down)
1910    {
1911            uint16 button, flags = 0;
1912            g_last_gesturetime = xevent.xbutton.time;
1913            /* Reverse the pointer button mapping, e.g. in the case of
1914               "left-handed mouse mode"; the RDP session expects to
1915               receive physical buttons (true in mstsc as well) and
1916               logical button behavior depends on the remote desktop's own
1917               mouse settings */
1918            xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
1919            button = xkeymap_translate_button(xevent.xbutton.button);
1920            if (button == 0)
1921                    return;
1922    
1923            if (down)
1924                    flags = MOUSE_FLAG_DOWN;
1925    
1926            /* Stop moving window when button is released, regardless of cursor position */
1927            if (g_moving_wnd && (xevent.type == ButtonRelease))
1928                    g_moving_wnd = False;
1929    
1930            /* If win_button_size is nonzero, enable single app mode */
1931            if (xevent.xbutton.y < g_win_button_size)
1932            {
1933                    /*  Check from right to left: */
1934                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1935                    {
1936                            /* The close button, continue */
1937                            ;
1938                    }
1939                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1940                    {
1941                            /* The maximize/restore button. Do not send to
1942                               server.  It might be a good idea to change the
1943                               cursor or give some other visible indication
1944                               that rdesktop inhibited this click */
1945                            if (xevent.type == ButtonPress)
1946                                    return;
1947                    }
1948                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1949                    {
1950                            /* The minimize button. Iconify window. */
1951                            if (xevent.type == ButtonRelease)
1952                            {
1953                                    /* Release the mouse button outside the minimize button, to prevent the
1954                                       actual minimazation to happen */
1955                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1956                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1957                                    return;
1958                            }
1959                    }
1960                    else if (xevent.xbutton.x <= g_win_button_size)
1961                    {
1962                            /* The system menu. Ignore. */
1963                            if (xevent.type == ButtonPress)
1964                                    return;
1965                    }
1966                    else
1967                    {
1968                            /* The title bar. */
1969                            if (xevent.type == ButtonPress)
1970                            {
1971                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1972                                    {
1973                                            g_moving_wnd = True;
1974                                            g_move_x_offset = xevent.xbutton.x;
1975                                            g_move_y_offset = xevent.xbutton.y;
1976                                    }
1977                                    return;
1978                            }
1979                    }
1980            }
1981    
1982            if (xevent.xmotion.window == g_wnd)
1983            {
1984                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1985                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1986            }
1987            else
1988            {
1989                    /* SeamlessRDP */
1990                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1991                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1992            }
1993    }
1994    
1995    
1996    /* Process events in Xlib queue
1997     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1998  static int  static int
1999  xwin_process_events(void)  xwin_process_events(void)
2000  {  {
2001          XEvent xevent;          XEvent xevent;
2002          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
2003          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
2004          char str[256];          char str[256];
2005          Status status;          Status status;
2006            int events = 0;
2007            seamless_window *sw;
2008    
2009          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
2010          {          {
2011                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
2012    
# Line 1330  xwin_process_events(void) Line 2016  xwin_process_events(void)
2016                          continue;                          continue;
2017                  }                  }
2018    
                 flags = 0;  
   
2019                  switch (xevent.type)                  switch (xevent.type)
2020                  {                  {
2021                          case VisibilityNotify:                          case VisibilityNotify:
2022                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
2023                                            g_Unobscured =
2024                                                    xevent.xvisibility.state == VisibilityUnobscured;
2025    
2026                                  break;                                  break;
2027                          case ClientMessage:                          case ClientMessage:
2028                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1368  xwin_process_events(void) Line 2055  xwin_process_events(void)
2055                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
2056                                  }                                  }
2057    
2058                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
2059                                             get_ksname(keysym)));                                             get_ksname(keysym)));
2060    
2061                                  ev_time = time(NULL);                                  ev_time = time(NULL);
2062                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
2063                                          break;                                          break;
2064    
2065                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
2066                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, True, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 save_remote_modifiers(tr.scancode);  
                                 ensure_remote_modifiers(ev_time, tr);  
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);  
                                 restore_remote_modifiers(ev_time, tr.scancode);  
   
2067                                  break;                                  break;
2068    
2069                          case KeyRelease:                          case KeyRelease:
# Line 1393  xwin_process_events(void) Line 2071  xwin_process_events(void)
2071                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
2072                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
2073    
2074                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
2075                                             get_ksname(keysym)));                                             get_ksname(keysym)));
2076    
2077                                  ev_time = time(NULL);                                  ev_time = time(NULL);
2078                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
2079                                          break;                                          break;
2080    
2081                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
2082                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
2083                                  break;                                  break;
2084    
2085                          case ButtonPress:                          case ButtonPress:
2086                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
2087                                  /* fall through */                                  break;
2088    
2089                          case ButtonRelease:                          case ButtonRelease:
2090                                  g_last_gesturetime = xevent.xbutton.time;                                  handle_button_event(xevent, False);
                                 button = xkeymap_translate_button(xevent.xbutton.button);  
                                 if (button == 0)  
                                         break;  
   
                                 /* If win_button_size is nonzero, enable single app mode */  
                                 if (xevent.xbutton.y < g_win_button_size)  
                                 {  
                                         /* Stop moving window when button is released, regardless of cursor position */  
                                         if (g_moving_wnd && (xevent.type == ButtonRelease))  
                                                 g_moving_wnd = False;  
   
                                         /*  Check from right to left: */  
   
                                         if (xevent.xbutton.x >= g_width - g_win_button_size)  
                                         {  
                                                 /* The close button, continue */  
                                                 ;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 2)  
                                         {  
                                                 /* The maximize/restore button. Do not send to  
                                                    server.  It might be a good idea to change the  
                                                    cursor or give some other visible indication  
                                                    that rdesktop inhibited this click */  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 3)  
                                         {  
                                                 /* The minimize button. Iconify window. */  
                                                 XIconifyWindow(g_display, g_wnd,  
                                                                DefaultScreen(g_display));  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x <= g_win_button_size)  
                                         {  
                                                 /* The system menu. Ignore. */  
                                                 break;  
                                         }  
                                         else  
                                         {  
                                                 /* The title bar. */  
                                                 if ((xevent.type == ButtonPress) && !g_fullscreen  
                                                     && g_hide_decorations)  
                                                 {  
                                                         g_moving_wnd = True;  
                                                         g_move_x_offset = xevent.xbutton.x;  
                                                         g_move_y_offset = xevent.xbutton.y;  
                                                 }  
                                                 break;  
   
                                         }  
                                 }  
   
                                 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
                                                flags | button, xevent.xbutton.x, xevent.xbutton.y);  
2091                                  break;                                  break;
2092    
2093                          case MotionNotify:                          case MotionNotify:
# Line 1486  xwin_process_events(void) Line 2102  xwin_process_events(void)
2102                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
2103                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2104                                                         CurrentTime);                                                         CurrentTime);
2105                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
2106                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
2107                                    {
2108                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2109                                                           xevent.xmotion.x, xevent.xmotion.y);
2110                                    }
2111                                    else
2112                                    {
2113                                            /* SeamlessRDP */
2114                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2115                                                           xevent.xmotion.x_root,
2116                                                           xevent.xmotion.y_root);
2117                                    }
2118                                  break;                                  break;
2119    
2120                          case FocusIn:                          case FocusIn:
# Line 1498  xwin_process_events(void) Line 2125  xwin_process_events(void)
2125                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2126                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2127                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2128    
2129                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2130                                    if (!sw)
2131                                            break;
2132    
2133                                    if (sw->id != g_seamless_focused)
2134                                    {
2135                                            seamless_send_focus(sw->id, 0);
2136                                            g_seamless_focused = sw->id;
2137                                    }
2138                                  break;                                  break;
2139    
2140                          case FocusOut:                          case FocusOut:
# Line 1530  xwin_process_events(void) Line 2167  xwin_process_events(void)
2167                                  break;                                  break;
2168    
2169                          case Expose:                          case Expose:
2170                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2171                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2172                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2173                                            xevent.xexpose.height,                                                    g_gc,
2174                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2175                                                      xevent.xexpose.width, xevent.xexpose.height,
2176                                                      xevent.xexpose.x, xevent.xexpose.y);
2177                                    }
2178                                    else
2179                                    {
2180                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2181                                            if (!sw)
2182                                                    break;
2183                                            XCopyArea(g_display, g_backstore,
2184                                                      xevent.xexpose.window, g_gc,
2185                                                      xevent.xexpose.x + sw->xoffset,
2186                                                      xevent.xexpose.y + sw->yoffset,
2187                                                      xevent.xexpose.width,
2188                                                      xevent.xexpose.height, xevent.xexpose.x,
2189                                                      xevent.xexpose.y);
2190                                    }
2191    
2192                                  break;                                  break;
2193    
2194                          case MappingNotify:                          case MappingNotify:
# Line 1549  xwin_process_events(void) Line 2203  xwin_process_events(void)
2203                                          XFreeModifiermap(g_mod_map);                                          XFreeModifiermap(g_mod_map);
2204                                          g_mod_map = XGetModifierMapping(g_display);                                          g_mod_map = XGetModifierMapping(g_display);
2205                                  }                                  }
2206    
2207                                    if (xevent.xmapping.request == MappingPointer)
2208                                    {
2209                                            xwin_refresh_pointer_map();
2210                                    }
2211    
2212                                  break;                                  break;
2213    
2214                                  /* clipboard stuff */                                  /* clipboard stuff */
# Line 1563  xwin_process_events(void) Line 2223  xwin_process_events(void)
2223                                  break;                                  break;
2224                          case PropertyNotify:                          case PropertyNotify:
2225                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2226                                    if (xevent.xproperty.window == g_wnd)
2227                                            break;
2228                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2229                                            break;
2230    
2231                                    /* seamless */
2232                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2233                                    if (!sw)
2234                                            break;
2235    
2236                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2237                                        && (xevent.xproperty.state == PropertyNewValue))
2238                                    {
2239                                            sw->state = ewmh_get_window_state(sw->wnd);
2240                                            seamless_send_state(sw->id, sw->state, 0);
2241                                    }
2242    
2243                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2244                                        && (xevent.xproperty.state == PropertyNewValue))
2245                                    {
2246                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2247                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2248                                    }
2249    
2250                                    break;
2251                            case MapNotify:
2252                                    if (!g_seamless_active)
2253                                            rdp_send_client_window_status(1);
2254                                    break;
2255                            case UnmapNotify:
2256                                    if (!g_seamless_active)
2257                                            rdp_send_client_window_status(0);
2258                                    break;
2259                            case ConfigureNotify:
2260                                    if (!g_seamless_active)
2261                                            break;
2262    
2263                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2264                                    if (!sw)
2265                                            break;
2266    
2267                                    gettimeofday(sw->position_timer, NULL);
2268                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2269                                        1000000)
2270                                    {
2271                                            sw->position_timer->tv_usec +=
2272                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2273                                            sw->position_timer->tv_sec += 1;
2274                                    }
2275                                    else
2276                                    {
2277                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2278                                    }
2279    
2280                                    sw_handle_restack(sw);
2281                                  break;                                  break;
2282                  }                  }
2283          }          }
# Line 1577  ui_select(int rdp_socket) Line 2292  ui_select(int rdp_socket)
2292          int n;          int n;
2293          fd_set rfds, wfds;          fd_set rfds, wfds;
2294          struct timeval tv;          struct timeval tv;
2295          BOOL s_timeout = False;          RD_BOOL s_timeout = False;
2296    
2297          while (True)          while (True)
2298          {          {
# Line 1587  ui_select(int rdp_socket) Line 2302  ui_select(int rdp_socket)
2302                          /* User quit */                          /* User quit */
2303                          return 0;                          return 0;
2304    
2305                    if (g_seamless_active)
2306                            sw_check_timers();
2307    
2308                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2309                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2310                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
2311                  FD_SET(g_x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
2312    
 #ifdef WITH_RDPSND  
                 /* FIXME: there should be an API for registering fds */  
                 if (g_dsp_busy)  
                 {  
                         FD_SET(g_dsp_fd, &wfds);  
                         n = (g_dsp_fd > n) ? g_dsp_fd : n;  
                 }  
 #endif  
2313                  /* default timeout */                  /* default timeout */
2314                  tv.tv_sec = 60;                  tv.tv_sec = 60;
2315                  tv.tv_usec = 0;                  tv.tv_usec = 0;
2316    
2317    #ifdef WITH_RDPSND
2318                    rdpsnd_add_fds(&n, &rfds, &wfds, &tv);
2319    #endif
2320    
2321                  /* add redirection handles */                  /* add redirection handles */
2322                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2323                    seamless_select_timeout(&tv);
2324    
2325                  n++;                  n++;
2326    
# Line 1615  ui_select(int rdp_socket) Line 2330  ui_select(int rdp_socket)
2330                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2331    
2332                          case 0:                          case 0:
2333    #ifdef WITH_RDPSND
2334                                    rdpsnd_check_fds(&rfds, &wfds);
2335    #endif
2336    
2337                                  /* Abort serial read calls */                                  /* Abort serial read calls */
2338                                  if (s_timeout)                                  if (s_timeout)
2339                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);                                          rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True);
2340                                  continue;                                  continue;
2341                  }                  }
2342    
2343                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);  #ifdef WITH_RDPSND
2344                    rdpsnd_check_fds(&rfds, &wfds);
2345    #endif
2346    
2347                    rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False);
2348    
2349                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2350                          return 1;                          return 1;
2351    
 #ifdef WITH_RDPSND  
                 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))  
                         wave_out_play();  
 #endif  
2352          }          }
2353  }  }
2354    
# Line 1639  ui_move_pointer(int x, int y) Line 2358  ui_move_pointer(int x, int y)
2358          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
2359  }  }
2360    
2361  HBITMAP  RD_HBITMAP
2362  ui_create_bitmap(int width, int height, uint8 * data)  ui_create_bitmap(int width, int height, uint8 * data)
2363  {  {
2364          XImage *image;          XImage *image;
# Line 1647  ui_create_bitmap(int width, int height, Line 2366  ui_create_bitmap(int width, int height,
2366          uint8 *tdata;          uint8 *tdata;
2367          int bitmap_pad;          int bitmap_pad;
2368    
2369          if (g_server_bpp == 8)          if (g_server_depth == 8)
2370          {          {
2371                  bitmap_pad = 8;                  bitmap_pad = 8;
2372          }          }
# Line 1669  ui_create_bitmap(int width, int height, Line 2388  ui_create_bitmap(int width, int height,
2388          XFree(image);          XFree(image);
2389          if (tdata != data)          if (tdata != data)
2390                  xfree(tdata);                  xfree(tdata);
2391          return (HBITMAP) bitmap;          return (RD_HBITMAP) bitmap;
2392  }  }
2393    
2394  void  void
# Line 1679  ui_paint_bitmap(int x, int y, int cx, in Line 2398  ui_paint_bitmap(int x, int y, int cx, in
2398          uint8 *tdata;          uint8 *tdata;
2399          int bitmap_pad;          int bitmap_pad;
2400    
2401          if (g_server_bpp == 8)          if (g_server_depth == 8)
2402          {          {
2403                  bitmap_pad = 8;                  bitmap_pad = 8;
2404          }          }
# Line 1699  ui_paint_bitmap(int x, int y, int cx, in Line 2418  ui_paint_bitmap(int x, int y, int cx, in
2418          {          {
2419                  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);
2420                  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);
2421                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2422                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2423                                             x - sw->xoffset, y - sw->yoffset));
2424          }          }
2425          else          else
2426          {          {
2427                  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);
2428                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2429                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2430                                             x - sw->xoffset, y - sw->yoffset));
2431          }          }
2432    
2433          XFree(image);          XFree(image);
# Line 1711  ui_paint_bitmap(int x, int y, int cx, in Line 2436  ui_paint_bitmap(int x, int y, int cx, in
2436  }  }
2437    
2438  void  void
2439  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(RD_HBITMAP bmp)
2440  {  {
2441          XFreePixmap(g_display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2442  }  }
2443    
2444  HGLYPH  RD_HGLYPH
2445  ui_create_glyph(int width, int height, uint8 * data)  ui_create_glyph(int width, int height, uint8 * data)
2446  {  {
2447          XImage *image;          XImage *image;
# Line 1738  ui_create_glyph(int width, int height, u Line 2463  ui_create_glyph(int width, int height, u
2463          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
2464    
2465          XFree(image);          XFree(image);
2466          return (HGLYPH) bitmap;          return (RD_HGLYPH) bitmap;
2467  }  }
2468    
2469  void  void
2470  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(RD_HGLYPH glyph)
2471  {  {
2472          XFreePixmap(g_display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2473  }  }
2474    
2475  HCURSOR  RD_HCURSOR
2476  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
2477                   uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
2478  {  {
2479          HGLYPH maskglyph, cursorglyph;          RD_HGLYPH maskglyph, cursorglyph;
2480          XColor bg, fg;          XColor bg, fg;
2481          Cursor xcursor;          Cursor xcursor;
2482          uint8 *cursor, *pcursor;          uint8 *cursor, *pcursor;
# Line 1815  ui_create_cursor(unsigned int x, unsigne Line 2540  ui_create_cursor(unsigned int x, unsigne
2540          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2541          xfree(mask);          xfree(mask);
2542          xfree(cursor);          xfree(cursor);
2543          return (HCURSOR) xcursor;          return (RD_HCURSOR) xcursor;
2544  }  }
2545    
2546  void  void
2547  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(RD_HCURSOR cursor)
2548  {  {
2549          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2550          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2551            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2552  }  }
2553    
2554  void  void
2555  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(RD_HCURSOR cursor)
2556  {  {
2557          XFreeCursor(g_display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2558  }  }
# Line 1844  ui_set_null_cursor(void) Line 2570  ui_set_null_cursor(void)
2570                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2571    
2572    
2573  HCOLOURMAP  RD_HCOLOURMAP
2574  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
2575  {  {
2576          COLOURENTRY *entry;          COLOURENTRY *entry;
# Line 1940  ui_create_colourmap(COLOURMAP * colours) Line 2666  ui_create_colourmap(COLOURMAP * colours)
2666                  XStoreColors(g_display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2667    
2668                  xfree(xcolours);                  xfree(xcolours);
2669                  return (HCOLOURMAP) map;                  return (RD_HCOLOURMAP) map;
2670          }          }
2671  }  }
2672    
2673  void  void
2674  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(RD_HCOLOURMAP map)
2675  {  {
2676          if (!g_owncolmap)          if (!g_owncolmap)
2677                  xfree(map);                  xfree(map);
# Line 1954  ui_destroy_colourmap(HCOLOURMAP map) Line 2680  ui_destroy_colourmap(HCOLOURMAP map)
2680  }  }
2681    
2682  void  void
2683  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(RD_HCOLOURMAP map)
2684  {  {
2685          if (!g_owncolmap)          if (!g_owncolmap)
2686          {          {
# Line 1964  ui_set_colourmap(HCOLOURMAP map) Line 2690  ui_set_colourmap(HCOLOURMAP map)
2690                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2691          }          }
2692          else          else
2693            {
2694                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2695                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2696            }
2697  }  }
2698    
2699  void  void
2700  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2701  {  {
2702          XRectangle rect;          g_clip_rectangle.x = x;
2703            g_clip_rectangle.y = y;
2704          rect.x = x;          g_clip_rectangle.width = cx;
2705          rect.y = y;          g_clip_rectangle.height = cy;
2706          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);  
2707  }  }
2708    
2709  void  void
2710  ui_reset_clip(void)  ui_reset_clip(void)
2711  {  {
2712          XRectangle rect;          g_clip_rectangle.x = 0;
2713            g_clip_rectangle.y = 0;
2714          rect.x = 0;          g_clip_rectangle.width = g_width;
2715          rect.y = 0;          g_clip_rectangle.height = g_height;
2716          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);  
2717  }  }
2718    
2719  void  void
# Line 2043  ui_patblt(uint8 opcode, Line 2768  ui_patblt(uint8 opcode,
2768                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2769                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2770                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2771                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2772                          break;                          break;
2773    
2774                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2058  ui_patblt(uint8 opcode, Line 2783  ui_patblt(uint8 opcode,
2783                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2784                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2785                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2786                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2787                          break;                          break;
2788    
2789                  default:                  default:
# Line 2069  ui_patblt(uint8 opcode, Line 2794  ui_patblt(uint8 opcode,
2794    
2795          if (g_ownbackstore)          if (g_ownbackstore)
2796                  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);
2797            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2798                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2799                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2800  }  }
2801    
2802  void  void
# Line 2079  ui_screenblt(uint8 opcode, Line 2807  ui_screenblt(uint8 opcode,
2807          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2808          if (g_ownbackstore)          if (g_ownbackstore)
2809          {          {
2810                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2811                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2812                          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);  
                 }  
2813          }          }
2814          else          else
2815          {          {
2816                  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);
2817          }          }
2818    
2819            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2820                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2821                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2822    
2823          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2824  }  }
2825    
2826  void  void
2827  ui_memblt(uint8 opcode,  ui_memblt(uint8 opcode,
2828            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2829            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ RD_HBITMAP src, int srcx, int srcy)
2830  {  {
2831          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2832          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);
2833            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2834                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2835                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2836          if (g_ownbackstore)          if (g_ownbackstore)
2837                  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);
2838          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2114  ui_memblt(uint8 opcode, Line 2841  ui_memblt(uint8 opcode,
2841  void  void
2842  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2843            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2844            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ RD_HBITMAP src, int srcx, int srcy,
2845            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2846  {  {
2847          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
# Line 2152  ui_line(uint8 opcode, Line 2879  ui_line(uint8 opcode,
2879          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2880          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2881          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2882            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2883                                                startx - sw->xoffset, starty - sw->yoffset,
2884                                                endx - sw->xoffset, endy - sw->yoffset));
2885          if (g_ownbackstore)          if (g_ownbackstore)
2886                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2887          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2166  ui_rect( Line 2896  ui_rect(
2896          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2897  }  }
2898    
2899    void
2900    ui_polygon(uint8 opcode,
2901               /* mode */ uint8 fillmode,
2902               /* dest */ RD_POINT * point, int npoints,
2903               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2904    {
2905            uint8 style, i, ipattern[8];
2906            Pixmap fill;
2907    
2908            SET_FUNCTION(opcode);
2909    
2910            switch (fillmode)
2911            {
2912                    case ALTERNATE:
2913                            XSetFillRule(g_display, g_gc, EvenOddRule);
2914                            break;
2915                    case WINDING:
2916                            XSetFillRule(g_display, g_gc, WindingRule);
2917                            break;
2918                    default:
2919                            unimpl("fill mode %d\n", fillmode);
2920            }
2921    
2922            if (brush)
2923                    style = brush->style;
2924            else
2925                    style = 0;
2926    
2927            switch (style)
2928            {
2929                    case 0: /* Solid */
2930                            SET_FOREGROUND(fgcolour);
2931                            FILL_POLYGON((XPoint *) point, npoints);
2932                            break;
2933    
2934                    case 2: /* Hatch */
2935                            fill = (Pixmap) ui_create_glyph(8, 8,
2936                                                            hatch_patterns + brush->pattern[0] * 8);
2937                            SET_FOREGROUND(fgcolour);
2938                            SET_BACKGROUND(bgcolour);
2939                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2940                            XSetStipple(g_display, g_gc, fill);
2941                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2942                            FILL_POLYGON((XPoint *) point, npoints);
2943                            XSetFillStyle(g_display, g_gc, FillSolid);
2944                            XSetTSOrigin(g_display, g_gc, 0, 0);
2945                            ui_destroy_glyph((RD_HGLYPH) fill);
2946                            break;
2947    
2948                    case 3: /* Pattern */
2949                            for (i = 0; i != 8; i++)
2950                                    ipattern[7 - i] = brush->pattern[i];
2951                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2952                            SET_FOREGROUND(bgcolour);
2953                            SET_BACKGROUND(fgcolour);
2954                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2955                            XSetStipple(g_display, g_gc, fill);
2956                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2957                            FILL_POLYGON((XPoint *) point, npoints);
2958                            XSetFillStyle(g_display, g_gc, FillSolid);
2959                            XSetTSOrigin(g_display, g_gc, 0, 0);
2960                            ui_destroy_glyph((RD_HGLYPH) fill);
2961                            break;
2962    
2963                    default:
2964                            unimpl("brush %d\n", brush->style);
2965            }
2966    
2967            RESET_FUNCTION(opcode);
2968    }
2969    
2970    void
2971    ui_polyline(uint8 opcode,
2972                /* dest */ RD_POINT * points, int npoints,
2973                /* pen */ PEN * pen)
2974    {
2975            /* TODO: set join style */
2976            SET_FUNCTION(opcode);
2977            SET_FOREGROUND(pen->colour);
2978            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2979            if (g_ownbackstore)
2980                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2981                               CoordModePrevious);
2982    
2983            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2984                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2985    
2986            RESET_FUNCTION(opcode);
2987    }
2988    
2989    void
2990    ui_ellipse(uint8 opcode,
2991               /* mode */ uint8 fillmode,
2992               /* dest */ int x, int y, int cx, int cy,
2993               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2994    {
2995            uint8 style, i, ipattern[8];
2996            Pixmap fill;
2997    
2998            SET_FUNCTION(opcode);
2999    
3000            if (brush)
3001                    style = brush->style;
3002            else
3003                    style = 0;
3004    
3005            switch (style)
3006            {
3007                    case 0: /* Solid */
3008                            SET_FOREGROUND(fgcolour);
3009                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3010                            break;
3011    
3012                    case 2: /* Hatch */
3013                            fill = (Pixmap) ui_create_glyph(8, 8,
3014                                                            hatch_patterns + brush->pattern[0] * 8);
3015                            SET_FOREGROUND(fgcolour);
3016                            SET_BACKGROUND(bgcolour);
3017                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3018                            XSetStipple(g_display, g_gc, fill);
3019                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3020                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3021                            XSetFillStyle(g_display, g_gc, FillSolid);
3022                            XSetTSOrigin(g_display, g_gc, 0, 0);
3023                            ui_destroy_glyph((RD_HGLYPH) fill);
3024                            break;
3025    
3026                    case 3: /* Pattern */
3027                            for (i = 0; i != 8; i++)
3028                                    ipattern[7 - i] = brush->pattern[i];
3029                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
3030                            SET_FOREGROUND(bgcolour);
3031                            SET_BACKGROUND(fgcolour);
3032                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3033                            XSetStipple(g_display, g_gc, fill);
3034                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3035                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3036                            XSetFillStyle(g_display, g_gc, FillSolid);
3037                            XSetTSOrigin(g_display, g_gc, 0, 0);
3038                            ui_destroy_glyph((RD_HGLYPH) fill);
3039                            break;
3040    
3041                    default:
3042                            unimpl("brush %d\n", brush->style);
3043            }
3044    
3045            RESET_FUNCTION(opcode);
3046    }
3047    
3048  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
3049  void  void
3050  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
3051                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
3052                /* src */ HGLYPH glyph, int srcx, int srcy,                /* src */ RD_HGLYPH glyph, int srcx, int srcy,
3053                int bgcolour, int fgcolour)                int bgcolour, int fgcolour)
3054  {  {
3055          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
# Line 2221  ui_draw_glyph(int mixmode, Line 3100  ui_draw_glyph(int mixmode,
3100  }  }
3101    
3102  void  void
3103  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
3104               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
3105               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
3106               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
3107  {  {
3108            /* TODO: use brush appropriately */
3109    
3110          FONTGLYPH *glyph;          FONTGLYPH *glyph;
3111          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
3112          DATABLOB *entry;          DATABLOB *entry;
# Line 2257  ui_draw_text(uint8 font, uint8 flags, in Line 3138  ui_draw_text(uint8 font, uint8 flags, in
3138                  switch (text[i])                  switch (text[i])
3139                  {                  {
3140                          case 0xff:                          case 0xff:
3141                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
3142                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
3143                                  {                                  {
3144                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
3145                                          exit(1);                                          for (j = 0; j < length; j++)
3146                                                    fprintf(stderr, "%02x ", text[j]);
3147                                            fprintf(stderr, "\n");
3148                                            i = length = 0;
3149                                            break;
3150                                  }                                  }
3151                                    cache_put_text(text[i + 1], text, text[i + 2]);
3152                                    i += 3;
3153                                    length -= i;
3154                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
3155                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
3156                                  i = 0;                                  i = 0;
3157                                  break;                                  break;
3158    
3159                          case 0xfe:                          case 0xfe:
3160                                    /* At least one byte needs to follow */
3161                                    if (i + 2 > length)
3162                                    {
3163                                            warning("Skipping short 0xfe command:");
3164                                            for (j = 0; j < length; j++)
3165                                                    fprintf(stderr, "%02x ", text[j]);
3166                                            fprintf(stderr, "\n");
3167                                            i = length = 0;
3168                                            break;
3169                                    }
3170                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
3171                                  if (entry != NULL)                                  if (entry->data != NULL)
3172                                  {                                  {
3173                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
3174                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
3175                                          {                                          {
3176                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
3177                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2307  ui_draw_text(uint8 font, uint8 flags, in Line 3203  ui_draw_text(uint8 font, uint8 flags, in
3203          if (g_ownbackstore)          if (g_ownbackstore)
3204          {          {
3205                  if (boxcx > 1)                  if (boxcx > 1)
3206                    {
3207                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3208                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3209                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3210                                                    (g_display, g_backstore, sw->wnd, g_gc,
3211                                                     boxx, boxy,
3212                                                     boxcx, boxcy,
3213                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3214                    }
3215                  else                  else
3216                    {
3217                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3218                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3219                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3220                                                    (g_display, g_backstore, sw->wnd, g_gc,
3221                                                     clipx, clipy,
3222                                                     clipcx, clipcy, clipx - sw->xoffset,
3223                                                     clipy - sw->yoffset));
3224                    }
3225          }          }
3226  }  }
3227    
# Line 2324  ui_desktop_save(uint32 offset, int x, in Line 3234  ui_desktop_save(uint32 offset, int x, in
3234          if (g_ownbackstore)          if (g_ownbackstore)
3235          {          {
3236                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3237                    exit_if_null(image);
3238          }          }
3239          else          else
3240          {          {
3241                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3242                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
3243                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3244                    exit_if_null(image);
3245                  XFreePixmap(g_display, pix);                  XFreePixmap(g_display, pix);
3246          }          }
3247    
# Line 2351  ui_desktop_restore(uint32 offset, int x, Line 3263  ui_desktop_restore(uint32 offset, int x,
3263                  return;                  return;
3264    
3265          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3266                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3267    
3268          if (g_ownbackstore)          if (g_ownbackstore)
3269          {          {
3270                  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);
3271                  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);
3272                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3273                                            (g_display, g_backstore, sw->wnd, g_gc,
3274                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3275          }          }
3276          else          else
3277          {          {
3278                  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);
3279                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3280                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3281                                             x - sw->xoffset, y - sw->yoffset));
3282          }          }
3283    
3284          XFree(image);          XFree(image);
# Line 2376  void Line 3294  void
3294  ui_end_update(void)  ui_end_update(void)
3295  {  {
3296  }  }
3297    
3298    
3299    void
3300    ui_seamless_begin(RD_BOOL hidden)
3301    {
3302            if (!g_seamless_rdp)
3303                    return;
3304    
3305            if (g_seamless_started)
3306                    return;
3307    
3308            g_seamless_started = True;
3309            g_seamless_hidden = hidden;
3310    
3311            if (!hidden)
3312                    ui_seamless_toggle();
3313    }
3314    
3315    
3316    void
3317    ui_seamless_hide_desktop()
3318    {
3319            if (!g_seamless_rdp)
3320                    return;
3321    
3322            if (!g_seamless_started)
3323                    return;
3324    
3325            if (g_seamless_active)
3326                    ui_seamless_toggle();
3327    
3328            g_seamless_hidden = True;
3329    }
3330    
3331    
3332    void
3333    ui_seamless_unhide_desktop()
3334    {
3335            if (!g_seamless_rdp)
3336                    return;
3337    
3338            if (!g_seamless_started)
3339                    return;
3340    
3341            g_seamless_hidden = False;
3342    
3343            ui_seamless_toggle();
3344    }
3345    
3346    
3347    void
3348    ui_seamless_toggle()
3349    {
3350            if (!g_seamless_rdp)
3351                    return;
3352    
3353            if (!g_seamless_started)
3354                    return;
3355    
3356            if (g_seamless_hidden)
3357                    return;
3358    
3359            if (g_seamless_active)
3360            {
3361                    /* Deactivate */
3362                    while (g_seamless_windows)
3363                    {
3364                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3365                            sw_remove_window(g_seamless_windows);
3366                    }
3367                    XMapWindow(g_display, g_wnd);
3368            }
3369            else
3370            {
3371                    /* Activate */
3372                    XUnmapWindow(g_display, g_wnd);
3373                    seamless_send_sync();
3374            }
3375    
3376            g_seamless_active = !g_seamless_active;
3377    }
3378    
3379    
3380    void
3381    ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3382                              unsigned long flags)
3383    {
3384            Window wnd;
3385            XSetWindowAttributes attribs;
3386            XClassHint *classhints;
3387            XSizeHints *sizehints;
3388            XWMHints *wmhints;
3389            long input_mask;
3390            seamless_window *sw, *sw_parent;
3391    
3392            if (!g_seamless_active)
3393                    return;
3394    
3395            /* Ignore CREATEs for existing windows */
3396            sw = sw_get_window_by_id(id);
3397            if (sw)
3398                    return;
3399    
3400            get_window_attribs(&attribs);
3401            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3402                                InputOutput, g_visual,
3403                                CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3404    
3405            XStoreName(g_display, wnd, "SeamlessRDP");
3406            ewmh_set_wm_name(wnd, "SeamlessRDP");
3407    
3408            mwm_hide_decorations(wnd);
3409    
3410            classhints = XAllocClassHint();
3411            if (classhints != NULL)
3412            {
3413                    classhints->res_name = "rdesktop";
3414                    classhints->res_class = "SeamlessRDP";
3415                    XSetClassHint(g_display, wnd, classhints);
3416                    XFree(classhints);
3417            }
3418    
3419            /* WM_NORMAL_HINTS */
3420            sizehints = XAllocSizeHints();
3421            if (sizehints != NULL)
3422            {
3423                    sizehints->flags = USPosition;
3424                    XSetWMNormalHints(g_display, wnd, sizehints);
3425                    XFree(sizehints);
3426            }
3427    
3428            /* Parent-less transient windows */
3429            if (parent == 0xFFFFFFFF)
3430            {
3431                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3432                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3433                       using some other hints. */
3434                    ewmh_set_window_popup(wnd);
3435            }
3436            /* Normal transient windows */
3437            else if (parent != 0x00000000)
3438            {
3439                    sw_parent = sw_get_window_by_id(parent);
3440                    if (sw_parent)
3441                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3442                    else
3443                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3444            }
3445    
3446            if (flags & SEAMLESSRDP_CREATE_MODAL)
3447            {
3448                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3449                       somewhat at least */
3450                    if (parent == 0x00000000)
3451                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3452                    ewmh_set_window_modal(wnd);
3453            }
3454    
3455            /* FIXME: Support for Input Context:s */
3456    
3457            get_input_mask(&input_mask);
3458            input_mask |= PropertyChangeMask;
3459    
3460            XSelectInput(g_display, wnd, input_mask);
3461    
3462            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3463               seamless window, we could try to close the window on the
3464               serverside, instead of terminating rdesktop */
3465            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3466    
3467            sw = xmalloc(sizeof(seamless_window));
3468    
3469            memset(sw, 0, sizeof(seamless_window));
3470    
3471            sw->wnd = wnd;
3472            sw->id = id;
3473            sw->group = sw_find_group(group, False);
3474            sw->group->refcnt++;
3475            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3476            sw->desktop = 0;
3477            sw->position_timer = xmalloc(sizeof(struct timeval));
3478            timerclear(sw->position_timer);
3479    
3480            sw->outstanding_position = False;
3481            sw->outpos_serial = 0;
3482            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3483            sw->outpos_width = sw->outpos_height = 0;
3484    
3485            sw->next = g_seamless_windows;
3486            g_seamless_windows = sw;
3487    
3488            /* WM_HINTS */
3489            wmhints = XAllocWMHints();
3490            if (wmhints)
3491            {
3492                    wmhints->flags = WindowGroupHint;
3493                    wmhints->window_group = sw->group->wnd;
3494                    XSetWMHints(g_display, sw->wnd, wmhints);
3495                    XFree(wmhints);
3496            }
3497    }
3498    
3499    
3500    void
3501    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3502    {
3503            seamless_window *sw;
3504    
3505            if (!g_seamless_active)
3506                    return;
3507    
3508            sw = sw_get_window_by_id(id);
3509            if (!sw)
3510            {
3511                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3512                    return;
3513            }
3514    
3515            XDestroyWindow(g_display, sw->wnd);
3516            sw_remove_window(sw);
3517    }
3518    
3519    
3520    void
3521    ui_seamless_destroy_group(unsigned long id, unsigned long flags)
3522    {
3523            seamless_window *sw, *sw_next;
3524    
3525            if (!g_seamless_active)
3526                    return;
3527    
3528            for (sw = g_seamless_windows; sw; sw = sw_next)
3529            {
3530                    sw_next = sw->next;
3531    
3532                    if (sw->group->id == id)
3533                    {
3534                            XDestroyWindow(g_display, sw->wnd);
3535                            sw_remove_window(sw);
3536                    }
3537            }
3538    }
3539    
3540    
3541    void
3542    ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
3543                        const char *data, int chunk_len)
3544    {
3545            seamless_window *sw;
3546    
3547            if (!g_seamless_active)
3548                    return;
3549    
3550            sw = sw_get_window_by_id(id);
3551            if (!sw)
3552            {
3553                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3554                    return;
3555            }
3556    
3557            if (chunk == 0)
3558            {
3559                    if (sw->icon_size)
3560                            warning("ui_seamless_seticon: New icon started before previous completed\n");
3561    
3562                    if (strcmp(format, "RGBA") != 0)
3563                    {
3564                            warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3565                            return;
3566                    }
3567    
3568                    sw->icon_size = width * height * 4;
3569                    if (sw->icon_size > 32 * 32 * 4)
3570                    {
3571                            warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
3572                            sw->icon_size = 0;
3573                            return;
3574                    }
3575    
3576                    sw->icon_offset = 0;
3577            }
3578            else
3579            {
3580                    if (!sw->icon_size)
3581                            return;
3582            }
3583    
3584            if (chunk_len > (sw->icon_size - sw->icon_offset))
3585            {
3586                    warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
3587                            chunk_len, sw->icon_size - sw->icon_offset);
3588                    sw->icon_size = 0;
3589                    return;
3590            }
3591    
3592            memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
3593            sw->icon_offset += chunk_len;
3594    
3595            if (sw->icon_offset == sw->icon_size)
3596            {
3597                    ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
3598                    sw->icon_size = 0;
3599            }
3600    }
3601    
3602    
3603    void
3604    ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
3605    {
3606            seamless_window *sw;
3607    
3608            if (!g_seamless_active)
3609                    return;
3610    
3611            sw = sw_get_window_by_id(id);
3612            if (!sw)
3613            {
3614                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3615                    return;
3616            }
3617    
3618            if (strcmp(format, "RGBA") != 0)
3619            {
3620                    warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3621                    return;
3622            }
3623    
3624            ewmh_del_icon(sw->wnd, width, height);
3625    }
3626    
3627    
3628    void
3629    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3630    {
3631            seamless_window *sw;
3632    
3633            if (!g_seamless_active)
3634                    return;
3635    
3636            sw = sw_get_window_by_id(id);
3637            if (!sw)
3638            {
3639                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3640                    return;
3641            }
3642    
3643            /* We ignore server updates until it has handled our request. */
3644            if (sw->outstanding_position)
3645                    return;
3646    
3647            if (!width || !height)
3648                    /* X11 windows must be at least 1x1 */
3649                    return;
3650    
3651            sw->xoffset = x;
3652            sw->yoffset = y;
3653            sw->width = width;
3654            sw->height = height;
3655    
3656            /* If we move the window in a maximized state, then KDE won't
3657               accept restoration */
3658            switch (sw->state)
3659            {
3660                    case SEAMLESSRDP_MINIMIZED:
3661                    case SEAMLESSRDP_MAXIMIZED:
3662                            return;
3663            }
3664    
3665            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3666            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3667    }
3668    
3669    
3670    void
3671    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3672    {
3673            seamless_window *sw;
3674    
3675            if (!g_seamless_active)
3676                    return;
3677    
3678            sw = sw_get_window_by_id(id);
3679            if (!sw)
3680            {
3681                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3682                    return;
3683            }
3684    
3685            if (behind)
3686            {
3687                    seamless_window *sw_behind;
3688                    Window wnds[2];
3689    
3690                    sw_behind = sw_get_window_by_id(behind);
3691                    if (!sw_behind)
3692                    {
3693                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3694                                    behind);
3695                            return;
3696                    }
3697    
3698                    wnds[1] = sw_behind->wnd;
3699                    wnds[0] = sw->wnd;
3700    
3701                    XRestackWindows(g_display, wnds, 2);
3702            }
3703            else
3704            {
3705                    XRaiseWindow(g_display, sw->wnd);
3706            }
3707    
3708            sw_restack_window(sw, behind);
3709    }
3710    
3711    
3712    void
3713    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3714    {
3715            seamless_window *sw;
3716    
3717            if (!g_seamless_active)
3718                    return;
3719    
3720            sw = sw_get_window_by_id(id);
3721            if (!sw)
3722            {
3723                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3724                    return;
3725            }
3726    
3727            /* FIXME: Might want to convert the name for non-EWMH WMs */
3728            XStoreName(g_display, sw->wnd, title);
3729            ewmh_set_wm_name(sw->wnd, title);
3730    }
3731    
3732    
3733    void
3734    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3735    {
3736            seamless_window *sw;
3737    
3738            if (!g_seamless_active)
3739                    return;
3740    
3741            sw = sw_get_window_by_id(id);
3742            if (!sw)
3743            {
3744                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3745                    return;
3746            }
3747    
3748            switch (state)
3749            {
3750                    case SEAMLESSRDP_NORMAL:
3751                    case SEAMLESSRDP_MAXIMIZED:
3752                            ewmh_change_state(sw->wnd, state);
3753                            XMapWindow(g_display, sw->wnd);
3754                            break;
3755                    case SEAMLESSRDP_MINIMIZED:
3756                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3757                               the Window Manager should probably just ignore the request, since
3758                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3759                               such as minimization, rather than an independent state." Besides,
3760                               XIconifyWindow is easier. */
3761                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3762                            {
3763                                    XWMHints *hints;
3764                                    hints = XGetWMHints(g_display, sw->wnd);
3765                                    if (hints)
3766                                    {
3767                                            hints->flags |= StateHint;
3768                                            hints->initial_state = IconicState;
3769                                            XSetWMHints(g_display, sw->wnd, hints);
3770                                            XFree(hints);
3771                                    }
3772                                    XMapWindow(g_display, sw->wnd);
3773                            }
3774                            else
3775                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3776                            break;
3777                    default:
3778                            warning("SeamlessRDP: Invalid state %d\n", state);
3779                            break;
3780            }
3781    
3782            sw->state = state;
3783    }
3784    
3785    
3786    void
3787    ui_seamless_syncbegin(unsigned long flags)
3788    {
3789            if (!g_seamless_active)
3790                    return;
3791    
3792            /* Destroy all seamless windows */
3793            while (g_seamless_windows)
3794            {
3795                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3796                    sw_remove_window(g_seamless_windows);
3797            }
3798    }
3799    
3800    
3801    void
3802    ui_seamless_ack(unsigned int serial)
3803    {
3804            seamless_window *sw;
3805            for (sw = g_seamless_windows; sw; sw = sw->next)
3806            {
3807                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3808                    {
3809                            sw->xoffset = sw->outpos_xoffset;
3810                            sw->yoffset = sw->outpos_yoffset;
3811                            sw->width = sw->outpos_width;
3812                            sw->height = sw->outpos_height;
3813                            sw->outstanding_position = False;
3814    
3815                            /* Do a complete redraw of the window as part of the
3816                               completion of the move. This is to remove any
3817                               artifacts caused by our lack of synchronization. */
3818                            XCopyArea(g_display, g_backstore,
3819                                      sw->wnd, g_gc,
3820                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3821    
3822                            break;
3823                    }
3824            }
3825    }

Legend:
Removed from v.828  
changed lines
  Added in v.1417

  ViewVC Help
Powered by ViewVC 1.1.26