/[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 1403 by stargo, Thu Apr 12 16:04:25 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    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <X11/Xproto.h>
24  #include <unistd.h>  #include <unistd.h>
25  #include <sys/time.h>  #include <sys/time.h>
26  #include <time.h>  #include <time.h>
# Line 33  extern int g_height; Line 34  extern int g_height;
34  extern int g_xpos;  extern int g_xpos;
35  extern int g_ypos;  extern int g_ypos;
36  extern int g_pos;  extern int g_pos;
37  extern BOOL g_sendmotion;  extern RD_BOOL g_sendmotion;
38  extern BOOL g_fullscreen;  extern RD_BOOL g_fullscreen;
39  extern BOOL g_grab_keyboard;  extern RD_BOOL g_grab_keyboard;
40  extern BOOL g_hide_decorations;  extern RD_BOOL g_hide_decorations;
41  extern char g_title[];  extern char g_title[];
42  /* Color depth of the RDP session.  /* Color depth of the RDP session.
43     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 49  Time g_last_gesturetime;
49  static int g_x_socket;  static int g_x_socket;
50  static Screen *g_screen;  static Screen *g_screen;
51  Window g_wnd;  Window g_wnd;
52    
53    /* SeamlessRDP support */
54    typedef struct _seamless_group
55    {
56            Window wnd;
57            unsigned long id;
58            unsigned int refcnt;
59    } seamless_group;
60    typedef struct _seamless_window
61    {
62            Window wnd;
63            unsigned long id;
64            unsigned long behind;
65            seamless_group *group;
66            int xoffset, yoffset;
67            int width, height;
68            int state;              /* normal/minimized/maximized. */
69            unsigned int desktop;
70            struct timeval *position_timer;
71    
72            RD_BOOL outstanding_position;
73            unsigned int outpos_serial;
74            int outpos_xoffset, outpos_yoffset;
75            int outpos_width, outpos_height;
76    
77            struct _seamless_window *next;
78    } seamless_window;
79    static seamless_window *g_seamless_windows = NULL;
80    static unsigned long g_seamless_focused = 0;
81    static RD_BOOL g_seamless_started = False;      /* Server end is up and running */
82    static RD_BOOL g_seamless_active = False;       /* We are currently in seamless mode */
83    static RD_BOOL g_seamless_hidden = False;       /* Desktop is hidden on server */
84    extern RD_BOOL g_seamless_rdp;
85    
86  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
87  BOOL g_enable_compose = False;  RD_BOOL g_enable_compose = False;
88  BOOL g_Unobscured;              /* used for screenblt */  RD_BOOL g_Unobscured;           /* used for screenblt */
89  static GC g_gc = NULL;  static GC g_gc = NULL;
90  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
91  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
92    static XRectangle g_clip_rectangle;
93  static Visual *g_visual;  static Visual *g_visual;
94  /* 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).
95     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 67  static XIM g_IM; Line 103  static XIM g_IM;
103  static XIC g_IC;  static XIC g_IC;
104  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
105  static Cursor g_current_cursor;  static Cursor g_current_cursor;
106  static HCURSOR g_null_cursor = NULL;  static RD_HCURSOR g_null_cursor = NULL;
107  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
108  static BOOL g_focused;  extern Atom g_net_wm_state_atom;
109  static BOOL g_mouse_in_wnd;  extern Atom g_net_wm_desktop_atom;
110    static RD_BOOL g_focused;
111    static RD_BOOL g_mouse_in_wnd;
112  /* Indicates that:  /* Indicates that:
113     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
114        as its RDP equivalent (implies X server is LE),        as its RDP equivalent (implies X server is LE),
115     2) host is LE     2) host is LE
116     This will trigger an optimization whose real value is questionable.     This will trigger an optimization whose real value is questionable.
117  */  */
118  static BOOL g_compatible_arch;  static RD_BOOL g_compatible_arch;
119  /* Indicates whether RDP's bitmaps and our XImages have the same  /* Indicates whether RDP's bitmaps and our XImages have the same
120     binary format. If so, we can avoid an expensive translation.     binary format. If so, we can avoid an expensive translation.
121     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 126  static BOOL g_compatible_arch;
126     ('host' is the machine running rdesktop; the host simply memcpy's     ('host' is the machine running rdesktop; the host simply memcpy's
127      so its endianess doesn't matter)      so its endianess doesn't matter)
128   */   */
129  static BOOL g_no_translate_image = False;  static RD_BOOL g_no_translate_image = False;
130    
131  /* endianness */  /* endianness */
132  static BOOL g_host_be;  static RD_BOOL g_host_be;
133  static BOOL g_xserver_be;  static RD_BOOL g_xserver_be;
134  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;
135  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;
136    
137  /* software backing store */  /* software backing store */
138  extern BOOL g_ownbackstore;  extern RD_BOOL g_ownbackstore;
139  static Pixmap g_backstore = 0;  static Pixmap g_backstore = 0;
140    
141  /* Moving in single app mode */  /* Moving in single app mode */
142  static BOOL g_moving_wnd;  static RD_BOOL g_moving_wnd;
143  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
144  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
145  static BOOL g_using_full_workarea = False;  static RD_BOOL g_using_full_workarea = False;
146    
147  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
148  extern int g_dsp_fd;  extern RD_BOOL g_rdpsnd;
 extern BOOL g_dsp_busy;  
 extern BOOL g_rdpsnd;  
149  #endif  #endif
150    
151  /* MWM decorations */  /* MWM decorations */
# Line 133  typedef struct Line 169  typedef struct
169  }  }
170  PixelColour;  PixelColour;
171    
172    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
173            do { \
174                    seamless_window *sw; \
175                    XRectangle rect; \
176                    if (!g_seamless_windows) break; \
177                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
178                        rect.x = g_clip_rectangle.x - sw->xoffset; \
179                        rect.y = g_clip_rectangle.y - sw->yoffset; \
180                        rect.width = g_clip_rectangle.width; \
181                        rect.height = g_clip_rectangle.height; \
182                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
183                        func args; \
184                    } \
185                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
186            } while (0)
187    
188    static void
189    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
190    {
191            points[0].x -= xoffset;
192            points[0].y -= yoffset;
193            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
194            points[0].x += xoffset;
195            points[0].y += yoffset;
196    }
197    
198    static void
199    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
200    {
201            points[0].x -= xoffset;
202            points[0].y -= yoffset;
203            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
204            points[0].x += xoffset;
205            points[0].y += yoffset;
206    }
207    
208  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
209  { \  { \
210          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
211            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
212          if (g_ownbackstore) \          if (g_ownbackstore) \
213                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
214  }  }
# Line 151  PixelColour; Line 223  PixelColour;
223          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
224          if (g_ownbackstore) \          if (g_ownbackstore) \
225                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
226            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
227  }  }
228    
229  #define DRAW_ELLIPSE(x,y,cx,cy,m)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 159  PixelColour; Line 232  PixelColour;
232          { \          { \
233                  case 0: /* Outline */ \                  case 0: /* Outline */ \
234                          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); \
235                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
236                          if (g_ownbackstore) \                          if (g_ownbackstore) \
237                                  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); \
238                          break; \                          break; \
239                  case 1: /* Filled */ \                  case 1: /* Filled */ \
240                          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); \
241                            ON_ALL_SEAMLESS_WINDOWS(XFillArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
242                          if (g_ownbackstore) \                          if (g_ownbackstore) \
243                                  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); \
244                          break; \                          break; \
# Line 171  PixelColour; Line 246  PixelColour;
246  }  }
247    
248  /* colour maps */  /* colour maps */
249  extern BOOL g_owncolmap;  extern RD_BOOL g_owncolmap;
250  static Colormap g_xcolmap;  static Colormap g_xcolmap;
251  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
252    
# Line 201  static int rop2_map[] = { Line 276  static int rop2_map[] = {
276  #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]); }
277  #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); }
278    
279    static seamless_window *
280    sw_get_window_by_id(unsigned long id)
281    {
282            seamless_window *sw;
283            for (sw = g_seamless_windows; sw; sw = sw->next)
284            {
285                    if (sw->id == id)
286                            return sw;
287            }
288            return NULL;
289    }
290    
291    
292    static seamless_window *
293    sw_get_window_by_wnd(Window wnd)
294    {
295            seamless_window *sw;
296            for (sw = g_seamless_windows; sw; sw = sw->next)
297            {
298                    if (sw->wnd == wnd)
299                            return sw;
300            }
301            return NULL;
302    }
303    
304    
305    static void
306    sw_remove_window(seamless_window * win)
307    {
308            seamless_window *sw, **prevnext = &g_seamless_windows;
309            for (sw = g_seamless_windows; sw; sw = sw->next)
310            {
311                    if (sw == win)
312                    {
313                            *prevnext = sw->next;
314                            sw->group->refcnt--;
315                            if (sw->group->refcnt == 0)
316                            {
317                                    XDestroyWindow(g_display, sw->group->wnd);
318                                    xfree(sw->group);
319                            }
320                            xfree(sw->position_timer);
321                            xfree(sw);
322                            return;
323                    }
324                    prevnext = &sw->next;
325            }
326            return;
327    }
328    
329    
330    /* Move all windows except wnd to new desktop */
331    static void
332    sw_all_to_desktop(Window wnd, unsigned int desktop)
333    {
334            seamless_window *sw;
335            for (sw = g_seamless_windows; sw; sw = sw->next)
336            {
337                    if (sw->wnd == wnd)
338                            continue;
339                    if (sw->desktop != desktop)
340                    {
341                            ewmh_move_to_desktop(sw->wnd, desktop);
342                            sw->desktop = desktop;
343                    }
344            }
345    }
346    
347    
348    /* Send our position */
349    static void
350    sw_update_position(seamless_window * sw)
351    {
352            XWindowAttributes wa;
353            int x, y;
354            Window child_return;
355            unsigned int serial;
356    
357            XGetWindowAttributes(g_display, sw->wnd, &wa);
358            XTranslateCoordinates(g_display, sw->wnd, wa.root,
359                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
360    
361            serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
362    
363            sw->outstanding_position = True;
364            sw->outpos_serial = serial;
365    
366            sw->outpos_xoffset = x;
367            sw->outpos_yoffset = y;
368            sw->outpos_width = wa.width;
369            sw->outpos_height = wa.height;
370    }
371    
372    
373    /* Check if it's time to send our position */
374    static void
375    sw_check_timers()
376    {
377            seamless_window *sw;
378            struct timeval now;
379    
380            gettimeofday(&now, NULL);
381            for (sw = g_seamless_windows; sw; sw = sw->next)
382            {
383                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
384                    {
385                            timerclear(sw->position_timer);
386                            sw_update_position(sw);
387                    }
388            }
389    }
390    
391    
392    static void
393    sw_restack_window(seamless_window * sw, unsigned long behind)
394    {
395            seamless_window *sw_above;
396    
397            /* Remove window from stack */
398            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
399            {
400                    if (sw_above->behind == sw->id)
401                            break;
402            }
403    
404            if (sw_above)
405                    sw_above->behind = sw->behind;
406    
407            /* And then add it at the new position */
408            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
409            {
410                    if (sw_above->behind == behind)
411                            break;
412            }
413    
414            if (sw_above)
415                    sw_above->behind = sw->id;
416    
417            sw->behind = behind;
418    }
419    
420    
421    static void
422    sw_handle_restack(seamless_window * sw)
423    {
424            Status status;
425            Window root, parent, *children;
426            unsigned int nchildren, i;
427            seamless_window *sw_below;
428    
429            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
430                                &root, &parent, &children, &nchildren);
431            if (!status || !nchildren)
432                    return;
433    
434            sw_below = NULL;
435    
436            i = 0;
437            while (children[i] != sw->wnd)
438            {
439                    i++;
440                    if (i >= nchildren)
441                            goto end;
442            }
443    
444            for (i++; i < nchildren; i++)
445            {
446                    sw_below = sw_get_window_by_wnd(children[i]);
447                    if (sw_below)
448                            break;
449            }
450    
451            if (!sw_below && !sw->behind)
452                    goto end;
453            if (sw_below && (sw_below->id == sw->behind))
454                    goto end;
455    
456            if (sw_below)
457            {
458                    seamless_send_zchange(sw->id, sw_below->id, 0);
459                    sw_restack_window(sw, sw_below->id);
460            }
461            else
462            {
463                    seamless_send_zchange(sw->id, 0, 0);
464                    sw_restack_window(sw, 0);
465            }
466    
467          end:
468            XFree(children);
469    }
470    
471    
472    static seamless_group *
473    sw_find_group(unsigned long id, RD_BOOL dont_create)
474    {
475            seamless_window *sw;
476            seamless_group *sg;
477            XSetWindowAttributes attribs;
478    
479            for (sw = g_seamless_windows; sw; sw = sw->next)
480            {
481                    if (sw->group->id == id)
482                            return sw->group;
483            }
484    
485            if (dont_create)
486                    return NULL;
487    
488            sg = xmalloc(sizeof(seamless_group));
489    
490            sg->wnd =
491                    XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0,
492                                  CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
493    
494            sg->id = id;
495            sg->refcnt = 0;
496    
497            return sg;
498    }
499    
500    
501  static void  static void
502  mwm_hide_decorations(void)  mwm_hide_decorations(Window wnd)
503  {  {
504          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
505          Atom hintsatom;          Atom hintsatom;
# Line 219  mwm_hide_decorations(void) Line 516  mwm_hide_decorations(void)
516                  return;                  return;
517          }          }
518    
519          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
520                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
521    
522  }  }
523    
524  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 962  translate_image(int width, int height, u Line 1260  translate_image(int width, int height, u
1260          return out;          return out;
1261  }  }
1262    
1263  BOOL  RD_BOOL
1264  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1265  {  {
1266          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
# Line 1010  calculate_mask_weight(uint32 mask) Line 1308  calculate_mask_weight(uint32 mask)
1308          return weight;          return weight;
1309  }  }
1310    
1311  static BOOL  static RD_BOOL
1312  select_visual()  select_visual(int screen_num)
1313  {  {
1314          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1315          int pixmap_formats_count, visuals_count;          int pixmap_formats_count, visuals_count;
# Line 1022  select_visual() Line 1320  select_visual()
1320    
1321          red_weight = blue_weight = green_weight = 0;          red_weight = blue_weight = green_weight = 0;
1322    
1323            if (g_server_depth == -1)
1324            {
1325                    g_server_depth = DisplayPlanes(g_display, DefaultScreen(g_display));
1326            }
1327    
1328          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1329          if (pfm == NULL)          if (pfm == NULL)
1330          {          {
# Line 1032  select_visual() Line 1335  select_visual()
1335    
1336          /* Search for best TrueColor visual */          /* Search for best TrueColor visual */
1337          template.class = TrueColor;          template.class = TrueColor;
1338          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);          template.screen = screen_num;
1339            vmatches =
1340                    XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template,
1341                                   &visuals_count);
1342          g_visual = NULL;          g_visual = NULL;
1343          g_no_translate_image = False;          g_no_translate_image = False;
1344          g_compatible_arch = False;          g_compatible_arch = False;
# Line 1041  select_visual() Line 1347  select_visual()
1347                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
1348                  {                  {
1349                          XVisualInfo *visual_info = &vmatches[i];                          XVisualInfo *visual_info = &vmatches[i];
1350                            RD_BOOL can_translate_to_bpp = False;
1351                            int j;
1352    
1353                          /* Try to find a no-translation visual that'll                          /* Try to find a no-translation visual that'll
1354                             allow us to use RDP bitmaps directly as ZPixmaps. */                             allow us to use RDP bitmaps directly as ZPixmaps. */
# Line 1084  select_visual() Line 1392  select_visual()
1392    
1393                          /* Only care for visuals, for whose BPPs (not depths!)                          /* Only care for visuals, for whose BPPs (not depths!)
1394                             we have a translateXtoY function. */                             we have a translateXtoY function. */
                         BOOL can_translate_to_bpp = False;  
                         int j;  
1395                          for (j = 0; j < pixmap_formats_count; ++j)                          for (j = 0; j < pixmap_formats_count; ++j)
1396                          {                          {
1397                                  if (pfm[j].depth == visual_info->depth)                                  if (pfm[j].depth == visual_info->depth)
# Line 1197  select_visual() Line 1503  select_visual()
1503          return True;          return True;
1504  }  }
1505    
1506  BOOL  static XErrorHandler g_old_error_handler;
1507    
1508    static int
1509    error_handler(Display * dpy, XErrorEvent * eev)
1510    {
1511            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1512            {
1513                    fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1514                    fprintf(stderr,
1515                            "This is most likely caused by a broken window manager (commonly KWin).\n");
1516                    return 0;
1517            }
1518    
1519            return g_old_error_handler(dpy, eev);
1520    }
1521    
1522    RD_BOOL
1523  ui_init(void)  ui_init(void)
1524  {  {
1525          int screen_num;          int screen_num;
# Line 1211  ui_init(void) Line 1533  ui_init(void)
1533    
1534          {          {
1535                  uint16 endianess_test = 1;                  uint16 endianess_test = 1;
1536                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test));
1537          }          }
1538    
1539            g_old_error_handler = XSetErrorHandler(error_handler);
1540          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1541          screen_num = DefaultScreen(g_display);          screen_num = DefaultScreen(g_display);
1542          g_x_socket = ConnectionNumber(g_display);          g_x_socket = ConnectionNumber(g_display);
1543          g_screen = ScreenOfDisplay(g_display, screen_num);          g_screen = ScreenOfDisplay(g_display, screen_num);
1544          g_depth = DefaultDepthOfScreen(g_screen);          g_depth = DefaultDepthOfScreen(g_screen);
1545    
1546          if (!select_visual())          if (!select_visual(screen_num))
1547                  return False;                  return False;
1548    
1549          if (g_no_translate_image)          if (g_no_translate_image)
# Line 1259  ui_init(void) Line 1582  ui_init(void)
1582          {          {
1583                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1584                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1585                    g_using_full_workarea = True;
1586          }          }
1587          else if (g_width < 0)          else if (g_width < 0)
1588          {          {
# Line 1272  ui_init(void) Line 1596  ui_init(void)
1596          {          {
1597                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1598                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
                 g_using_full_workarea = True;  
   
1599                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1600                  {                  {
1601                          g_width = cx;                          g_width = cx;
1602                          g_height = cy;                          g_height = cy;
1603                            g_using_full_workarea = True;
1604                  }                  }
1605                  else                  else
1606                  {                  {
1607                          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");
1608                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1609                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1610                  }                  }
1611          }          }
1612    
# Line 1298  ui_init(void) Line 1621  ui_init(void)
1621                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1622    
1623          xclip_init();          xclip_init();
1624            ewmh_init();
1625            if (g_seamless_rdp)
1626                    seamless_init();
1627    
1628          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));
1629    
# Line 1307  ui_init(void) Line 1633  ui_init(void)
1633  void  void
1634  ui_deinit(void)  ui_deinit(void)
1635  {  {
1636            while (g_seamless_windows)
1637            {
1638                    XDestroyWindow(g_display, g_seamless_windows->wnd);
1639                    sw_remove_window(g_seamless_windows);
1640            }
1641    
1642            xclip_deinit();
1643    
1644          if (g_IM != NULL)          if (g_IM != NULL)
1645                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1646    
# Line 1323  ui_deinit(void) Line 1657  ui_deinit(void)
1657          g_display = NULL;          g_display = NULL;
1658  }  }
1659    
1660  BOOL  
1661    static void
1662    get_window_attribs(XSetWindowAttributes * attribs)
1663    {
1664            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1665            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1666            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1667            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1668            attribs->override_redirect = g_fullscreen;
1669            attribs->colormap = g_xcolmap;
1670    }
1671    
1672    static void
1673    get_input_mask(long *input_mask)
1674    {
1675            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1676                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1677    
1678            if (g_sendmotion)
1679                    *input_mask |= PointerMotionMask;
1680            if (g_ownbackstore)
1681                    *input_mask |= ExposureMask;
1682            if (g_fullscreen || g_grab_keyboard)
1683                    *input_mask |= EnterWindowMask;
1684            if (g_grab_keyboard)
1685                    *input_mask |= LeaveWindowMask;
1686    }
1687    
1688    RD_BOOL
1689  ui_create_window(void)  ui_create_window(void)
1690  {  {
1691          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
# Line 1345  ui_create_window(void) Line 1707  ui_create_window(void)
1707          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1708                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1709    
1710          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;  
1711    
1712          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,
1713                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1357  ui_create_window(void) Line 1715  ui_create_window(void)
1715                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1716    
1717          if (g_gc == NULL)          if (g_gc == NULL)
1718            {
1719                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1720                    ui_reset_clip();
1721            }
1722    
1723          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1724                  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 1733  ui_create_window(void)
1733          }          }
1734    
1735          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1736            ewmh_set_wm_name(g_wnd, g_title);
1737    
1738          if (g_hide_decorations)          if (g_hide_decorations)
1739                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1740    
1741          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1742          if (classhints != NULL)          if (classhints != NULL)
# Line 1401  ui_create_window(void) Line 1763  ui_create_window(void)
1763                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1764          }          }
1765    
1766          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;  
1767    
1768          if (g_IM != NULL)          if (g_IM != NULL)
1769          {          {
# Line 1496  xwin_toggle_fullscreen(void) Line 1848  xwin_toggle_fullscreen(void)
1848  {  {
1849          Pixmap contents = 0;          Pixmap contents = 0;
1850    
1851            if (g_seamless_active)
1852                    /* Turn off SeamlessRDP mode */
1853                    ui_seamless_toggle();
1854    
1855          if (!g_ownbackstore)          if (!g_ownbackstore)
1856          {          {
1857                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1517  xwin_toggle_fullscreen(void) Line 1873  xwin_toggle_fullscreen(void)
1873  }  }
1874    
1875  static void  static void
1876  handle_button_event(XEvent xevent, BOOL down)  handle_button_event(XEvent xevent, RD_BOOL down)
1877  {  {
1878          uint16 button, flags = 0;          uint16 button, flags = 0;
1879          g_last_gesturetime = xevent.xbutton.time;          g_last_gesturetime = xevent.xbutton.time;
# Line 1584  handle_button_event(XEvent xevent, BOOL Line 1940  handle_button_event(XEvent xevent, BOOL
1940                  }                  }
1941          }          }
1942    
1943          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1944                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1945                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1946                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1947            }
1948            else
1949            {
1950                    /* SeamlessRDP */
1951                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1952                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1953            }
1954  }  }
1955    
1956    
1957  /* Process events in Xlib queue  /* Process events in Xlib queue
1958     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1959  static int  static int
# Line 1599  xwin_process_events(void) Line 1965  xwin_process_events(void)
1965          char str[256];          char str[256];
1966          Status status;          Status status;
1967          int events = 0;          int events = 0;
1968            seamless_window *sw;
1969    
1970          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1971          {          {
# Line 1613  xwin_process_events(void) Line 1980  xwin_process_events(void)
1980                  switch (xevent.type)                  switch (xevent.type)
1981                  {                  {
1982                          case VisibilityNotify:                          case VisibilityNotify:
1983                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1984                                            g_Unobscured =
1985                                                    xevent.xvisibility.state == VisibilityUnobscured;
1986    
1987                                  break;                                  break;
1988                          case ClientMessage:                          case ClientMessage:
1989                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1693  xwin_process_events(void) Line 2063  xwin_process_events(void)
2063                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
2064                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2065                                                         CurrentTime);                                                         CurrentTime);
2066                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
2067                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
2068                                    {
2069                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2070                                                           xevent.xmotion.x, xevent.xmotion.y);
2071                                    }
2072                                    else
2073                                    {
2074                                            /* SeamlessRDP */
2075                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2076                                                           xevent.xmotion.x_root,
2077                                                           xevent.xmotion.y_root);
2078                                    }
2079                                  break;                                  break;
2080    
2081                          case FocusIn:                          case FocusIn:
# Line 1705  xwin_process_events(void) Line 2086  xwin_process_events(void)
2086                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2087                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2088                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2089    
2090                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2091                                    if (!sw)
2092                                            break;
2093    
2094                                    if (sw->id != g_seamless_focused)
2095                                    {
2096                                            seamless_send_focus(sw->id, 0);
2097                                            g_seamless_focused = sw->id;
2098                                    }
2099                                  break;                                  break;
2100    
2101                          case FocusOut:                          case FocusOut:
# Line 1737  xwin_process_events(void) Line 2128  xwin_process_events(void)
2128                                  break;                                  break;
2129    
2130                          case Expose:                          case Expose:
2131                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2132                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2133                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2134                                            xevent.xexpose.height,                                                    g_gc,
2135                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2136                                                      xevent.xexpose.width, xevent.xexpose.height,
2137                                                      xevent.xexpose.x, xevent.xexpose.y);
2138                                    }
2139                                    else
2140                                    {
2141                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2142                                            if (!sw)
2143                                                    break;
2144                                            XCopyArea(g_display, g_backstore,
2145                                                      xevent.xexpose.window, g_gc,
2146                                                      xevent.xexpose.x + sw->xoffset,
2147                                                      xevent.xexpose.y + sw->yoffset,
2148                                                      xevent.xexpose.width,
2149                                                      xevent.xexpose.height, xevent.xexpose.x,
2150                                                      xevent.xexpose.y);
2151                                    }
2152    
2153                                  break;                                  break;
2154    
2155                          case MappingNotify:                          case MappingNotify:
# Line 1770  xwin_process_events(void) Line 2178  xwin_process_events(void)
2178                                  break;                                  break;
2179                          case PropertyNotify:                          case PropertyNotify:
2180                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2181                                    if (xevent.xproperty.window == g_wnd)
2182                                            break;
2183                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2184                                            break;
2185    
2186                                    /* seamless */
2187                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2188                                    if (!sw)
2189                                            break;
2190    
2191                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2192                                        && (xevent.xproperty.state == PropertyNewValue))
2193                                    {
2194                                            sw->state = ewmh_get_window_state(sw->wnd);
2195                                            seamless_send_state(sw->id, sw->state, 0);
2196                                    }
2197    
2198                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2199                                        && (xevent.xproperty.state == PropertyNewValue))
2200                                    {
2201                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2202                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2203                                    }
2204    
2205                                  break;                                  break;
2206                          case MapNotify:                          case MapNotify:
2207                                  rdp_send_client_window_status(1);                                  if (!g_seamless_active)
2208                                            rdp_send_client_window_status(1);
2209                                  break;                                  break;
2210                          case UnmapNotify:                          case UnmapNotify:
2211                                  rdp_send_client_window_status(0);                                  if (!g_seamless_active)
2212                                            rdp_send_client_window_status(0);
2213                                    break;
2214                            case ConfigureNotify:
2215                                    if (!g_seamless_active)
2216                                            break;
2217    
2218                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2219                                    if (!sw)
2220                                            break;
2221    
2222                                    gettimeofday(sw->position_timer, NULL);
2223                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2224                                        1000000)
2225                                    {
2226                                            sw->position_timer->tv_usec +=
2227                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2228                                            sw->position_timer->tv_sec += 1;
2229                                    }
2230                                    else
2231                                    {
2232                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2233                                    }
2234    
2235                                    sw_handle_restack(sw);
2236                                  break;                                  break;
2237                  }                  }
2238          }          }
# Line 1790  ui_select(int rdp_socket) Line 2247  ui_select(int rdp_socket)
2247          int n;          int n;
2248          fd_set rfds, wfds;          fd_set rfds, wfds;
2249          struct timeval tv;          struct timeval tv;
2250          BOOL s_timeout = False;          RD_BOOL s_timeout = False;
2251    
2252          while (True)          while (True)
2253          {          {
# Line 1800  ui_select(int rdp_socket) Line 2257  ui_select(int rdp_socket)
2257                          /* User quit */                          /* User quit */
2258                          return 0;                          return 0;
2259    
2260                    if (g_seamless_active)
2261                            sw_check_timers();
2262    
2263                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2264                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2265                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
2266                  FD_SET(g_x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
2267    
 #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  
2268                  /* default timeout */                  /* default timeout */
2269                  tv.tv_sec = 60;                  tv.tv_sec = 60;
2270                  tv.tv_usec = 0;                  tv.tv_usec = 0;
2271    
2272    #ifdef WITH_RDPSND
2273                    rdpsnd_add_fds(&n, &rfds, &wfds, &tv);
2274    #endif
2275    
2276                  /* add redirection handles */                  /* add redirection handles */
2277                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2278                    seamless_select_timeout(&tv);
2279    
2280                  n++;                  n++;
2281    
# Line 1828  ui_select(int rdp_socket) Line 2285  ui_select(int rdp_socket)
2285                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2286    
2287                          case 0:                          case 0:
2288    #ifdef WITH_RDPSND
2289                                    rdpsnd_check_fds(&rfds, &wfds);
2290    #endif
2291    
2292                                  /* Abort serial read calls */                                  /* Abort serial read calls */
2293                                  if (s_timeout)                                  if (s_timeout)
2294                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);                                          rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True);
2295                                  continue;                                  continue;
2296                  }                  }
2297    
2298                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);  #ifdef WITH_RDPSND
2299                    rdpsnd_check_fds(&rfds, &wfds);
2300    #endif
2301    
2302                    rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False);
2303    
2304                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2305                          return 1;                          return 1;
2306    
 #ifdef WITH_RDPSND  
                 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))  
                         wave_out_play();  
 #endif  
