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

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

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

revision 1049 by astrand, Wed Mar 1 13:54:19 2006 UTC revision 1413 by ossman_, Mon Jun 18 12:00:34 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 33  extern int g_height; Line 35  extern int g_height;
35  extern int g_xpos;  extern int g_xpos;
36  extern int g_ypos;  extern int g_ypos;
37  extern int g_pos;  extern int g_pos;
38  extern BOOL g_sendmotion;  extern RD_BOOL g_sendmotion;
39  extern BOOL g_fullscreen;  extern RD_BOOL g_fullscreen;
40  extern BOOL g_grab_keyboard;  extern RD_BOOL g_grab_keyboard;
41  extern BOOL g_hide_decorations;  extern RD_BOOL g_hide_decorations;
42  extern char g_title[];  extern char g_title[];
43  /* Color depth of the RDP session.  /* Color depth of the RDP session.
44     As of RDP 5.1, it may be 8, 15, 16 or 24. */     As of RDP 5.1, it may be 8, 15, 16 or 24. */
# Line 48  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).  /* 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     This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
# Line 66  static int g_bpp; Line 107  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 RD_BOOL g_focused;
119    static RD_BOOL g_mouse_in_wnd;
120  /* Indicates that:  /* Indicates that:
121     1) visual has 15, 16 or 24 depth and the same color channel masks     1) visual has 15, 16 or 24 depth and the same color channel masks
122        as its RDP equivalent (implies X server is LE),        as its RDP equivalent (implies X server is LE),
123     2) host is LE     2) host is LE
124     This will trigger an optimization whose real value is questionable.     This will trigger an optimization whose real value is questionable.
125  */  */
126  static BOOL g_compatible_arch;  static RD_BOOL g_compatible_arch;
127  /* Indicates whether RDP's bitmaps and our XImages have the same  /* Indicates whether RDP's bitmaps and our XImages have the same
128     binary format. If so, we can avoid an expensive translation.     binary format. If so, we can avoid an expensive translation.
129     Note that this can be true when g_compatible_arch is false,     Note that this can be true when g_compatible_arch is false,
# Line 88  static BOOL g_compatible_arch; Line 134  static BOOL g_compatible_arch;
134     ('host' is the machine running rdesktop; the host simply memcpy's     ('host' is the machine running rdesktop; the host simply memcpy's
135      so its endianess doesn't matter)      so its endianess doesn't matter)
136   */   */
137  static BOOL g_no_translate_image = False;  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 BOOL g_using_full_workarea = False;  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 133  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 151  PixelColour; Line 231  PixelColour;
231          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
232          if (g_ownbackstore) \          if (g_ownbackstore) \
233                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  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)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 159  PixelColour; Line 240  PixelColour;
240          { \          { \
241                  case 0: /* Outline */ \                  case 0: /* Outline */ \
242                          XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
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) \                          if (g_ownbackstore) \
245                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
246                          break; \                          break; \
247                  case 1: /* Filled */ \                  case 1: /* Filled */ \
248                          XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          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) \                          if (g_ownbackstore) \
251                                  XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \                                  XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
252                          break; \                          break; \
# Line 171  PixelColour; Line 254  PixelColour;
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    
# Line 201  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
314    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  static void
430  mwm_hide_decorations(void)  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 219  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 962  translate_image(int width, int height, u Line 1268  translate_image(int width, int height, u
1268          return out;          return out;
1269  }  }
1270    
1271  BOOL  static void
1272    xwin_refresh_pointer_map(void)
1273    {
1274            unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)];
1275            int i, pointer_buttons;
1276    
1277            pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map));
1278            for (i = 0; i < pointer_buttons; ++i)
1279            {
1280                    /* This might produce multiple logical buttons mapping
1281                       to a single physical one, but hey, that's
1282                       life... */
1283                    g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
1284            }
1285    }
1286    
1287    RD_BOOL
1288  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1289  {  {
1290          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
# Line 1010  calculate_mask_weight(uint32 mask) Line 1332  calculate_mask_weight(uint32 mask)
1332          return weight;          return weight;
1333  }  }
1334    
1335  static BOOL  static RD_BOOL
1336  select_visual()  select_visual(int screen_num)
1337  {  {
1338          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1339          int pixmap_formats_count, visuals_count;          int pixmap_formats_count, visuals_count;
# Line 1022  select_visual() Line 1344  select_visual()
1344    
1345          red_weight = blue_weight = green_weight = 0;          red_weight = blue_weight = green_weight = 0;
1346    
1347            if (g_server_depth == -1)
1348            {
1349                    g_server_depth = DisplayPlanes(g_display, DefaultScreen(g_display));
1350            }
1351    
1352          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1353          if (pfm == NULL)          if (pfm == NULL)
1354          {          {
# Line 1032  select_visual() Line 1359  select_visual()
1359    
1360          /* Search for best TrueColor visual */          /* Search for best TrueColor visual */
1361          template.class = TrueColor;          template.class = TrueColor;
1362          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);          template.screen = screen_num;
1363            vmatches =
1364                    XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template,
1365                                   &visuals_count);
1366          g_visual = NULL;          g_visual = NULL;
1367          g_no_translate_image = False;          g_no_translate_image = False;
1368          g_compatible_arch = False;          g_compatible_arch = False;
# Line 1041  select_visual() Line 1371  select_visual()
1371                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
1372                  {                  {
1373                          XVisualInfo *visual_info = &vmatches[i];                          XVisualInfo *visual_info = &vmatches[i];
1374                            RD_BOOL can_translate_to_bpp = False;
1375                            int j;
1376    
1377                          /* Try to find a no-translation visual that'll                          /* Try to find a no-translation visual that'll
1378                             allow us to use RDP bitmaps directly as ZPixmaps. */                             allow us to use RDP bitmaps directly as ZPixmaps. */
# Line 1084  select_visual() Line 1416  select_visual()
1416    
1417                          /* Only care for visuals, for whose BPPs (not depths!)                          /* Only care for visuals, for whose BPPs (not depths!)
1418                             we have a translateXtoY function. */                             we have a translateXtoY function. */
                         BOOL can_translate_to_bpp = False;  
                         int j;  
1419                          for (j = 0; j < pixmap_formats_count; ++j)                          for (j = 0; j < pixmap_formats_count; ++j)
1420                          {                          {
1421                                  if (pfm[j].depth == visual_info->depth)                                  if (pfm[j].depth == visual_info->depth)
# Line 1197  select_visual() Line 1527  select_visual()
1527          return True;          return True;
1528  }  }
1529    
1530  BOOL  static XErrorHandler g_old_error_handler;
1531    
1532    static int
1533    error_handler(Display * dpy, XErrorEvent * eev)
1534    {
1535            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1536            {
1537                    fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1538                    fprintf(stderr,
1539                            "This is most likely caused by a broken window manager (commonly KWin).\n");
1540                    return 0;
1541            }
1542    
1543            return g_old_error_handler(dpy, eev);
1544    }
1545    
1546    RD_BOOL
1547  ui_init(void)  ui_init(void)
1548  {  {
1549          int screen_num;          int screen_num;
# Line 1211  ui_init(void) Line 1557  ui_init(void)
1557    
1558          {          {
1559                  uint16 endianess_test = 1;                  uint16 endianess_test = 1;
1560                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test));
1561          }          }
1562    
1563            g_old_error_handler = XSetErrorHandler(error_handler);
1564          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1565          screen_num = DefaultScreen(g_display);          screen_num = DefaultScreen(g_display);
1566          g_x_socket = ConnectionNumber(g_display);          g_x_socket = ConnectionNumber(g_display);
1567          g_screen = ScreenOfDisplay(g_display, screen_num);          g_screen = ScreenOfDisplay(g_display, screen_num);
1568          g_depth = DefaultDepthOfScreen(g_screen);          g_depth = DefaultDepthOfScreen(g_screen);
1569    
1570          if (!select_visual())          if (!select_visual(screen_num))
1571                  return False;                  return False;
1572    
1573          if (g_no_translate_image)          if (g_no_translate_image)
# Line 1259  ui_init(void) Line 1606  ui_init(void)
1606          {          {
1607                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1608                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1609                    g_using_full_workarea = True;
1610          }          }
1611          else if (g_width < 0)          else if (g_width < 0)
1612          {          {
# Line 1272  ui_init(void) Line 1620  ui_init(void)
1620          {          {
1621                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1622                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
                 g_using_full_workarea = True;  
   
1623                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1624                  {                  {
1625                          g_width = cx;                          g_width = cx;
1626                          g_height = cy;                          g_height = cy;
1627                            g_using_full_workarea = True;
1628                  }                  }
1629                  else                  else
1630                  {                  {
1631                          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");
1632                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1633                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1634                  }                  }
1635          }          }
1636    
# Line 1291  ui_init(void) Line 1638  ui_init(void)
1638          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1639    
1640          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1641            xwin_refresh_pointer_map();
1642    
1643          xkeymap_init();          xkeymap_init();
1644    
# Line 1298  ui_init(void) Line 1646  ui_init(void)
1646                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1647    
1648          xclip_init();          xclip_init();
1649            ewmh_init();
1650            if (g_seamless_rdp)
1651                    seamless_init();
1652    
1653          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1654    
# Line 1307  ui_init(void) Line 1658  ui_init(void)
1658  void  void
1659  ui_deinit(void)  ui_deinit(void)
1660  {  {
1661            while (g_seamless_windows)
1662            {
1663                    XDestroyWindow(g_display, g_seamless_windows->wnd);
1664                    sw_remove_window(g_seamless_windows);
1665            }
1666    
1667            xclip_deinit();
1668    
1669          if (g_IM != NULL)          if (g_IM != NULL)
1670                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1671    
# Line 1323  ui_deinit(void) Line 1682  ui_deinit(void)
1682          g_display = NULL;          g_display = NULL;
1683  }  }
1684    
1685  BOOL  
1686    static void
1687    get_window_attribs(XSetWindowAttributes * attribs)
1688    {
1689            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1690            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1691            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1692            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1693            attribs->override_redirect = g_fullscreen;
1694            attribs->colormap = g_xcolmap;
1695    }
1696    
1697    static void
1698    get_input_mask(long *input_mask)
1699    {
1700            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1701                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1702    
1703            if (g_sendmotion)
1704                    *input_mask |= PointerMotionMask;
1705            if (g_ownbackstore)
1706                    *input_mask |= ExposureMask;
1707            if (g_fullscreen || g_grab_keyboard)
1708                    *input_mask |= EnterWindowMask;
1709            if (g_grab_keyboard)
1710                    *input_mask |= LeaveWindowMask;
1711    }
1712    
1713    RD_BOOL
1714  ui_create_window(void)  ui_create_window(void)
1715  {  {
1716          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
# Line 1345  ui_create_window(void) Line 1732  ui_create_window(void)
1732          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1733                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1734    
1735          attribs.background_pixel = BlackPixelOfScreen(g_screen);          get_window_attribs(&attribs);
         attribs.border_pixel = WhitePixelOfScreen(g_screen);  
         attribs.backing_store = g_ownbackstore ? NotUseful : Always;  
         attribs.override_redirect = g_fullscreen;  
         attribs.colormap = g_xcolmap;  
1736    
1737          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,
1738                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1357  ui_create_window(void) Line 1740  ui_create_window(void)
1740                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1741    
1742          if (g_gc == NULL)          if (g_gc == NULL)
1743            {
1744                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1745                    ui_reset_clip();
1746            }
1747    
1748          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1749                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 1372  ui_create_window(void) Line 1758  ui_create_window(void)
1758          }          }
1759    
1760          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1761            ewmh_set_wm_name(g_wnd, g_title);
1762    
1763          if (g_hide_decorations)          if (g_hide_decorations)
1764                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1765    
1766          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1767          if (classhints != NULL)          if (classhints != NULL)
# Line 1401  ui_create_window(void) Line 1788  ui_create_window(void)
1788                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1789          }          }
1790    
1791          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          get_input_mask(&input_mask);
                 VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;  
   
         if (g_sendmotion)  
                 input_mask |= PointerMotionMask;  
         if (g_ownbackstore)  
                 input_mask |= ExposureMask;  
         if (g_fullscreen || g_grab_keyboard)  
                 input_mask |= EnterWindowMask;  
         if (g_grab_keyboard)  
                 input_mask |= LeaveWindowMask;  
1792    
1793          if (g_IM != NULL)          if (g_IM != NULL)
1794          {          {
# Line 1496  xwin_toggle_fullscreen(void) Line 1873  xwin_toggle_fullscreen(void)
1873  {  {
1874          Pixmap contents = 0;          Pixmap contents = 0;
1875    
1876            if (g_seamless_active)
1877                    /* Turn off SeamlessRDP mode */
1878                    ui_seamless_toggle();
1879    
1880          if (!g_ownbackstore)          if (!g_ownbackstore)
1881          {          {
1882                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1517  xwin_toggle_fullscreen(void) Line 1898  xwin_toggle_fullscreen(void)
1898  }  }
1899    
1900  static void  static void
1901  handle_button_event(XEvent xevent, BOOL down)  handle_button_event(XEvent xevent, RD_BOOL down)
1902  {  {
1903          uint16 button, flags = 0;          uint16 button, flags = 0;
1904          g_last_gesturetime = xevent.xbutton.time;          g_last_gesturetime = xevent.xbutton.time;
1905            /* Reverse the pointer button mapping, e.g. in the case of
1906               "left-handed mouse mode"; the RDP session expects to
1907               receive physical buttons (true in mstsc as well) and
1908               logical button behavior depends on the remote desktop's own
1909               mouse settings */
1910            xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
1911          button = xkeymap_translate_button(xevent.xbutton.button);          button = xkeymap_translate_button(xevent.xbutton.button);
1912          if (button == 0)          if (button == 0)
1913                  return;                  return;
# Line 1584  handle_button_event(XEvent xevent, BOOL Line 1971  handle_button_event(XEvent xevent, BOOL
1971                  }                  }
1972          }          }
1973    
1974          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1975                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1976                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1977                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1978            }
1979            else
1980            {
1981                    /* SeamlessRDP */
1982                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1983                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1984            }
1985  }  }
1986    
1987    
1988  /* Process events in Xlib queue  /* Process events in Xlib queue
1989     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1990  static int  static int
# Line 1599  xwin_process_events(void) Line 1996  xwin_process_events(void)
1996          char str[256];          char str[256];
1997          Status status;          Status status;
1998          int events = 0;          int events = 0;
1999            seamless_window *sw;
2000    
2001          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
2002          {          {
# Line 1613  xwin_process_events(void) Line 2011  xwin_process_events(void)
2011                  switch (xevent.type)                  switch (xevent.type)
2012                  {                  {
2013                          case VisibilityNotify:                          case VisibilityNotify:
2014                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
2015                                            g_Unobscured =
2016                                                    xevent.xvisibility.state == VisibilityUnobscured;
2017    
2018                                  break;                                  break;
2019                          case ClientMessage:                          case ClientMessage:
2020                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1693  xwin_process_events(void) Line 2094  xwin_process_events(void)
2094                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
2095                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2096                                                         CurrentTime);                                                         CurrentTime);
2097                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
2098                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
2099                                    {
2100                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2101                                                           xevent.xmotion.x, xevent.xmotion.y);
2102                                    }
2103                                    else
2104                                    {
2105                                            /* SeamlessRDP */
2106                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2107                                                           xevent.xmotion.x_root,
2108                                                           xevent.xmotion.y_root);
2109                                    }
2110                                  break;                                  break;
2111    
2112                          case FocusIn:                          case FocusIn:
# Line 1705  xwin_process_events(void) Line 2117  xwin_process_events(void)
2117                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2118                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2119                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2120    
2121                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2122                                    if (!sw)
2123                                            break;
2124    
2125                                    if (sw->id != g_seamless_focused)
2126                                    {
2127                                            seamless_send_focus(sw->id, 0);
2128                                            g_seamless_focused = sw->id;
2129                                    }
2130                                  break;                                  break;
2131    
2132                          case FocusOut:                          case FocusOut:
# Line 1737  xwin_process_events(void) Line 2159  xwin_process_events(void)
2159                                  break;                                  break;
2160    
2161                          case Expose:                          case Expose:
2162                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2163                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2164                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2165                                            xevent.xexpose.height,                                                    g_gc,
2166                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2167                                                      xevent.xexpose.width, xevent.xexpose.height,
2168                                                      xevent.xexpose.x, xevent.xexpose.y);
2169                                    }
2170                                    else
2171                                    {
2172                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2173                                            if (!sw)
2174                                                    break;
2175                                            XCopyArea(g_display, g_backstore,
2176                                                      xevent.xexpose.window, g_gc,
2177                                                      xevent.xexpose.x + sw->xoffset,
2178                                                      xevent.xexpose.y + sw->yoffset,
2179                                                      xevent.xexpose.width,
2180                                                      xevent.xexpose.height, xevent.xexpose.x,
2181                                                      xevent.xexpose.y);
2182                                    }
2183    
2184                                  break;                                  break;
2185    
2186                          case MappingNotify:                          case MappingNotify:
# Line 1756  xwin_process_events(void) Line 2195  xwin_process_events(void)
2195                                          XFreeModifiermap(g_mod_map);                                          XFreeModifiermap(g_mod_map);
2196                                          g_mod_map = XGetModifierMapping(g_display);                                          g_mod_map = XGetModifierMapping(g_display);
2197                                  }                                  }
2198    
2199                                    if (xevent.xmapping.request == MappingPointer)
2200                                    {
2201                                            xwin_refresh_pointer_map();
2202                                    }
2203    
2204                                  break;                                  break;
2205    
2206                                  /* clipboard stuff */                                  /* clipboard stuff */
# Line 1770  xwin_process_events(void) Line 2215  xwin_process_events(void)
2215                                  break;                                  break;
2216                          case PropertyNotify:                          case PropertyNotify:
2217                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2218                                    if (xevent.xproperty.window == g_wnd)
2219                                            break;
2220                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2221                                            break;
2222    
2223                                    /* seamless */
2224                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2225                                    if (!sw)
2226                                            break;
2227    
2228                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2229                                        && (xevent.xproperty.state == PropertyNewValue))
2230                                    {
2231                                            sw->state = ewmh_get_window_state(sw->wnd);
2232                                            seamless_send_state(sw->id, sw->state, 0);
2233                                    }
2234    
2235                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2236                                        && (xevent.xproperty.state == PropertyNewValue))
2237                                    {
2238                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2239                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2240                                    }
2241    
2242                                  break;                                  break;
2243                          case MapNotify:                          case MapNotify:
2244                                  rdp_send_client_window_status(1);                                  if (!g_seamless_active)
2245                                            rdp_send_client_window_status(1);
2246                                  break;                                  break;
2247                          case UnmapNotify:                          case UnmapNotify:
2248                                  rdp_send_client_window_status(0);                                  if (!g_seamless_active)
2249                                            rdp_send_client_window_status(0);
2250                                    break;
2251                            case ConfigureNotify:
2252                                    if (!g_seamless_active)
2253                                            break;
2254    
2255                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2256                                    if (!sw)
2257                                            break;
2258    
2259                                    gettimeofday(sw->position_timer, NULL);
2260                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2261                                        1000000)
2262                                    {
2263                                            sw->position_timer->tv_usec +=
2264                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2265                                            sw->position_timer->tv_sec += 1;
2266                                    }
2267                                    else
2268                                    {
2269                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2270                                    }
2271    
2272                                    sw_handle_restack(sw);
2273                                  break;                                  break;
2274                  }                  }
2275          }          }
# Line 1790  ui_select(int rdp_socket) Line 2284  ui_select(int rdp_socket)
2284          int n;          int n;
2285          fd_set rfds, wfds;          fd_set rfds, wfds;
2286          struct timeval tv;          struct timeval tv;
2287          BOOL s_timeout = False;          RD_BOOL s_timeout = False;
2288    
2289          while (True)          while (True)
2290          {          {
# Line 1800  ui_select(int rdp_socket) Line 2294  ui_select(int rdp_socket)
2294                          /* User quit */                          /* User quit */
2295                          return 0;                          return 0;
2296    
2297                    if (g_seamless_active)
2298                            sw_check_timers();
2299    
2300                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2301                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2302                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
2303                  FD_SET(g_x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
2304    
 #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  
2305                  /* default timeout */                  /* default timeout */
2306                  tv.tv_sec = 60;                  tv.tv_sec = 60;
2307                  tv.tv_usec = 0;                  tv.tv_usec = 0;
2308    
2309    #ifdef WITH_RDPSND
2310                    rdpsnd_add_fds(&n, &rfds, &wfds, &tv);
2311    #endif
2312    
2313                  /* add redirection handles */                  /* add redirection handles */
2314                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2315                    seamless_select_timeout(&tv);
2316    
2317                  n++;                  n++;
2318    
# Line 1828  ui_select(int rdp_socket) Line 2322  ui_select(int rdp_socket)
2322                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2323    
2324                          case 0:                          case 0:
2325    #ifdef WITH_RDPSND
2326                                    rdpsnd_check_fds(&rfds, &wfds);
2327    #endif
2328    
2329                                  /* Abort serial read calls */                                  /* Abort serial read calls */
2330                                  if (s_timeout)                                  if (s_timeout)
2331                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);                                          rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True);
2332                                  continue;                                  continue;
2333                  }                  }
2334    
2335                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);  #ifdef WITH_RDPSND
2336                    rdpsnd_check_fds(&rfds, &wfds);
2337    #endif
2338    
2339                    rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False);
2340    
2341                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2342                          return 1;                          return 1;
2343    
 #ifdef WITH_RDPSND  
                 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))  
                         wave_out_play();  
 #endif  
