/[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 1346 by ossman_, Thu Dec 7 15:23:45 2006 UTC
# Line 28  Line 28 
28  #include "rdesktop.h"  #include "rdesktop.h"
29  #include "xproto.h"  #include "xproto.h"
30    
31    /* We can't include Xproto.h because of conflicting defines for BOOL */
32    #define X_ConfigureWindow              12
33    
34  extern int g_width;  extern int g_width;
35  extern int g_height;  extern int g_height;
36  extern int g_xpos;  extern int g_xpos;
# Line 48  Time g_last_gesturetime; Line 51  Time g_last_gesturetime;
51  static int g_x_socket;  static int g_x_socket;
52  static Screen *g_screen;  static Screen *g_screen;
53  Window g_wnd;  Window g_wnd;
54    
55    /* SeamlessRDP support */
56    typedef struct _seamless_group
57    {
58            Window wnd;
59            unsigned long id;
60            unsigned int refcnt;
61    } seamless_group;
62    typedef struct _seamless_window
63    {
64            Window wnd;
65            unsigned long id;
66            unsigned long behind;
67            seamless_group *group;
68            int xoffset, yoffset;
69            int width, height;
70            int state;              /* normal/minimized/maximized. */
71            unsigned int desktop;
72            struct timeval *position_timer;
73    
74            BOOL outstanding_position;
75            unsigned int outpos_serial;
76            int outpos_xoffset, outpos_yoffset;
77            int outpos_width, outpos_height;
78    
79            struct _seamless_window *next;
80    } seamless_window;
81    static seamless_window *g_seamless_windows = NULL;
82    static unsigned long g_seamless_focused = 0;
83    static BOOL g_seamless_started = False; /* Server end is up and running */
84    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
85    static BOOL g_seamless_hidden = False;  /* Desktop is hidden on server */
86    extern BOOL g_seamless_rdp;
87    
88  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
89  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
90  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
91  static GC g_gc = NULL;  static GC g_gc = NULL;
92  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
93  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
94    static XRectangle g_clip_rectangle;
95  static Visual *g_visual;  static Visual *g_visual;
96  /* 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).
97     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 69  static XModifierKeymap *g_mod_map; Line 107  static XModifierKeymap *g_mod_map;
107  static Cursor g_current_cursor;  static Cursor g_current_cursor;
108  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
109  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
110    extern Atom g_net_wm_state_atom;
111    extern Atom g_net_wm_desktop_atom;
112  static BOOL g_focused;  static BOOL g_focused;
113  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
114  /* Indicates that:  /* Indicates that:
# Line 107  static int g_move_y_offset = 0; Line 147  static int g_move_y_offset = 0;
147  static BOOL g_using_full_workarea = False;  static BOOL g_using_full_workarea = False;
148    
149  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
 extern int g_dsp_fd;  
 extern BOOL g_dsp_busy;  
150  extern BOOL g_rdpsnd;  extern BOOL g_rdpsnd;
151  #endif  #endif
152    
# Line 133  typedef struct Line 171  typedef struct
171  }  }
172  PixelColour;  PixelColour;
173    
174    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
175            do { \
176                    seamless_window *sw; \
177                    XRectangle rect; \
178                    if (!g_seamless_windows) break; \
179                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
180                        rect.x = g_clip_rectangle.x - sw->xoffset; \
181                        rect.y = g_clip_rectangle.y - sw->yoffset; \
182                        rect.width = g_clip_rectangle.width; \
183                        rect.height = g_clip_rectangle.height; \
184                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
185                        func args; \
186                    } \
187                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
188            } while (0)
189    
190    static void
191    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
192    {
193            points[0].x -= xoffset;
194            points[0].y -= yoffset;
195            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
196            points[0].x += xoffset;
197            points[0].y += yoffset;
198    }
199    
200    static void
201    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
202    {
203            points[0].x -= xoffset;
204            points[0].y -= yoffset;
205            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
206            points[0].x += xoffset;
207            points[0].y += yoffset;
208    }
209    
210  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
211  { \  { \
212          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
213            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
214          if (g_ownbackstore) \          if (g_ownbackstore) \
215                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
216  }  }
# Line 151  PixelColour; Line 225  PixelColour;
225          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
226          if (g_ownbackstore) \          if (g_ownbackstore) \
227                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
228            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
229  }  }
230    
231  #define DRAW_ELLIPSE(x,y,cx,cy,m)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 159  PixelColour; Line 234  PixelColour;
234          { \          { \
235                  case 0: /* Outline */ \                  case 0: /* Outline */ \
236                          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); \
237                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
238                          if (g_ownbackstore) \                          if (g_ownbackstore) \
239                                  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); \
240                          break; \                          break; \
241                  case 1: /* Filled */ \                  case 1: /* Filled */ \
242                          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); \
243                            ON_ALL_SEAMLESS_WINDOWS(XFillArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
244                          if (g_ownbackstore) \                          if (g_ownbackstore) \
245                                  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); \
246                          break; \                          break; \
# Line 201  static int rop2_map[] = { Line 278  static int rop2_map[] = {
278  #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]); }
279  #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); }
280    
281    static seamless_window *
282    sw_get_window_by_id(unsigned long id)
283    {
284            seamless_window *sw;
285            for (sw = g_seamless_windows; sw; sw = sw->next)
286            {
287                    if (sw->id == id)
288                            return sw;
289            }
290            return NULL;
291    }
292    
293    
294    static seamless_window *
295    sw_get_window_by_wnd(Window wnd)
296    {
297            seamless_window *sw;
298            for (sw = g_seamless_windows; sw; sw = sw->next)
299            {
300                    if (sw->wnd == wnd)
301                            return sw;
302            }
303            return NULL;
304    }
305    
306    
307    static void
308    sw_remove_window(seamless_window * win)
309    {
310            seamless_window *sw, **prevnext = &g_seamless_windows;
311            for (sw = g_seamless_windows; sw; sw = sw->next)
312            {
313                    if (sw == win)
314                    {
315                            *prevnext = sw->next;
316                            sw->group->refcnt--;
317                            if (sw->group->refcnt == 0)
318                            {
319                                    XDestroyWindow(g_display, sw->group->wnd);
320                                    xfree(sw->group);
321                            }
322                            xfree(sw->position_timer);
323                            xfree(sw);
324                            return;
325                    }
326                    prevnext = &sw->next;
327            }
328            return;
329    }
330    
331    
332    /* Move all windows except wnd to new desktop */
333    static void
334    sw_all_to_desktop(Window wnd, unsigned int desktop)
335    {
336            seamless_window *sw;
337            for (sw = g_seamless_windows; sw; sw = sw->next)
338            {
339                    if (sw->wnd == wnd)
340                            continue;
341                    if (sw->desktop != desktop)
342                    {
343                            ewmh_move_to_desktop(sw->wnd, desktop);
344                            sw->desktop = desktop;
345                    }
346            }
347    }
348    
349    
350    /* Send our position */
351    static void
352    sw_update_position(seamless_window * sw)
353    {
354            XWindowAttributes wa;
355            int x, y;
356            Window child_return;
357            unsigned int serial;
358    
359            XGetWindowAttributes(g_display, sw->wnd, &wa);
360            XTranslateCoordinates(g_display, sw->wnd, wa.root,
361                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
362    
363            serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
364    
365            sw->outstanding_position = True;
366            sw->outpos_serial = serial;
367    
368            sw->outpos_xoffset = x;
369            sw->outpos_yoffset = y;
370            sw->outpos_width = wa.width;
371            sw->outpos_height = wa.height;
372    }
373    
374    
375    /* Check if it's time to send our position */
376    static void
377    sw_check_timers()
378    {
379            seamless_window *sw;
380            struct timeval now;
381    
382            gettimeofday(&now, NULL);
383            for (sw = g_seamless_windows; sw; sw = sw->next)
384            {
385                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
386                    {
387                            timerclear(sw->position_timer);
388                            sw_update_position(sw);
389                    }
390            }
391    }
392    
393    
394    static void
395    sw_restack_window(seamless_window * sw, unsigned long behind)
396    {
397            seamless_window *sw_above;
398    
399            /* Remove window from stack */
400            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
401            {
402                    if (sw_above->behind == sw->id)
403                            break;
404            }
405    
406            if (sw_above)
407                    sw_above->behind = sw->behind;
408    
409            /* And then add it at the new position */
410            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
411            {
412                    if (sw_above->behind == behind)
413                            break;
414            }
415    
416            if (sw_above)
417                    sw_above->behind = sw->id;
418    
419            sw->behind = behind;
420    }
421    
422    
423    static void
424    sw_handle_restack(seamless_window * sw)
425    {
426            Status status;
427            Window root, parent, *children;
428            unsigned int nchildren, i;
429            seamless_window *sw_below;
430    
431            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
432                                &root, &parent, &children, &nchildren);
433            if (!status || !nchildren)
434                    return;
435    
436            sw_below = NULL;
437    
438            i = 0;
439            while (children[i] != sw->wnd)
440            {
441                    i++;
442                    if (i >= nchildren)
443                            goto end;
444            }
445    
446            for (i++; i < nchildren; i++)
447            {
448                    sw_below = sw_get_window_by_wnd(children[i]);
449                    if (sw_below)
450                            break;
451            }
452    
453            if (!sw_below && !sw->behind)
454                    goto end;
455            if (sw_below && (sw_below->id == sw->behind))
456                    goto end;
457    
458            if (sw_below)
459            {
460                    seamless_send_zchange(sw->id, sw_below->id, 0);
461                    sw_restack_window(sw, sw_below->id);
462            }
463            else
464            {
465                    seamless_send_zchange(sw->id, 0, 0);
466                    sw_restack_window(sw, 0);
467            }
468    
469          end:
470            XFree(children);
471    }
472    
473    
474    static seamless_group *
475    sw_find_group(unsigned long id, BOOL dont_create)
476    {
477            seamless_window *sw;
478            seamless_group *sg;
479            XSetWindowAttributes attribs;
480    
481            for (sw = g_seamless_windows; sw; sw = sw->next)
482            {
483                    if (sw->group->id == id)
484                            return sw->group;
485            }
486    
487            if (dont_create)
488                    return NULL;
489    
490            sg = xmalloc(sizeof(seamless_group));
491    
492            sg->wnd =
493                    XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0,
494                                  CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
495    
496            sg->id = id;
497            sg->refcnt = 0;
498    
499            return sg;
500    }
501    
502    
503  static void  static void
504  mwm_hide_decorations(void)  mwm_hide_decorations(Window wnd)
505  {  {
506          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
507          Atom hintsatom;          Atom hintsatom;
# Line 219  mwm_hide_decorations(void) Line 518  mwm_hide_decorations(void)
518                  return;                  return;
519          }          }
520    
521          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
522                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
523    
524  }  }
525    
526  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 1011  calculate_mask_weight(uint32 mask) Line 1311  calculate_mask_weight(uint32 mask)
1311  }  }
1312    
1313  static BOOL  static BOOL
1314  select_visual()  select_visual(int screen_num)
1315  {  {
1316          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1317          int pixmap_formats_count, visuals_count;          int pixmap_formats_count, visuals_count;
# Line 1022  select_visual() Line 1322  select_visual()
1322    
1323          red_weight = blue_weight = green_weight = 0;          red_weight = blue_weight = green_weight = 0;
1324    
1325            if (g_server_depth == -1)
1326            {
1327                    g_server_depth = DisplayPlanes(g_display, DefaultScreen(g_display));
1328            }
1329    
1330          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1331          if (pfm == NULL)          if (pfm == NULL)
1332          {          {
# Line 1032  select_visual() Line 1337  select_visual()
1337    
1338          /* Search for best TrueColor visual */          /* Search for best TrueColor visual */
1339          template.class = TrueColor;          template.class = TrueColor;
1340          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);          template.screen = screen_num;
1341            vmatches =
1342                    XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template,
1343                                   &visuals_count);
1344          g_visual = NULL;          g_visual = NULL;
1345          g_no_translate_image = False;          g_no_translate_image = False;
1346          g_compatible_arch = False;          g_compatible_arch = False;
# Line 1041  select_visual() Line 1349  select_visual()
1349                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
1350                  {                  {
1351                          XVisualInfo *visual_info = &vmatches[i];                          XVisualInfo *visual_info = &vmatches[i];
1352                            BOOL can_translate_to_bpp = False;
1353                            int j;
1354    
1355                          /* Try to find a no-translation visual that'll                          /* Try to find a no-translation visual that'll
1356                             allow us to use RDP bitmaps directly as ZPixmaps. */                             allow us to use RDP bitmaps directly as ZPixmaps. */
# Line 1084  select_visual() Line 1394  select_visual()
1394    
1395                          /* Only care for visuals, for whose BPPs (not depths!)                          /* Only care for visuals, for whose BPPs (not depths!)
1396                             we have a translateXtoY function. */                             we have a translateXtoY function. */
                         BOOL can_translate_to_bpp = False;  
                         int j;  
1397                          for (j = 0; j < pixmap_formats_count; ++j)                          for (j = 0; j < pixmap_formats_count; ++j)
1398                          {                          {
1399                                  if (pfm[j].depth == visual_info->depth)                                  if (pfm[j].depth == visual_info->depth)
# Line 1197  select_visual() Line 1505  select_visual()
1505          return True;          return True;
1506  }  }
1507    
1508    static XErrorHandler g_old_error_handler;
1509    
1510    static int
1511    error_handler(Display * dpy, XErrorEvent * eev)
1512    {
1513            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1514            {
1515                    fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1516                    fprintf(stderr,
1517                            "This is most likely caused by a broken window manager (commonly KWin).\n");
1518                    return 0;
1519            }
1520    
1521            return g_old_error_handler(dpy, eev);
1522    }
1523    
1524  BOOL  BOOL
1525  ui_init(void)  ui_init(void)
1526  {  {
# Line 1214  ui_init(void) Line 1538  ui_init(void)
1538                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1539          }          }
1540    
1541            g_old_error_handler = XSetErrorHandler(error_handler);
1542          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1543          screen_num = DefaultScreen(g_display);          screen_num = DefaultScreen(g_display);
1544          g_x_socket = ConnectionNumber(g_display);          g_x_socket = ConnectionNumber(g_display);
1545          g_screen = ScreenOfDisplay(g_display, screen_num);          g_screen = ScreenOfDisplay(g_display, screen_num);
1546          g_depth = DefaultDepthOfScreen(g_screen);          g_depth = DefaultDepthOfScreen(g_screen);
1547    
1548          if (!select_visual())          if (!select_visual(screen_num))
1549                  return False;                  return False;
1550    
1551          if (g_no_translate_image)          if (g_no_translate_image)
# Line 1259  ui_init(void) Line 1584  ui_init(void)
1584          {          {
1585                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1586                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1587                    g_using_full_workarea = True;
1588          }          }
1589          else if (g_width < 0)          else if (g_width < 0)
1590          {          {
# Line 1272  ui_init(void) Line 1598  ui_init(void)
1598          {          {
1599                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1600                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
                 g_using_full_workarea = True;  
   
1601                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1602                  {                  {
1603                          g_width = cx;                          g_width = cx;
1604                          g_height = cy;                          g_height = cy;
1605                            g_using_full_workarea = True;
1606                  }                  }
1607                  else                  else
1608                  {                  {
1609                          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");
1610                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1611                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1612                  }                  }
1613          }          }
1614    
# Line 1298  ui_init(void) Line 1623  ui_init(void)
1623                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1624    
1625          xclip_init();          xclip_init();
1626            ewmh_init();
1627            if (g_seamless_rdp)
1628                    seamless_init();
1629    
1630          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));
1631    
# Line 1307  ui_init(void) Line 1635  ui_init(void)
1635  void  void
1636  ui_deinit(void)  ui_deinit(void)
1637  {  {
1638            while (g_seamless_windows)
1639            {
1640                    XDestroyWindow(g_display, g_seamless_windows->wnd);
1641                    sw_remove_window(g_seamless_windows);
1642            }
1643    
1644            xclip_deinit();
1645    
1646          if (g_IM != NULL)          if (g_IM != NULL)
1647                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1648    
# Line 1323  ui_deinit(void) Line 1659  ui_deinit(void)
1659          g_display = NULL;          g_display = NULL;
1660  }  }
1661    
1662    
1663    static void
1664    get_window_attribs(XSetWindowAttributes * attribs)
1665    {
1666            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1667            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1668            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1669            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1670            attribs->override_redirect = g_fullscreen;
1671            attribs->colormap = g_xcolmap;
1672    }
1673    
1674    static void
1675    get_input_mask(long *input_mask)
1676    {
1677            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1678                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1679    
1680            if (g_sendmotion)
1681                    *input_mask |= PointerMotionMask;
1682            if (g_ownbackstore)
1683                    *input_mask |= ExposureMask;
1684            if (g_fullscreen || g_grab_keyboard)
1685                    *input_mask |= EnterWindowMask;
1686            if (g_grab_keyboard)
1687                    *input_mask |= LeaveWindowMask;
1688    }
1689    
1690  BOOL  BOOL
1691  ui_create_window(void)  ui_create_window(void)
1692  {  {
# Line 1345  ui_create_window(void) Line 1709  ui_create_window(void)
1709          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1710                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1711    
1712          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;  
1713    
1714          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,
1715                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1357  ui_create_window(void) Line 1717  ui_create_window(void)
1717                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1718    
1719          if (g_gc == NULL)          if (g_gc == NULL)
1720            {
1721                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1722                    ui_reset_clip();
1723            }
1724    
1725          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1726                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 1374  ui_create_window(void) Line 1737  ui_create_window(void)
1737          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1738    
1739          if (g_hide_decorations)          if (g_hide_decorations)
1740                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1741    
1742          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1743          if (classhints != NULL)          if (classhints != NULL)
# Line 1401  ui_create_window(void) Line 1764  ui_create_window(void)
1764                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1765          }          }
1766    
1767          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;  
1768    
1769          if (g_IM != NULL)          if (g_IM != NULL)
1770          {          {
# Line 1496  xwin_toggle_fullscreen(void) Line 1849  xwin_toggle_fullscreen(void)
1849  {  {
1850          Pixmap contents = 0;          Pixmap contents = 0;
1851    
1852            if (g_seamless_active)
1853                    /* Turn off SeamlessRDP mode */
1854                    ui_seamless_toggle();
1855    
1856          if (!g_ownbackstore)          if (!g_ownbackstore)
1857          {          {
1858                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1584  handle_button_event(XEvent xevent, BOOL Line 1941  handle_button_event(XEvent xevent, BOOL
1941                  }                  }
1942          }          }
1943    
1944          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1945                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1946                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1947                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1948            }
1949            else
1950            {
1951                    /* SeamlessRDP */
1952                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1953                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1954            }
1955  }  }
1956    
1957    
1958  /* Process events in Xlib queue  /* Process events in Xlib queue
1959     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1960  static int  static int
# Line 1599  xwin_process_events(void) Line 1966  xwin_process_events(void)
1966          char str[256];          char str[256];
1967          Status status;          Status status;
1968          int events = 0;          int events = 0;
1969            seamless_window *sw;
1970    
1971          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1972          {          {
# Line 1613  xwin_process_events(void) Line 1981  xwin_process_events(void)
1981                  switch (xevent.type)                  switch (xevent.type)
1982                  {                  {
1983                          case VisibilityNotify:                          case VisibilityNotify:
1984                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1985                                            g_Unobscured =
1986                                                    xevent.xvisibility.state == VisibilityUnobscured;
1987    
1988                                  break;                                  break;
1989                          case ClientMessage:                          case ClientMessage:
1990                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1693  xwin_process_events(void) Line 2064  xwin_process_events(void)
2064                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
2065                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2066                                                         CurrentTime);                                                         CurrentTime);
2067                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
2068                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
2069                                    {
2070                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2071                                                           xevent.xmotion.x, xevent.xmotion.y);
2072                                    }
2073                                    else
2074                                    {
2075                                            /* SeamlessRDP */
2076                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2077                                                           xevent.xmotion.x_root,
2078                                                           xevent.xmotion.y_root);
2079                                    }
2080                                  break;                                  break;
2081    
2082                          case FocusIn:                          case FocusIn:
# Line 1705  xwin_process_events(void) Line 2087  xwin_process_events(void)
2087                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2088                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2089                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2090    
2091                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2092                                    if (!sw)
2093                                            break;
2094    
2095                                    if (sw->id != g_seamless_focused)
2096                                    {
2097                                            seamless_send_focus(sw->id, 0);
2098                                            g_seamless_focused = sw->id;
2099                                    }
2100                                  break;                                  break;
2101    
2102                          case FocusOut:                          case FocusOut:
# Line 1737  xwin_process_events(void) Line 2129  xwin_process_events(void)
2129                                  break;                                  break;
2130    
2131                          case Expose:                          case Expose:
2132                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2133                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2134                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2135                                            xevent.xexpose.height,                                                    g_gc,
2136                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2137                                                      xevent.xexpose.width, xevent.xexpose.height,
2138                                                      xevent.xexpose.x, xevent.xexpose.y);
2139                                    }
2140                                    else
2141                                    {
2142                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2143                                            if (!sw)
2144                                                    break;
2145                                            XCopyArea(g_display, g_backstore,
2146                                                      xevent.xexpose.window, g_gc,
2147                                                      xevent.xexpose.x + sw->xoffset,
2148                                                      xevent.xexpose.y + sw->yoffset,
2149                                                      xevent.xexpose.width,
2150                                                      xevent.xexpose.height, xevent.xexpose.x,
2151                                                      xevent.xexpose.y);
2152                                    }
2153    
2154                                  break;                                  break;
2155    
2156                          case MappingNotify:                          case MappingNotify:
# Line 1770  xwin_process_events(void) Line 2179  xwin_process_events(void)
2179                                  break;                                  break;
2180                          case PropertyNotify:                          case PropertyNotify:
2181                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2182                                    if (xevent.xproperty.window == g_wnd)
2183                                            break;
2184                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2185                                            break;
2186    
2187                                    /* seamless */
2188                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2189                                    if (!sw)
2190                                            break;
2191    
2192                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2193                                        && (xevent.xproperty.state == PropertyNewValue))
2194                                    {
2195                                            sw->state = ewmh_get_window_state(sw->wnd);
2196                                            seamless_send_state(sw->id, sw->state, 0);
2197                                    }
2198    
2199                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2200                                        && (xevent.xproperty.state == PropertyNewValue))
2201                                    {
2202                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2203                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2204                                    }
2205    
2206                                  break;                                  break;
2207                          case MapNotify:                          case MapNotify:
2208                                  rdp_send_client_window_status(1);                                  if (!g_seamless_active)
2209                                            rdp_send_client_window_status(1);
2210                                  break;                                  break;
2211                          case UnmapNotify:                          case UnmapNotify:
2212                                  rdp_send_client_window_status(0);                                  if (!g_seamless_active)
2213                                            rdp_send_client_window_status(0);
2214                                    break;
2215                            case ConfigureNotify:
2216                                    if (!g_seamless_active)
2217                                            break;
2218    
2219                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2220                                    if (!sw)
2221                                            break;
2222    
2223                                    gettimeofday(sw->position_timer, NULL);
2224                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2225                                        1000000)
2226                                    {
2227                                            sw->position_timer->tv_usec +=
2228                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2229                                            sw->position_timer->tv_sec += 1;
2230                                    }
2231                                    else
2232                                    {
2233                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2234                                    }
2235    
2236                                    sw_handle_restack(sw);
2237                                  break;                                  break;
2238                  }                  }
2239          }          }
# Line 1800  ui_select(int rdp_socket) Line 2258  ui_select(int rdp_socket)
2258                          /* User quit */                          /* User quit */
2259                          return 0;                          return 0;
2260    
2261                    if (g_seamless_active)
2262                            sw_check_timers();
2263    
2264                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2265                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2266                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
2267                  FD_SET(g_x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
2268    
 #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  
2269                  /* default timeout */                  /* default timeout */
2270                  tv.tv_sec = 60;                  tv.tv_sec = 60;
2271                  tv.tv_usec = 0;                  tv.tv_usec = 0;
2272    
2273    #ifdef WITH_RDPSND
2274                    rdpsnd_add_fds(&n, &rfds, &wfds, &tv);
2275    #endif
2276    
2277                  /* add redirection handles */                  /* add redirection handles */
2278                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2279                    seamless_select_timeout(&tv);
2280    
2281                  n++;                  n++;
2282    
# Line 1828  ui_select(int rdp_socket) Line 2286  ui_select(int rdp_socket)
2286                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2287    
2288                          case 0:                          case 0:
2289    #ifdef WITH_RDPSND
2290                                    rdpsnd_check_fds(&rfds, &wfds);
2291    #endif
2292    
2293                                  /* Abort serial read calls */                                  /* Abort serial read calls */
2294                                  if (s_timeout)                                  if (s_timeout)
2295                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
2296                                  continue;                                  continue;
2297                  }                  }
2298    
2299    #ifdef WITH_RDPSND
2300                    rdpsnd_check_fds(&rfds, &wfds);
2301    #endif
2302    
2303                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
2304    
2305                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2306                          return 1;                          return 1;
2307    
 #ifdef WITH_RDPSND  
                 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))  
                         wave_out_play();  
 #endif  