2307          }          }
2308  }  }
2309    
# Line 1852  ui_move_pointer(int x, int y) Line 2313  ui_move_pointer(int x, int y)
2313          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);
2314  }  }
2315    
2316  HBITMAP  RD_HBITMAP
2317  ui_create_bitmap(int width, int height, uint8 * data)  ui_create_bitmap(int width, int height, uint8 * data)
2318  {  {
2319          XImage *image;          XImage *image;
# Line 1882  ui_create_bitmap(int width, int height, Line 2343  ui_create_bitmap(int width, int height,
2343          XFree(image);          XFree(image);
2344          if (tdata != data)          if (tdata != data)
2345                  xfree(tdata);                  xfree(tdata);
2346          return (HBITMAP) bitmap;          return (RD_HBITMAP) bitmap;
2347  }  }
2348    
2349  void  void
# Line 1912  ui_paint_bitmap(int x, int y, int cx, in Line 2373  ui_paint_bitmap(int x, int y, int cx, in
2373          {          {
2374                  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);
2375                  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);
2376                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2377                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2378                                             x - sw->xoffset, y - sw->yoffset));
2379          }          }
2380          else          else
2381          {          {
2382                  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);
2383                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2384                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2385                                             x - sw->xoffset, y - sw->yoffset));
2386          }          }
2387    
2388          XFree(image);          XFree(image);
# Line 1924  ui_paint_bitmap(int x, int y, int cx, in Line 2391  ui_paint_bitmap(int x, int y, int cx, in
2391  }  }
2392    
2393  void  void
2394  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(RD_HBITMAP bmp)
2395  {  {
2396          XFreePixmap(g_display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2397  }  }
2398    
2399  HGLYPH  RD_HGLYPH
2400  ui_create_glyph(int width, int height, uint8 * data)  ui_create_glyph(int width, int height, uint8 * data)
2401  {  {
2402          XImage *image;          XImage *image;
# Line 1951  ui_create_glyph(int width, int height, u Line 2418  ui_create_glyph(int width, int height, u
2418          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);
2419    
2420          XFree(image);          XFree(image);
2421          return (HGLYPH) bitmap;          return (RD_HGLYPH) bitmap;
2422  }  }
2423    
2424  void  void
2425  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(RD_HGLYPH glyph)
2426  {  {
2427          XFreePixmap(g_display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2428  }  }
2429    
2430  HCURSOR  RD_HCURSOR
2431  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,
2432                   uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
2433  {  {
2434          HGLYPH maskglyph, cursorglyph;          RD_HGLYPH maskglyph, cursorglyph;
2435          XColor bg, fg;          XColor bg, fg;
2436          Cursor xcursor;          Cursor xcursor;
2437          uint8 *cursor, *pcursor;          uint8 *cursor, *pcursor;
# Line 2028  ui_create_cursor(unsigned int x, unsigne Line 2495  ui_create_cursor(unsigned int x, unsigne
2495          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2496          xfree(mask);          xfree(mask);
2497          xfree(cursor);          xfree(cursor);
2498          return (HCURSOR) xcursor;          return (RD_HCURSOR) xcursor;
2499  }  }
2500    
2501  void  void
2502  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(RD_HCURSOR cursor)
2503  {  {
2504          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2505          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2506            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2507  }  }
2508    
2509  void  void
2510  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(RD_HCURSOR cursor)
2511  {  {
2512          XFreeCursor(g_display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2513  }  }
# Line 2057  ui_set_null_cursor(void) Line 2525  ui_set_null_cursor(void)
2525                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2526    
2527    
2528  HCOLOURMAP  RD_HCOLOURMAP
2529  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
2530  {  {
2531          COLOURENTRY *entry;          COLOURENTRY *entry;
# Line 2153  ui_create_colourmap(COLOURMAP * colours) Line 2621  ui_create_colourmap(COLOURMAP * colours)
2621                  XStoreColors(g_display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2622    
2623                  xfree(xcolours);                  xfree(xcolours);
2624                  return (HCOLOURMAP) map;                  return (RD_HCOLOURMAP) map;
2625          }          }
2626  }  }
2627    
2628  void  void
2629  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(RD_HCOLOURMAP map)
2630  {  {
2631          if (!g_owncolmap)          if (!g_owncolmap)
2632                  xfree(map);                  xfree(map);
# Line 2167  ui_destroy_colourmap(HCOLOURMAP map) Line 2635  ui_destroy_colourmap(HCOLOURMAP map)
2635  }  }
2636    
2637  void  void
2638  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(RD_HCOLOURMAP map)
2639  {  {
2640          if (!g_owncolmap)          if (!g_owncolmap)
2641          {          {
# Line 2177  ui_set_colourmap(HCOLOURMAP map) Line 2645  ui_set_colourmap(HCOLOURMAP map)
2645                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2646          }          }
2647          else          else
2648            {
2649                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2650                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2651            }
2652  }  }
2653    
2654  void  void
2655  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2656  {  {
2657          XRectangle rect;          g_clip_rectangle.x = x;
2658            g_clip_rectangle.y = y;
2659          rect.x = x;          g_clip_rectangle.width = cx;
2660          rect.y = y;          g_clip_rectangle.height = cy;
2661          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);  
2662  }  }
2663    
2664  void  void
2665  ui_reset_clip(void)  ui_reset_clip(void)
2666  {  {
2667          XRectangle rect;          g_clip_rectangle.x = 0;
2668            g_clip_rectangle.y = 0;
2669          rect.x = 0;          g_clip_rectangle.width = g_width;
2670          rect.y = 0;          g_clip_rectangle.height = g_height;
2671          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);  
2672  }  }
2673    
2674  void  void
# Line 2256  ui_patblt(uint8 opcode, Line 2723  ui_patblt(uint8 opcode,
2723                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2724                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2725                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2726                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2727                          break;                          break;
2728    
2729                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2271  ui_patblt(uint8 opcode, Line 2738  ui_patblt(uint8 opcode,
2738                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2739                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2740                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2741                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2742                          break;                          break;
2743    
2744                  default:                  default:
# Line 2282  ui_patblt(uint8 opcode, Line 2749  ui_patblt(uint8 opcode,
2749    
2750          if (g_ownbackstore)          if (g_ownbackstore)
2751                  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);
2752            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2753                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2754                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2755  }  }
2756    
2757  void  void
# Line 2292  ui_screenblt(uint8 opcode, Line 2762  ui_screenblt(uint8 opcode,
2762          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2763          if (g_ownbackstore)          if (g_ownbackstore)
2764          {          {
2765                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2766                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2767                          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);  
                 }  