2344          }          }
2345  }  }
2346    
# Line 1852  ui_move_pointer(int x, int y) Line 2350  ui_move_pointer(int x, int y)
2350          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);
2351  }  }
2352    
2353  HBITMAP  RD_HBITMAP
2354  ui_create_bitmap(int width, int height, uint8 * data)  ui_create_bitmap(int width, int height, uint8 * data)
2355  {  {
2356          XImage *image;          XImage *image;
# Line 1882  ui_create_bitmap(int width, int height, Line 2380  ui_create_bitmap(int width, int height,
2380          XFree(image);          XFree(image);
2381          if (tdata != data)          if (tdata != data)
2382                  xfree(tdata);                  xfree(tdata);
2383          return (HBITMAP) bitmap;          return (RD_HBITMAP) bitmap;
2384  }  }
2385    
2386  void  void
# Line 1912  ui_paint_bitmap(int x, int y, int cx, in Line 2410  ui_paint_bitmap(int x, int y, int cx, in
2410          {          {
2411                  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);
2412                  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);
2413                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2414                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2415                                             x - sw->xoffset, y - sw->yoffset));
2416          }          }
2417          else          else
2418          {          {
2419                  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);
2420                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2421                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2422                                             x - sw->xoffset, y - sw->yoffset));
2423          }          }
2424    
2425          XFree(image);          XFree(image);
# Line 1924  ui_paint_bitmap(int x, int y, int cx, in Line 2428  ui_paint_bitmap(int x, int y, int cx, in
2428  }  }
2429    
2430  void  void
2431  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(RD_HBITMAP bmp)
2432  {  {
2433          XFreePixmap(g_display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2434  }  }
2435    
2436  HGLYPH  RD_HGLYPH
2437  ui_create_glyph(int width, int height, uint8 * data)  ui_create_glyph(int width, int height, uint8 * data)
2438  {  {
2439          XImage *image;          XImage *image;
# Line 1951  ui_create_glyph(int width, int height, u Line 2455  ui_create_glyph(int width, int height, u
2455          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);
2456    
2457          XFree(image);          XFree(image);
2458          return (HGLYPH) bitmap;          return (RD_HGLYPH) bitmap;
2459  }  }
2460    
2461  void  void
2462  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(RD_HGLYPH glyph)
2463  {  {
2464          XFreePixmap(g_display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2465  }  }
2466    
2467  HCURSOR  RD_HCURSOR
2468  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,
2469                   uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
2470  {  {
2471          HGLYPH maskglyph, cursorglyph;          RD_HGLYPH maskglyph, cursorglyph;
2472          XColor bg, fg;          XColor bg, fg;
2473          Cursor xcursor;          Cursor xcursor;
2474          uint8 *cursor, *pcursor;          uint8 *cursor, *pcursor;
# Line 2028  ui_create_cursor(unsigned int x, unsigne Line 2532  ui_create_cursor(unsigned int x, unsigne
2532          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2533          xfree(mask);          xfree(mask);
2534          xfree(cursor);          xfree(cursor);
2535          return (HCURSOR) xcursor;          return (RD_HCURSOR) xcursor;
2536  }  }
2537    
2538  void  void
2539  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(RD_HCURSOR cursor)
2540  {  {
2541          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2542          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2543            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2544  }  }
2545    
2546  void  void
2547  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(RD_HCURSOR cursor)
2548  {  {
2549          XFreeCursor(g_display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2550  }  }
# Line 2057  ui_set_null_cursor(void) Line 2562  ui_set_null_cursor(void)
2562                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2563    
2564    
2565  HCOLOURMAP  RD_HCOLOURMAP
2566  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
2567  {  {
2568          COLOURENTRY *entry;          COLOURENTRY *entry;
# Line 2153  ui_create_colourmap(COLOURMAP * colours) Line 2658  ui_create_colourmap(COLOURMAP * colours)
2658                  XStoreColors(g_display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2659    
2660                  xfree(xcolours);                  xfree(xcolours);
2661                  return (HCOLOURMAP) map;                  return (RD_HCOLOURMAP) map;
2662          }          }
2663  }  }
2664    
2665  void  void
2666  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(RD_HCOLOURMAP map)
2667  {  {
2668          if (!g_owncolmap)          if (!g_owncolmap)
2669                  xfree(map);                  xfree(map);
# Line 2167  ui_destroy_colourmap(HCOLOURMAP map) Line 2672  ui_destroy_colourmap(HCOLOURMAP map)
2672  }  }
2673    
2674  void  void
2675  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(RD_HCOLOURMAP map)
2676  {  {
2677          if (!g_owncolmap)          if (!g_owncolmap)
2678          {          {
# Line 2177  ui_set_colourmap(HCOLOURMAP map) Line 2682  ui_set_colourmap(HCOLOURMAP map)
2682                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2683          }          }
2684          else          else
2685            {
2686                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2687                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2688            }
2689  }  }
2690    
2691  void  void
2692  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2693  {  {
2694          XRectangle rect;          g_clip_rectangle.x = x;
2695            g_clip_rectangle.y = y;
2696          rect.x = x;          g_clip_rectangle.width = cx;
2697          rect.y = y;          g_clip_rectangle.height = cy;
2698          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);  
2699  }  }
2700    
2701  void  void
2702  ui_reset_clip(void)  ui_reset_clip(void)
2703  {  {
2704          XRectangle rect;          g_clip_rectangle.x = 0;
2705            g_clip_rectangle.y = 0;
2706          rect.x = 0;          g_clip_rectangle.width = g_width;
2707          rect.y = 0;          g_clip_rectangle.height = g_height;
2708          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);  
2709  }  }
2710    
2711  void  void
# Line 2256  ui_patblt(uint8 opcode, Line 2760  ui_patblt(uint8 opcode,
2760                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2761                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2762                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2763                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2764                          break;                          break;
2765    
2766                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2271  ui_patblt(uint8 opcode, Line 2775  ui_patblt(uint8 opcode,
2775                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2776                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2777                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2778                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2779                          break;                          break;
2780    
2781                  default:                  default:
# Line 2282  ui_patblt(uint8 opcode, Line 2786  ui_patblt(uint8 opcode,
2786    
2787          if (g_ownbackstore)          if (g_ownbackstore)
2788                  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);
2789            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2790                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2791                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2792  }  }
2793    
2794  void  void
# Line 2292  ui_screenblt(uint8 opcode, Line 2799  ui_screenblt(uint8 opcode,
2799          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2800          if (g_ownbackstore)          if (g_ownbackstore)
2801          {          {
2802                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2803                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2804                          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);  
                 }  