2308          }          }
2309  }  }
2310    
# Line 1912  ui_paint_bitmap(int x, int y, int cx, in Line 2374  ui_paint_bitmap(int x, int y, int cx, in
2374          {          {
2375                  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);
2376                  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);
2377                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2378                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2379                                             x - sw->xoffset, y - sw->yoffset));
2380          }          }
2381          else          else
2382          {          {
2383                  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);
2384                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2385                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2386                                             x - sw->xoffset, y - sw->yoffset));
2387          }          }
2388    
2389          XFree(image);          XFree(image);
# Line 2036  ui_set_cursor(HCURSOR cursor) Line 2504  ui_set_cursor(HCURSOR cursor)
2504  {  {
2505          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2506          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2507            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2508  }  }
2509    
2510  void  void
# Line 2177  ui_set_colourmap(HCOLOURMAP map) Line 2646  ui_set_colourmap(HCOLOURMAP map)
2646                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2647          }          }
2648          else          else
2649            {
2650                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2651                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2652            }
2653  }  }
2654    
2655  void  void
2656  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2657  {  {
2658          XRectangle rect;          g_clip_rectangle.x = x;
2659            g_clip_rectangle.y = y;
2660          rect.x = x;          g_clip_rectangle.width = cx;
2661          rect.y = y;          g_clip_rectangle.height = cy;
2662          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);  
2663  }  }
2664    
2665  void  void
2666  ui_reset_clip(void)  ui_reset_clip(void)
2667  {  {
2668          XRectangle rect;          g_clip_rectangle.x = 0;
2669            g_clip_rectangle.y = 0;
2670          rect.x = 0;          g_clip_rectangle.width = g_width;
2671          rect.y = 0;          g_clip_rectangle.height = g_height;
2672          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);  
2673  }  }
2674    
2675  void  void
# Line 2282  ui_patblt(uint8 opcode, Line 2750  ui_patblt(uint8 opcode,
2750    
2751          if (g_ownbackstore)          if (g_ownbackstore)
2752                  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);
2753            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2754                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2755                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2756  }  }
2757    
2758  void  void
# Line 2292  ui_screenblt(uint8 opcode, Line 2763  ui_screenblt(uint8 opcode,
2763          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2764          if (g_ownbackstore)          if (g_ownbackstore)
2765          {          {
2766                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2767                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2768                          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);  
                 }  