2768          }          }
2769          else          else
2770          {          {
2771                  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);
2772          }          }
2773    
2774            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2775                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2776                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2777    
2778          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2779  }  }
2780    
2781  void  void
2782  ui_memblt(uint8 opcode,  ui_memblt(uint8 opcode,
2783            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2784            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ RD_HBITMAP src, int srcx, int srcy)
2785  {  {
2786          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2787          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);
2788            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2789                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2790                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2791          if (g_ownbackstore)          if (g_ownbackstore)
2792                  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);
2793          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2327  ui_memblt(uint8 opcode, Line 2796  ui_memblt(uint8 opcode,
2796  void  void
2797  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2798            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2799            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ RD_HBITMAP src, int srcx, int srcy,
2800            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2801  {  {
2802          /* 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 2834  ui_line(uint8 opcode,
2834          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2835          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2836          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2837            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2838                                                startx - sw->xoffset, starty - sw->yoffset,
2839                                                endx - sw->xoffset, endy - sw->yoffset));
2840          if (g_ownbackstore)          if (g_ownbackstore)
2841                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2842          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2382  ui_rect( Line 2854  ui_rect(
2854  void  void
2855  ui_polygon(uint8 opcode,  ui_polygon(uint8 opcode,
2856             /* mode */ uint8 fillmode,             /* mode */ uint8 fillmode,
2857             /* dest */ POINT * point, int npoints,             /* dest */ RD_POINT * point, int npoints,
2858             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2859  {  {
2860          uint8 style, i, ipattern[8];          uint8 style, i, ipattern[8];
# Line 2425  ui_polygon(uint8 opcode, Line 2897  ui_polygon(uint8 opcode,
2897                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
2898                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2899                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2900                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2901                          break;                          break;
2902    
2903                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2440  ui_polygon(uint8 opcode, Line 2912  ui_polygon(uint8 opcode,
2912                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
2913                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2914                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2915                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2916                          break;                          break;
2917    
2918                  default:                  default:
# Line 2452  ui_polygon(uint8 opcode, Line 2924  ui_polygon(uint8 opcode,
2924    
2925  void  void
2926  ui_polyline(uint8 opcode,  ui_polyline(uint8 opcode,
2927              /* dest */ POINT * points, int npoints,              /* dest */ RD_POINT * points, int npoints,
2928              /* pen */ PEN * pen)              /* pen */ PEN * pen)
2929  {  {
2930          /* TODO: set join style */          /* TODO: set join style */
# Line 2462  ui_polyline(uint8 opcode, Line 2934  ui_polyline(uint8 opcode,
2934          if (g_ownbackstore)          if (g_ownbackstore)
2935                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2936                             CoordModePrevious);                             CoordModePrevious);
2937    
2938            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2939                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2940    
2941          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2942  }  }
2943    
# Line 2499  ui_ellipse(uint8 opcode, Line 2975  ui_ellipse(uint8 opcode,
2975                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2976                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2977                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2978                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2979                          break;                          break;
2980    
2981                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2514  ui_ellipse(uint8 opcode, Line 2990  ui_ellipse(uint8 opcode,
2990                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2991                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2992                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2993                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
2994                          break;                          break;
2995    
2996                  default:                  default:
# Line 2528  ui_ellipse(uint8 opcode, Line 3004  ui_ellipse(uint8 opcode,
3004  void  void
3005  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
3006                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
3007                /* src */ HGLYPH glyph, int srcx, int srcy,                /* src */ RD_HGLYPH glyph, int srcx, int srcy,
3008                int bgcolour, int fgcolour)                int bgcolour, int fgcolour)
3009  {  {
3010          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
# Line 2682  ui_draw_text(uint8 font, uint8 flags, ui Line 3158  ui_draw_text(uint8 font, uint8 flags, ui
3158          if (g_ownbackstore)          if (g_ownbackstore)
3159          {          {
3160                  if (boxcx > 1)                  if (boxcx > 1)
3161                    {
3162                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3163                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3164                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3165                                                    (g_display, g_backstore, sw->wnd, g_gc,
3166                                                     boxx, boxy,
3167                                                     boxcx, boxcy,
3168                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3169                    }
3170                  else                  else
3171                    {
3172                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3173                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3174                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3175                                                    (g_display, g_backstore, sw->wnd, g_gc,
3176                                                     clipx, clipy,
3177                                                     clipcx, clipcy, clipx - sw->xoffset,
3178                                                     clipy - sw->yoffset));
3179                    }
3180          }          }
3181  }  }
3182    
# Line 2699  ui_desktop_save(uint32 offset, int x, in Line 3189  ui_desktop_save(uint32 offset, int x, in
3189          if (g_ownbackstore)          if (g_ownbackstore)
3190          {          {
3191                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3192                    exit_if_null(image);
3193          }          }
3194          else          else
3195          {          {
3196                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3197                  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);
3198                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3199                    exit_if_null(image);
3200                  XFreePixmap(g_display, pix);                  XFreePixmap(g_display, pix);
3201          }          }
3202    
# Line 2726  ui_desktop_restore(uint32 offset, int x, Line 3218  ui_desktop_restore(uint32 offset, int x,
3218                  return;                  return;
3219    
3220          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3221                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3222    
3223          if (g_ownbackstore)          if (g_ownbackstore)
3224          {          {
3225                  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);
3226                  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);
3227                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3228                                            (g_display, g_backstore, sw->wnd, g_gc,
3229                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3230          }          }
3231          else          else
3232          {          {
3233                  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);
3234                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3235                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3236                                             x - sw->xoffset, y - sw->yoffset));
3237          }          }
3238    
3239          XFree(image);          XFree(image);
# Line 2751  void Line 3249  void
3249  ui_end_update(void)  ui_end_update(void)
3250  {  {
3251  }  }
3252    
3253    
3254    void
3255    ui_seamless_begin(RD_BOOL hidden)
3256    {
3257            if (!g_seamless_rdp)
3258                    return;
3259    
3260            if (g_seamless_started)
3261                    return;
3262    
3263            g_seamless_started = True;
3264            g_seamless_hidden = hidden;
3265    
3266            if (!hidden)
3267                    ui_seamless_toggle();
3268    }
3269    
3270    
3271    void
3272    ui_seamless_hide_desktop()
3273    {
3274            if (!g_seamless_rdp)
3275                    return;
3276    
3277            if (!g_seamless_started)
3278                    return;
3279    
3280            if (g_seamless_active)
3281                    ui_seamless_toggle();
3282    
3283            g_seamless_hidden = True;
3284    }
3285    
3286    
3287    void
3288    ui_seamless_unhide_desktop()
3289    {
3290            if (!g_seamless_rdp)
3291                    return;
3292    
3293            if (!g_seamless_started)
3294                    return;
3295    
3296            g_seamless_hidden = False;
3297    
3298            ui_seamless_toggle();
3299    }
3300    
3301    
3302    void
3303    ui_seamless_toggle()
3304    {
3305            if (!g_seamless_rdp)
3306                    return;
3307    
3308            if (!g_seamless_started)
3309                    return;
3310    
3311            if (g_seamless_hidden)
3312                    return;
3313    
3314            if (g_seamless_active)
3315            {
3316                    /* Deactivate */
3317                    while (g_seamless_windows)
3318                    {
3319                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3320                            sw_remove_window(g_seamless_windows);
3321                    }
3322                    XMapWindow(g_display, g_wnd);
3323            }
3324            else
3325            {
3326                    /* Activate */
3327                    XUnmapWindow(g_display, g_wnd);
3328                    seamless_send_sync();
3329            }
3330    
3331            g_seamless_active = !g_seamless_active;
3332    }
3333    
3334    
3335    void
3336    ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3337                              unsigned long flags)
3338    {
3339            Window wnd;
3340            XSetWindowAttributes attribs;
3341            XClassHint *classhints;
3342            XSizeHints *sizehints;
3343            XWMHints *wmhints;
3344            long input_mask;
3345            seamless_window *sw, *sw_parent;
3346    
3347            if (!g_seamless_active)
3348                    return;
3349    
3350            /* Ignore CREATEs for existing windows */
3351            sw = sw_get_window_by_id(id);
3352            if (sw)
3353                    return;
3354    
3355            get_window_attribs(&attribs);
3356            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3357                                InputOutput, g_visual,
3358                                CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3359    
3360            XStoreName(g_display, wnd, "SeamlessRDP");
3361            ewmh_set_wm_name(wnd, "SeamlessRDP");
3362    
3363            mwm_hide_decorations(wnd);
3364    
3365            classhints = XAllocClassHint();
3366            if (classhints != NULL)
3367            {
3368                    classhints->res_name = "rdesktop";
3369                    classhints->res_class = "SeamlessRDP";
3370                    XSetClassHint(g_display, wnd, classhints);
3371                    XFree(classhints);
3372            }
3373    
3374            /* WM_NORMAL_HINTS */
3375            sizehints = XAllocSizeHints();
3376            if (sizehints != NULL)
3377            {
3378                    sizehints->flags = USPosition;
3379                    XSetWMNormalHints(g_display, wnd, sizehints);
3380                    XFree(sizehints);
3381            }
3382    
3383            /* Parent-less transient windows */
3384            if (parent == 0xFFFFFFFF)
3385            {
3386                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3387                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3388                       using some other hints. */
3389                    ewmh_set_window_popup(wnd);
3390            }
3391            /* Normal transient windows */
3392            else if (parent != 0x00000000)
3393            {
3394                    sw_parent = sw_get_window_by_id(parent);
3395                    if (sw_parent)
3396                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3397                    else
3398                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3399            }
3400    
3401            if (flags & SEAMLESSRDP_CREATE_MODAL)
3402            {
3403                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3404                       somewhat at least */
3405                    if (parent == 0x00000000)
3406                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3407                    ewmh_set_window_modal(wnd);
3408            }
3409    
3410            /* FIXME: Support for Input Context:s */
3411    
3412            get_input_mask(&input_mask);
3413            input_mask |= PropertyChangeMask;
3414    
3415            XSelectInput(g_display, wnd, input_mask);
3416    
3417            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3418               seamless window, we could try to close the window on the
3419               serverside, instead of terminating rdesktop */
3420            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3421    
3422            sw = xmalloc(sizeof(seamless_window));
3423            sw->wnd = wnd;
3424            sw->id = id;
3425            sw->behind = 0;
3426            sw->group = sw_find_group(group, False);
3427            sw->group->refcnt++;
3428            sw->xoffset = 0;
3429            sw->yoffset = 0;
3430            sw->width = 0;
3431            sw->height = 0;
3432            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3433            sw->desktop = 0;
3434            sw->position_timer = xmalloc(sizeof(struct timeval));
3435            timerclear(sw->position_timer);
3436    
3437            sw->outstanding_position = False;
3438            sw->outpos_serial = 0;
3439            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3440            sw->outpos_width = sw->outpos_height = 0;
3441    
3442            sw->next = g_seamless_windows;
3443            g_seamless_windows = sw;
3444    
3445            /* WM_HINTS */
3446            wmhints = XAllocWMHints();
3447            if (wmhints)
3448            {
3449                    wmhints->flags = WindowGroupHint;
3450                    wmhints->window_group = sw->group->wnd;
3451                    XSetWMHints(g_display, sw->wnd, wmhints);
3452                    XFree(wmhints);
3453            }
3454    }
3455    
3456    
3457    void
3458    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3459    {
3460            seamless_window *sw;
3461    
3462            if (!g_seamless_active)
3463                    return;
3464    
3465            sw = sw_get_window_by_id(id);
3466            if (!sw)
3467            {
3468                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3469                    return;
3470            }
3471    
3472            XDestroyWindow(g_display, sw->wnd);
3473            sw_remove_window(sw);
3474    }
3475    
3476    
3477    void
3478    ui_seamless_destroy_group(unsigned long id, unsigned long flags)
3479    {
3480            seamless_window *sw, *sw_next;
3481    
3482            if (!g_seamless_active)
3483                    return;
3484    
3485            for (sw = g_seamless_windows; sw; sw = sw_next)
3486            {
3487                    sw_next = sw->next;
3488    
3489                    if (sw->group->id == id)
3490                    {
3491                            XDestroyWindow(g_display, sw->wnd);
3492                            sw_remove_window(sw);
3493                    }
3494            }
3495    }
3496    
3497    
3498    void
3499    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3500    {
3501            seamless_window *sw;
3502    
3503            if (!g_seamless_active)
3504                    return;
3505    
3506            sw = sw_get_window_by_id(id);
3507            if (!sw)
3508            {
3509                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3510                    return;
3511            }
3512    
3513            /* We ignore server updates until it has handled our request. */
3514            if (sw->outstanding_position)
3515                    return;
3516    
3517            if (!width || !height)
3518                    /* X11 windows must be at least 1x1 */
3519                    return;
3520    
3521            sw->xoffset = x;
3522            sw->yoffset = y;
3523            sw->width = width;
3524            sw->height = height;
3525    
3526            /* If we move the window in a maximized state, then KDE won't
3527               accept restoration */
3528            switch (sw->state)
3529            {
3530                    case SEAMLESSRDP_MINIMIZED:
3531                    case SEAMLESSRDP_MAXIMIZED:
3532                            return;
3533            }
3534    
3535            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3536            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3537    }
3538    
3539    
3540    void
3541    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3542    {
3543            seamless_window *sw;
3544    
3545            if (!g_seamless_active)
3546                    return;
3547    
3548            sw = sw_get_window_by_id(id);
3549            if (!sw)
3550            {
3551                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3552                    return;
3553            }
3554    
3555            if (behind)
3556            {
3557                    seamless_window *sw_behind;
3558                    Window wnds[2];
3559    
3560                    sw_behind = sw_get_window_by_id(behind);
3561                    if (!sw_behind)
3562                    {
3563                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3564                                    behind);
3565                            return;
3566                    }
3567    
3568                    wnds[1] = sw_behind->wnd;
3569                    wnds[0] = sw->wnd;
3570    
3571                    XRestackWindows(g_display, wnds, 2);
3572            }
3573            else
3574            {
3575                    XRaiseWindow(g_display, sw->wnd);
3576            }
3577    
3578            sw_restack_window(sw, behind);
3579    }
3580    
3581    
3582    void
3583    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3584    {
3585            seamless_window *sw;
3586    
3587            if (!g_seamless_active)
3588                    return;
3589    
3590            sw = sw_get_window_by_id(id);
3591            if (!sw)
3592            {
3593                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3594                    return;
3595            }
3596    
3597            /* FIXME: Might want to convert the name for non-EWMH WMs */
3598            XStoreName(g_display, sw->wnd, title);
3599            ewmh_set_wm_name(sw->wnd, title);
3600    }
3601    
3602    
3603    void
3604    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3605    {
3606            seamless_window *sw;
3607    
3608            if (!g_seamless_active)
3609                    return;
3610    
3611            sw = sw_get_window_by_id(id);
3612            if (!sw)
3613            {
3614                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3615                    return;
3616            }
3617    
3618            switch (state)
3619            {
3620                    case SEAMLESSRDP_NORMAL:
3621                    case SEAMLESSRDP_MAXIMIZED:
3622                            ewmh_change_state(sw->wnd, state);
3623                            XMapWindow(g_display, sw->wnd);
3624                            break;
3625                    case SEAMLESSRDP_MINIMIZED:
3626                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3627                               the Window Manager should probably just ignore the request, since
3628                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3629                               such as minimization, rather than an independent state." Besides,
3630                               XIconifyWindow is easier. */
3631                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3632                            {
3633                                    XWMHints *hints;
3634                                    hints = XGetWMHints(g_display, sw->wnd);
3635                                    if (hints)
3636                                    {
3637                                            hints->flags |= StateHint;
3638                                            hints->initial_state = IconicState;
3639                                            XSetWMHints(g_display, sw->wnd, hints);
3640                                            XFree(hints);
3641                                    }
3642                                    XMapWindow(g_display, sw->wnd);
3643                            }
3644                            else
3645                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3646                            break;
3647                    default:
3648                            warning("SeamlessRDP: Invalid state %d\n", state);
3649                            break;
3650            }
3651    
3652            sw->state = state;
3653    }
3654    
3655    
3656    void
3657    ui_seamless_syncbegin(unsigned long flags)
3658    {
3659            if (!g_seamless_active)
3660                    return;
3661    
3662            /* Destroy all seamless windows */
3663            while (g_seamless_windows)
3664            {
3665                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3666                    sw_remove_window(g_seamless_windows);
3667            }
3668    }
3669    
3670    
3671    void
3672    ui_seamless_ack(unsigned int serial)
3673    {
3674            seamless_window *sw;
3675            for (sw = g_seamless_windows; sw; sw = sw->next)
3676            {
3677                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3678                    {
3679                            sw->xoffset = sw->outpos_xoffset;
3680                            sw->yoffset = sw->outpos_yoffset;
3681                            sw->width = sw->outpos_width;
3682                            sw->height = sw->outpos_height;
3683                            sw->outstanding_position = False;
3684    
3685                            /* Do a complete redraw of the window as part of the
3686                               completion of the move. This is to remove any
3687                               artifacts caused by our lack of synchronization. */
3688                            XCopyArea(g_display, g_backstore,
3689                                      sw->wnd, g_gc,
3690                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3691    
3692                            break;
3693                    }
3694            }
3695    }

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

  ViewVC Help
Powered by ViewVC 1.1.26