2805          }          }
2806          else          else
2807          {          {
2808                  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);
2809          }          }
2810    
2811            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2812                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2813                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2814    
2815          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2816  }  }
2817    
2818  void  void
2819  ui_memblt(uint8 opcode,  ui_memblt(uint8 opcode,
2820            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2821            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ RD_HBITMAP src, int srcx, int srcy)
2822  {  {
2823          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2824          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);
2825            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2826                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2827                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2828          if (g_ownbackstore)          if (g_ownbackstore)
2829                  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);
2830          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2327  ui_memblt(uint8 opcode, Line 2833  ui_memblt(uint8 opcode,
2833  void  void
2834  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2835            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2836            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ RD_HBITMAP src, int srcx, int srcy,
2837            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2838  {  {
2839          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
# Line 2365  ui_line(uint8 opcode, Line 2871  ui_line(uint8 opcode,
2871          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2872          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2873          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2874            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2875                                                startx - sw->xoffset, starty - sw->yoffset,
2876                                                endx - sw->xoffset, endy - sw->yoffset));
2877          if (g_ownbackstore)          if (g_ownbackstore)
2878                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2879          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2382  ui_rect( Line 2891  ui_rect(
2891  void  void
2892  ui_polygon(uint8 opcode,  ui_polygon(uint8 opcode,
2893             /* mode */ uint8 fillmode,             /* mode */ uint8 fillmode,
2894             /* dest */ POINT * point, int npoints,             /* dest */ RD_POINT * point, int npoints,
2895             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2896  {  {
2897          uint8 style, i, ipattern[8];          uint8 style, i, ipattern[8];
# Line 2425  ui_polygon(uint8 opcode, Line 2934  ui_polygon(uint8 opcode,
2934                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
2935                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2936                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2937                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2938                          break;                          break;
2939    
2940                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2440  ui_polygon(uint8 opcode, Line 2949  ui_polygon(uint8 opcode,
2949                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
2950                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2951                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2952                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2953                          break;                          break;
2954    
2955                  default:                  default:
# Line 2452  ui_polygon(uint8 opcode, Line 2961  ui_polygon(uint8 opcode,
2961    
2962  void  void
2963  ui_polyline(uint8 opcode,  ui_polyline(uint8 opcode,
2964              /* dest */ POINT * points, int npoints,              /* dest */ RD_POINT * points, int npoints,
2965              /* pen */ PEN * pen)              /* pen */ PEN * pen)
2966  {  {
2967          /* TODO: set join style */          /* TODO: set join style */
# Line 2462  ui_polyline(uint8 opcode, Line 2971  ui_polyline(uint8 opcode,
2971          if (g_ownbackstore)          if (g_ownbackstore)
2972                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2973                             CoordModePrevious);                             CoordModePrevious);
2974    
2975            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2976                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2977    
2978          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2979  }  }
2980    
# Line 2499  ui_ellipse(uint8 opcode, Line 3012  ui_ellipse(uint8 opcode,
3012                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3013                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3014                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3015                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3016                          break;                          break;
3017    
3018                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2514  ui_ellipse(uint8 opcode, Line 3027  ui_ellipse(uint8 opcode,
3027                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3028                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3029                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3030                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3031                          break;                          break;
3032    
3033                  default:                  default:
# Line 2528  ui_ellipse(uint8 opcode, Line 3041  ui_ellipse(uint8 opcode,
3041  void  void
3042  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
3043                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
3044                /* src */ HGLYPH glyph, int srcx, int srcy,                /* src */ RD_HGLYPH glyph, int srcx, int srcy,
3045                int bgcolour, int fgcolour)                int bgcolour, int fgcolour)
3046  {  {
3047          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
# Line 2682  ui_draw_text(uint8 font, uint8 flags, ui Line 3195  ui_draw_text(uint8 font, uint8 flags, ui
3195          if (g_ownbackstore)          if (g_ownbackstore)
3196          {          {
3197                  if (boxcx > 1)                  if (boxcx > 1)
3198                    {
3199                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3200                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3201                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3202                                                    (g_display, g_backstore, sw->wnd, g_gc,
3203                                                     boxx, boxy,
3204                                                     boxcx, boxcy,
3205                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3206                    }
3207                  else                  else
3208                    {
3209                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3210                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3211                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3212                                                    (g_display, g_backstore, sw->wnd, g_gc,
3213                                                     clipx, clipy,
3214                                                     clipcx, clipcy, clipx - sw->xoffset,
3215                                                     clipy - sw->yoffset));
3216                    }
3217          }          }
3218  }  }
3219    
# Line 2699  ui_desktop_save(uint32 offset, int x, in Line 3226  ui_desktop_save(uint32 offset, int x, in
3226          if (g_ownbackstore)          if (g_ownbackstore)
3227          {          {
3228                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3229                    exit_if_null(image);
3230          }          }
3231          else          else
3232          {          {
3233                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3234                  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);
3235                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3236                    exit_if_null(image);
3237                  XFreePixmap(g_display, pix);                  XFreePixmap(g_display, pix);
3238          }          }
3239    
# Line 2726  ui_desktop_restore(uint32 offset, int x, Line 3255  ui_desktop_restore(uint32 offset, int x,
3255                  return;                  return;
3256    
3257          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3258                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3259    
3260          if (g_ownbackstore)          if (g_ownbackstore)
3261          {          {
3262                  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);
3263                  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);
3264                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3265                                            (g_display, g_backstore, sw->wnd, g_gc,
3266                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3267          }          }
3268          else          else
3269          {          {
3270                  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);
3271                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3272                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3273                                             x - sw->xoffset, y - sw->yoffset));
3274          }          }
3275    
3276          XFree(image);          XFree(image);
# Line 2751  void Line 3286  void
3286  ui_end_update(void)  ui_end_update(void)
3287  {  {
3288  }  }
3289    
3290    
3291    void
3292    ui_seamless_begin(RD_BOOL hidden)
3293    {
3294            if (!g_seamless_rdp)
3295                    return;
3296    
3297            if (g_seamless_started)
3298                    return;
3299    
3300            g_seamless_started = True;
3301            g_seamless_hidden = hidden;
3302    
3303            if (!hidden)
3304                    ui_seamless_toggle();
3305    }
3306    
3307    
3308    void
3309    ui_seamless_hide_desktop()
3310    {
3311            if (!g_seamless_rdp)
3312                    return;
3313    
3314            if (!g_seamless_started)
3315                    return;
3316    
3317            if (g_seamless_active)
3318                    ui_seamless_toggle();
3319    
3320            g_seamless_hidden = True;
3321    }
3322    
3323    
3324    void
3325    ui_seamless_unhide_desktop()
3326    {
3327            if (!g_seamless_rdp)
3328                    return;
3329    
3330            if (!g_seamless_started)
3331                    return;
3332    
3333            g_seamless_hidden = False;
3334    
3335            ui_seamless_toggle();
3336    }
3337    
3338    
3339    void
3340    ui_seamless_toggle()
3341    {
3342            if (!g_seamless_rdp)
3343                    return;
3344    
3345            if (!g_seamless_started)
3346                    return;
3347    
3348            if (g_seamless_hidden)
3349                    return;
3350    
3351            if (g_seamless_active)
3352            {
3353                    /* Deactivate */
3354                    while (g_seamless_windows)
3355                    {
3356                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3357                            sw_remove_window(g_seamless_windows);
3358                    }
3359                    XMapWindow(g_display, g_wnd);
3360            }
3361            else
3362            {
3363                    /* Activate */
3364                    XUnmapWindow(g_display, g_wnd);
3365                    seamless_send_sync();
3366            }
3367    
3368            g_seamless_active = !g_seamless_active;
3369    }
3370    
3371    
3372    void
3373    ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3374                              unsigned long flags)
3375    {
3376            Window wnd;
3377            XSetWindowAttributes attribs;
3378            XClassHint *classhints;
3379            XSizeHints *sizehints;
3380            XWMHints *wmhints;
3381            long input_mask;
3382            seamless_window *sw, *sw_parent;
3383    
3384            if (!g_seamless_active)
3385                    return;
3386    
3387            /* Ignore CREATEs for existing windows */
3388            sw = sw_get_window_by_id(id);
3389            if (sw)
3390                    return;
3391    
3392            get_window_attribs(&attribs);
3393            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3394                                InputOutput, g_visual,
3395                                CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3396    
3397            XStoreName(g_display, wnd, "SeamlessRDP");
3398            ewmh_set_wm_name(wnd, "SeamlessRDP");
3399    
3400            mwm_hide_decorations(wnd);
3401    
3402            classhints = XAllocClassHint();
3403            if (classhints != NULL)
3404            {
3405                    classhints->res_name = "rdesktop";
3406                    classhints->res_class = "SeamlessRDP";
3407                    XSetClassHint(g_display, wnd, classhints);
3408                    XFree(classhints);
3409            }
3410    
3411            /* WM_NORMAL_HINTS */
3412            sizehints = XAllocSizeHints();
3413            if (sizehints != NULL)
3414            {
3415                    sizehints->flags = USPosition;
3416                    XSetWMNormalHints(g_display, wnd, sizehints);
3417                    XFree(sizehints);
3418            }
3419    
3420            /* Parent-less transient windows */
3421            if (parent == 0xFFFFFFFF)
3422            {
3423                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3424                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3425                       using some other hints. */
3426                    ewmh_set_window_popup(wnd);
3427            }
3428            /* Normal transient windows */
3429            else if (parent != 0x00000000)
3430            {
3431                    sw_parent = sw_get_window_by_id(parent);
3432                    if (sw_parent)
3433                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3434                    else
3435                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3436            }
3437    
3438            if (flags & SEAMLESSRDP_CREATE_MODAL)
3439            {
3440                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3441                       somewhat at least */
3442                    if (parent == 0x00000000)
3443                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3444                    ewmh_set_window_modal(wnd);
3445            }
3446    
3447            /* FIXME: Support for Input Context:s */
3448    
3449            get_input_mask(&input_mask);
3450            input_mask |= PropertyChangeMask;
3451    
3452            XSelectInput(g_display, wnd, input_mask);
3453    
3454            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3455               seamless window, we could try to close the window on the
3456               serverside, instead of terminating rdesktop */
3457            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3458    
3459            sw = xmalloc(sizeof(seamless_window));
3460    
3461            memset(sw, 0, sizeof(seamless_window));
3462    
3463            sw->wnd = wnd;
3464            sw->id = id;
3465            sw->group = sw_find_group(group, False);
3466            sw->group->refcnt++;
3467            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3468            sw->desktop = 0;
3469            sw->position_timer = xmalloc(sizeof(struct timeval));
3470            timerclear(sw->position_timer);
3471    
3472            sw->outstanding_position = False;
3473            sw->outpos_serial = 0;
3474            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3475            sw->outpos_width = sw->outpos_height = 0;
3476    
3477            sw->next = g_seamless_windows;
3478            g_seamless_windows = sw;
3479    
3480            /* WM_HINTS */
3481            wmhints = XAllocWMHints();
3482            if (wmhints)
3483            {
3484                    wmhints->flags = WindowGroupHint;
3485                    wmhints->window_group = sw->group->wnd;
3486                    XSetWMHints(g_display, sw->wnd, wmhints);
3487                    XFree(wmhints);
3488            }
3489    }
3490    
3491    
3492    void
3493    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3494    {
3495            seamless_window *sw;
3496    
3497            if (!g_seamless_active)
3498                    return;
3499    
3500            sw = sw_get_window_by_id(id);
3501            if (!sw)
3502            {
3503                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3504                    return;
3505            }
3506    
3507            XDestroyWindow(g_display, sw->wnd);
3508            sw_remove_window(sw);
3509    }
3510    
3511    
3512    void
3513    ui_seamless_destroy_group(unsigned long id, unsigned long flags)
3514    {
3515            seamless_window *sw, *sw_next;
3516    
3517            if (!g_seamless_active)
3518                    return;
3519    
3520            for (sw = g_seamless_windows; sw; sw = sw_next)
3521            {
3522                    sw_next = sw->next;
3523    
3524                    if (sw->group->id == id)
3525                    {
3526                            XDestroyWindow(g_display, sw->wnd);
3527                            sw_remove_window(sw);
3528                    }
3529            }
3530    }
3531    
3532    
3533    void
3534    ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
3535                        const char *data, int chunk_len)
3536    {
3537            seamless_window *sw;
3538    
3539            if (!g_seamless_active)
3540                    return;
3541    
3542            sw = sw_get_window_by_id(id);
3543            if (!sw)
3544            {
3545                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3546                    return;
3547            }
3548    
3549            if (chunk == 0)
3550            {
3551                    if (sw->icon_size)
3552                            warning("ui_seamless_seticon: New icon started before previous completed\n");
3553    
3554                    if (strcmp(format, "RGBA") != 0)
3555                    {
3556                            warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3557                            return;
3558                    }
3559    
3560                    sw->icon_size = width * height * 4;
3561                    if (sw->icon_size > 32 * 32 * 4)
3562                    {
3563                            warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
3564                            sw->icon_size = 0;
3565                            return;
3566                    }
3567    
3568                    sw->icon_offset = 0;
3569            }
3570            else
3571            {
3572                    if (!sw->icon_size)
3573                            return;
3574            }
3575    
3576            if (chunk_len > (sw->icon_size - sw->icon_offset))
3577            {
3578                    warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
3579                            chunk_len, sw->icon_size - sw->icon_offset);
3580                    sw->icon_size = 0;
3581                    return;
3582            }
3583    
3584            memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
3585            sw->icon_offset += chunk_len;
3586    
3587            if (sw->icon_offset == sw->icon_size)
3588            {
3589                    ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
3590                    sw->icon_size = 0;
3591            }
3592    }
3593    
3594    
3595    void
3596    ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
3597    {
3598            seamless_window *sw;
3599    
3600            if (!g_seamless_active)
3601                    return;
3602    
3603            sw = sw_get_window_by_id(id);
3604            if (!sw)
3605            {
3606                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3607                    return;
3608            }
3609    
3610            if (strcmp(format, "RGBA") != 0)
3611            {
3612                    warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3613                    return;
3614            }
3615    
3616            ewmh_del_icon(sw->wnd, width, height);
3617    }
3618    
3619    
3620    void
3621    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3622    {
3623            seamless_window *sw;
3624    
3625            if (!g_seamless_active)
3626                    return;
3627    
3628            sw = sw_get_window_by_id(id);
3629            if (!sw)
3630            {
3631                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3632                    return;
3633            }
3634    
3635            /* We ignore server updates until it has handled our request. */
3636            if (sw->outstanding_position)
3637                    return;
3638    
3639            if (!width || !height)
3640                    /* X11 windows must be at least 1x1 */
3641                    return;
3642    
3643            sw->xoffset = x;
3644            sw->yoffset = y;
3645            sw->width = width;
3646            sw->height = height;
3647    
3648            /* If we move the window in a maximized state, then KDE won't
3649               accept restoration */
3650            switch (sw->state)
3651            {
3652                    case SEAMLESSRDP_MINIMIZED:
3653                    case SEAMLESSRDP_MAXIMIZED:
3654                            return;
3655            }
3656    
3657            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3658            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3659    }
3660    
3661    
3662    void
3663    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3664    {
3665            seamless_window *sw;
3666    
3667            if (!g_seamless_active)
3668                    return;
3669    
3670            sw = sw_get_window_by_id(id);
3671            if (!sw)
3672            {
3673                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3674                    return;
3675            }
3676    
3677            if (behind)
3678            {
3679                    seamless_window *sw_behind;
3680                    Window wnds[2];
3681    
3682                    sw_behind = sw_get_window_by_id(behind);
3683                    if (!sw_behind)
3684                    {
3685                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3686                                    behind);
3687                            return;
3688                    }
3689    
3690                    wnds[1] = sw_behind->wnd;
3691                    wnds[0] = sw->wnd;
3692    
3693                    XRestackWindows(g_display, wnds, 2);
3694            }
3695            else
3696            {
3697                    XRaiseWindow(g_display, sw->wnd);
3698            }
3699    
3700            sw_restack_window(sw, behind);
3701    }
3702    
3703    
3704    void
3705    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3706    {
3707            seamless_window *sw;
3708    
3709            if (!g_seamless_active)
3710                    return;
3711    
3712            sw = sw_get_window_by_id(id);
3713            if (!sw)
3714            {
3715                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3716                    return;
3717            }
3718    
3719            /* FIXME: Might want to convert the name for non-EWMH WMs */
3720            XStoreName(g_display, sw->wnd, title);
3721            ewmh_set_wm_name(sw->wnd, title);
3722    }
3723    
3724    
3725    void
3726    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3727    {
3728            seamless_window *sw;
3729    
3730            if (!g_seamless_active)
3731                    return;
3732    
3733            sw = sw_get_window_by_id(id);
3734            if (!sw)
3735            {
3736                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3737                    return;
3738            }
3739    
3740            switch (state)
3741            {
3742                    case SEAMLESSRDP_NORMAL:
3743                    case SEAMLESSRDP_MAXIMIZED:
3744                            ewmh_change_state(sw->wnd, state);
3745                            XMapWindow(g_display, sw->wnd);
3746                            break;
3747                    case SEAMLESSRDP_MINIMIZED:
3748                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3749                               the Window Manager should probably just ignore the request, since
3750                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3751                               such as minimization, rather than an independent state." Besides,
3752                               XIconifyWindow is easier. */
3753                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3754                            {
3755                                    XWMHints *hints;
3756                                    hints = XGetWMHints(g_display, sw->wnd);
3757                                    if (hints)
3758                                    {
3759                                            hints->flags |= StateHint;
3760                                            hints->initial_state = IconicState;
3761                                            XSetWMHints(g_display, sw->wnd, hints);
3762                                            XFree(hints);
3763                                    }
3764                                    XMapWindow(g_display, sw->wnd);
3765                            }
3766                            else
3767                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3768                            break;
3769                    default:
3770                            warning("SeamlessRDP: Invalid state %d\n", state);
3771                            break;
3772            }
3773    
3774            sw->state = state;
3775    }
3776    
3777    
3778    void
3779    ui_seamless_syncbegin(unsigned long flags)
3780    {
3781            if (!g_seamless_active)
3782                    return;
3783    
3784            /* Destroy all seamless windows */
3785            while (g_seamless_windows)
3786            {
3787                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3788                    sw_remove_window(g_seamless_windows);
3789            }
3790    }
3791    
3792    
3793    void
3794    ui_seamless_ack(unsigned int serial)
3795    {
3796            seamless_window *sw;
3797            for (sw = g_seamless_windows; sw; sw = sw->next)
3798            {
3799                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3800                    {
3801                            sw->xoffset = sw->outpos_xoffset;
3802                            sw->yoffset = sw->outpos_yoffset;
3803                            sw->width = sw->outpos_width;
3804                            sw->height = sw->outpos_height;
3805                            sw->outstanding_position = False;
3806    
3807                            /* Do a complete redraw of the window as part of the
3808                               completion of the move. This is to remove any
3809                               artifacts caused by our lack of synchronization. */
3810                            XCopyArea(g_display, g_backstore,
3811                                      sw->wnd, g_gc,
3812                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3813    
3814                            break;
3815                    }
3816            }
3817    }

Legend:
Removed from v.1049  
changed lines
  Added in v.1413

  ViewVC Help
Powered by ViewVC 1.1.26