2769          }          }
2770          else          else
2771          {          {
2772                  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);
2773          }          }
2774    
2775            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2776                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2777                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2778    
2779          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2780  }  }
2781    
# Line 2319  ui_memblt(uint8 opcode, Line 2786  ui_memblt(uint8 opcode,
2786  {  {
2787          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2788          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);
2789            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2790                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2791                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2792          if (g_ownbackstore)          if (g_ownbackstore)
2793                  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);
2794          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2365  ui_line(uint8 opcode, Line 2835  ui_line(uint8 opcode,
2835          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2836          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2837          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2838            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2839                                                startx - sw->xoffset, starty - sw->yoffset,
2840                                                endx - sw->xoffset, endy - sw->yoffset));
2841          if (g_ownbackstore)          if (g_ownbackstore)
2842                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2843          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2462  ui_polyline(uint8 opcode, Line 2935  ui_polyline(uint8 opcode,
2935          if (g_ownbackstore)          if (g_ownbackstore)
2936                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2937                             CoordModePrevious);                             CoordModePrevious);
2938    
2939            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2940                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2941    
2942          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2943  }  }
2944    
# Line 2682  ui_draw_text(uint8 font, uint8 flags, ui Line 3159  ui_draw_text(uint8 font, uint8 flags, ui
3159          if (g_ownbackstore)          if (g_ownbackstore)
3160          {          {
3161                  if (boxcx > 1)                  if (boxcx > 1)
3162                    {
3163                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3164                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3165                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3166                                                    (g_display, g_backstore, sw->wnd, g_gc,
3167                                                     boxx, boxy,
3168                                                     boxcx, boxcy,
3169                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3170                    }
3171                  else                  else
3172                    {
3173                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3174                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3175                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3176                                                    (g_display, g_backstore, sw->wnd, g_gc,
3177                                                     clipx, clipy,
3178                                                     clipcx, clipcy, clipx - sw->xoffset,
3179                                                     clipy - sw->yoffset));
3180                    }
3181          }          }
3182  }  }
3183    
# Line 2699  ui_desktop_save(uint32 offset, int x, in Line 3190  ui_desktop_save(uint32 offset, int x, in
3190          if (g_ownbackstore)          if (g_ownbackstore)
3191          {          {
3192                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3193                    exit_if_null(image);
3194          }          }
3195          else          else
3196          {          {
3197                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3198                  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);
3199                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3200                    exit_if_null(image);
3201                  XFreePixmap(g_display, pix);                  XFreePixmap(g_display, pix);
3202          }          }
3203    
# Line 2732  ui_desktop_restore(uint32 offset, int x, Line 3225  ui_desktop_restore(uint32 offset, int x,
3225          {          {
3226                  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);
3227                  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);
3228                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3229                                            (g_display, g_backstore, sw->wnd, g_gc,
3230                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3231          }          }
3232          else          else
3233          {          {
3234                  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);
3235                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3236                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3237                                             x - sw->xoffset, y - sw->yoffset));
3238          }          }
3239    
3240          XFree(image);          XFree(image);
# Line 2751  void Line 3250  void
3250  ui_end_update(void)  ui_end_update(void)
3251  {  {
3252  }  }
3253    
3254    
3255    void
3256    ui_seamless_begin(BOOL hidden)
3257    {
3258            if (!g_seamless_rdp)
3259                    return;
3260    
3261            if (g_seamless_started)
3262                    return;
3263    
3264            g_seamless_started = True;
3265            g_seamless_hidden = hidden;
3266    
3267            if (!hidden)
3268                    ui_seamless_toggle();
3269    }
3270    
3271    
3272    void
3273    ui_seamless_hide_desktop()
3274    {
3275            if (!g_seamless_rdp)
3276                    return;
3277    
3278            if (!g_seamless_started)
3279                    return;
3280    
3281            if (g_seamless_active)
3282                    ui_seamless_toggle();
3283    
3284            g_seamless_hidden = True;
3285    }
3286    
3287    
3288    void
3289    ui_seamless_unhide_desktop()
3290    {
3291            if (!g_seamless_rdp)
3292                    return;
3293    
3294            if (!g_seamless_started)
3295                    return;
3296    
3297            g_seamless_hidden = False;
3298    
3299            ui_seamless_toggle();
3300    }
3301    
3302    
3303    void
3304    ui_seamless_toggle()
3305    {
3306            if (!g_seamless_rdp)
3307                    return;
3308    
3309            if (!g_seamless_started)
3310                    return;
3311    
3312            if (g_seamless_hidden)
3313                    return;
3314    
3315            if (g_seamless_active)
3316            {
3317                    /* Deactivate */
3318                    while (g_seamless_windows)
3319                    {
3320                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3321                            sw_remove_window(g_seamless_windows);
3322                    }
3323                    XMapWindow(g_display, g_wnd);
3324            }
3325            else
3326            {
3327                    /* Activate */
3328                    XUnmapWindow(g_display, g_wnd);
3329                    seamless_send_sync();
3330            }
3331    
3332            g_seamless_active = !g_seamless_active;
3333    }
3334    
3335    
3336    void
3337    ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3338                              unsigned long flags)
3339    {
3340            Window wnd;
3341            XSetWindowAttributes attribs;
3342            XClassHint *classhints;
3343            XSizeHints *sizehints;
3344            XWMHints *wmhints;
3345            long input_mask;
3346            seamless_window *sw, *sw_parent;
3347    
3348            if (!g_seamless_active)
3349                    return;
3350    
3351            /* Ignore CREATEs for existing windows */
3352            sw = sw_get_window_by_id(id);
3353            if (sw)
3354                    return;
3355    
3356            get_window_attribs(&attribs);
3357            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3358                                InputOutput, g_visual,
3359                                CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3360    
3361            XStoreName(g_display, wnd, "SeamlessRDP");
3362            ewmh_set_wm_name(wnd, "SeamlessRDP");
3363    
3364            mwm_hide_decorations(wnd);
3365    
3366            classhints = XAllocClassHint();
3367            if (classhints != NULL)
3368            {
3369                    classhints->res_name = "rdesktop";
3370                    classhints->res_class = "SeamlessRDP";
3371                    XSetClassHint(g_display, wnd, classhints);
3372                    XFree(classhints);
3373            }
3374    
3375            /* WM_NORMAL_HINTS */
3376            sizehints = XAllocSizeHints();
3377            if (sizehints != NULL)
3378            {
3379                    sizehints->flags = USPosition;
3380                    XSetWMNormalHints(g_display, wnd, sizehints);
3381                    XFree(sizehints);
3382            }
3383    
3384            /* Parent-less transient windows */
3385            if (parent == 0xFFFFFFFF)
3386            {
3387                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3388                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3389                       using some other hints. */
3390                    ewmh_set_window_popup(wnd);
3391            }
3392            /* Normal transient windows */
3393            else if (parent != 0x00000000)
3394            {
3395                    sw_parent = sw_get_window_by_id(parent);
3396                    if (sw_parent)
3397                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3398                    else
3399                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3400            }
3401    
3402            if (flags & SEAMLESSRDP_CREATE_MODAL)
3403            {
3404                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3405                       somewhat at least */
3406                    if (parent == 0x00000000)
3407                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3408                    ewmh_set_window_modal(wnd);
3409            }
3410    
3411            /* FIXME: Support for Input Context:s */
3412    
3413            get_input_mask(&input_mask);
3414            input_mask |= PropertyChangeMask;
3415    
3416            XSelectInput(g_display, wnd, input_mask);
3417    
3418            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3419               seamless window, we could try to close the window on the
3420               serverside, instead of terminating rdesktop */
3421            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3422    
3423            sw = xmalloc(sizeof(seamless_window));
3424            sw->wnd = wnd;
3425            sw->id = id;
3426            sw->behind = 0;
3427            sw->group = sw_find_group(group, False);
3428            sw->group->refcnt++;
3429            sw->xoffset = 0;
3430            sw->yoffset = 0;
3431            sw->width = 0;
3432            sw->height = 0;
3433            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3434            sw->desktop = 0;
3435            sw->position_timer = xmalloc(sizeof(struct timeval));
3436            timerclear(sw->position_timer);
3437    
3438            sw->outstanding_position = False;
3439            sw->outpos_serial = 0;
3440            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3441            sw->outpos_width = sw->outpos_height = 0;
3442    
3443            sw->next = g_seamless_windows;
3444            g_seamless_windows = sw;
3445    
3446            /* WM_HINTS */
3447            wmhints = XAllocWMHints();
3448            if (wmhints)
3449            {
3450                    wmhints->flags = WindowGroupHint;
3451                    wmhints->window_group = sw->group->wnd;
3452                    XSetWMHints(g_display, sw->wnd, wmhints);
3453                    XFree(wmhints);
3454            }
3455    }
3456    
3457    
3458    void
3459    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3460    {
3461            seamless_window *sw;
3462    
3463            if (!g_seamless_active)
3464                    return;
3465    
3466            sw = sw_get_window_by_id(id);
3467            if (!sw)
3468            {
3469                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3470                    return;
3471            }
3472    
3473            XDestroyWindow(g_display, sw->wnd);
3474            sw_remove_window(sw);
3475    }
3476    
3477    
3478    void
3479    ui_seamless_destroy_group(unsigned long id, unsigned long flags)
3480    {
3481            seamless_window *sw, *sw_next;
3482    
3483            if (!g_seamless_active)
3484                    return;
3485    
3486            for (sw = g_seamless_windows; sw; sw = sw_next)
3487            {
3488                    sw_next = sw->next;
3489    
3490                    if (sw->group->id == id)
3491                    {
3492                            XDestroyWindow(g_display, sw->wnd);
3493                            sw_remove_window(sw);
3494                    }
3495            }
3496    }
3497    
3498    
3499    void
3500    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3501    {
3502            seamless_window *sw;
3503    
3504            if (!g_seamless_active)
3505                    return;
3506    
3507            sw = sw_get_window_by_id(id);
3508            if (!sw)
3509            {
3510                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3511                    return;
3512            }
3513    
3514            /* We ignore server updates until it has handled our request. */
3515            if (sw->outstanding_position)
3516                    return;
3517    
3518            if (!width || !height)
3519                    /* X11 windows must be at least 1x1 */
3520                    return;
3521    
3522            sw->xoffset = x;
3523            sw->yoffset = y;
3524            sw->width = width;
3525            sw->height = height;
3526    
3527            /* If we move the window in a maximized state, then KDE won't
3528               accept restoration */
3529            switch (sw->state)
3530            {
3531                    case SEAMLESSRDP_MINIMIZED:
3532                    case SEAMLESSRDP_MAXIMIZED:
3533                            return;
3534            }
3535    
3536            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3537            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3538    }
3539    
3540    
3541    void
3542    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3543    {
3544            seamless_window *sw;
3545    
3546            if (!g_seamless_active)
3547                    return;
3548    
3549            sw = sw_get_window_by_id(id);
3550            if (!sw)
3551            {
3552                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3553                    return;
3554            }
3555    
3556            if (behind)
3557            {
3558                    seamless_window *sw_behind;
3559                    Window wnds[2];
3560    
3561                    sw_behind = sw_get_window_by_id(behind);
3562                    if (!sw_behind)
3563                    {
3564                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3565                                    behind);
3566                            return;
3567                    }
3568    
3569                    wnds[1] = sw_behind->wnd;
3570                    wnds[0] = sw->wnd;
3571    
3572                    XRestackWindows(g_display, wnds, 2);
3573            }
3574            else
3575            {
3576                    XRaiseWindow(g_display, sw->wnd);
3577            }
3578    
3579            sw_restack_window(sw, behind);
3580    }
3581    
3582    
3583    void
3584    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3585    {
3586            seamless_window *sw;
3587    
3588            if (!g_seamless_active)
3589                    return;
3590    
3591            sw = sw_get_window_by_id(id);
3592            if (!sw)
3593            {
3594                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3595                    return;
3596            }
3597    
3598            /* FIXME: Might want to convert the name for non-EWMH WMs */
3599            XStoreName(g_display, sw->wnd, title);
3600            ewmh_set_wm_name(sw->wnd, title);
3601    }
3602    
3603    
3604    void
3605    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3606    {
3607            seamless_window *sw;
3608    
3609            if (!g_seamless_active)
3610                    return;
3611    
3612            sw = sw_get_window_by_id(id);
3613            if (!sw)
3614            {
3615                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3616                    return;
3617            }
3618    
3619            switch (state)
3620            {
3621                    case SEAMLESSRDP_NORMAL:
3622                    case SEAMLESSRDP_MAXIMIZED:
3623                            ewmh_change_state(sw->wnd, state);
3624                            XMapWindow(g_display, sw->wnd);
3625                            break;
3626                    case SEAMLESSRDP_MINIMIZED:
3627                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3628                               the Window Manager should probably just ignore the request, since
3629                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3630                               such as minimization, rather than an independent state." Besides,
3631                               XIconifyWindow is easier. */
3632                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3633                            {
3634                                    XWMHints *hints;
3635                                    hints = XGetWMHints(g_display, sw->wnd);
3636                                    if (hints)
3637                                    {
3638                                            hints->flags |= StateHint;
3639                                            hints->initial_state = IconicState;
3640                                            XSetWMHints(g_display, sw->wnd, hints);
3641                                            XFree(hints);
3642                                    }
3643                                    XMapWindow(g_display, sw->wnd);
3644                            }
3645                            else
3646                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3647                            break;
3648                    default:
3649                            warning("SeamlessRDP: Invalid state %d\n", state);
3650                            break;
3651            }
3652    
3653            sw->state = state;
3654    }
3655    
3656    
3657    void
3658    ui_seamless_syncbegin(unsigned long flags)
3659    {
3660            if (!g_seamless_active)
3661                    return;
3662    
3663            /* Destroy all seamless windows */
3664            while (g_seamless_windows)
3665            {
3666                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3667                    sw_remove_window(g_seamless_windows);
3668            }
3669    }
3670    
3671    
3672    void
3673    ui_seamless_ack(unsigned int serial)
3674    {
3675            seamless_window *sw;
3676            for (sw = g_seamless_windows; sw; sw = sw->next)
3677            {
3678                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3679                    {
3680                            sw->xoffset = sw->outpos_xoffset;
3681                            sw->yoffset = sw->outpos_yoffset;
3682                            sw->width = sw->outpos_width;
3683                            sw->height = sw->outpos_height;
3684                            sw->outstanding_position = False;
3685    
3686                            /* Do a complete redraw of the window as part of the
3687                               completion of the move. This is to remove any
3688                               artifacts caused by our lack of synchronization. */
3689                            XCopyArea(g_display, g_backstore,
3690                                      sw->wnd, g_gc,
3691                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3692    
3693                            break;
3694                    }
3695            }
3696    }

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

  ViewVC Help
Powered by ViewVC 1.1.26