/[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 1042 by astrand, Tue Jan 24 12:40:24 2006 UTC revision 1214 by ossman_, Tue Mar 28 13:56:08 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 the visual is has 15, 16 or 24 depth  /* Indicates that:
115     and the same color channel masks as its RDP equivalent. */     1) visual has 15, 16 or 24 depth and the same color channel masks
116  static BOOL g_compatible_depth;        as its RDP equivalent (implies X server is LE),
117       2) host is LE
118       This will trigger an optimization whose real value is questionable.
119    */
120    static BOOL g_compatible_arch;
121  /* Indicates whether RDP's bitmaps and our XImages have the same  /* Indicates whether RDP's bitmaps and our XImages have the same
122     binary format. If so, we can avoid an expensive translation.     binary format. If so, we can avoid an expensive translation.
123     If this is True, so is g_compatible_depth. */     Note that this can be true when g_compatible_arch is false,
124       e.g.:
125      
126         RDP(LE) <-> host(BE) <-> X-Server(LE)
127        
128       ('host' is the machine running rdesktop; the host simply memcpy's
129        so its endianess doesn't matter)
130     */
131  static BOOL g_no_translate_image = False;  static BOOL g_no_translate_image = False;
132    
133  /* endianness */  /* endianness */
# Line 122  typedef struct Line 173  typedef struct
173  }  }
174  PixelColour;  PixelColour;
175    
176    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
177            do { \
178                    seamless_window *sw; \
179                    XRectangle rect; \
180                    if (!g_seamless_windows) break; \
181                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
182                        rect.x = g_clip_rectangle.x - sw->xoffset; \
183                        rect.y = g_clip_rectangle.y - sw->yoffset; \
184                        rect.width = g_clip_rectangle.width; \
185                        rect.height = g_clip_rectangle.height; \
186                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
187                        func args; \
188                    } \
189                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
190            } while (0)
191    
192    static void
193    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
194    {
195            points[0].x -= xoffset;
196            points[0].y -= yoffset;
197            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
198            points[0].x += xoffset;
199            points[0].y += yoffset;
200    }
201    
202    static void
203    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
204    {
205            points[0].x -= xoffset;
206            points[0].y -= yoffset;
207            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
208            points[0].x += xoffset;
209            points[0].y += yoffset;
210    }
211    
212  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
213  { \  { \
214          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
215            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
216          if (g_ownbackstore) \          if (g_ownbackstore) \
217                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
218  }  }
# Line 140  PixelColour; Line 227  PixelColour;
227          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
228          if (g_ownbackstore) \          if (g_ownbackstore) \
229                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
230            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
231  }  }
232    
233  #define DRAW_ELLIPSE(x,y,cx,cy,m)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 148  PixelColour; Line 236  PixelColour;
236          { \          { \
237                  case 0: /* Outline */ \                  case 0: /* Outline */ \
238                          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); \
239                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
240                          if (g_ownbackstore) \                          if (g_ownbackstore) \
241                                  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); \
242                          break; \                          break; \
243                  case 1: /* Filled */ \                  case 1: /* Filled */ \
244                          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); \
245                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc, \
246                                                                x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \
247                          if (g_ownbackstore) \                          if (g_ownbackstore) \
248                                  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); \
249                          break; \                          break; \
# Line 190  static int rop2_map[] = { Line 281  static int rop2_map[] = {
281  #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]); }
282  #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); }
283    
284    static seamless_window *
285    sw_get_window_by_id(unsigned long id)
286    {
287            seamless_window *sw;
288            for (sw = g_seamless_windows; sw; sw = sw->next)
289            {
290                    if (sw->id == id)
291                            return sw;
292            }
293            return NULL;
294    }
295    
296    
297    static seamless_window *
298    sw_get_window_by_wnd(Window wnd)
299    {
300            seamless_window *sw;
301            for (sw = g_seamless_windows; sw; sw = sw->next)
302            {
303                    if (sw->wnd == wnd)
304                            return sw;
305            }
306            return NULL;
307    }
308    
309    
310    static void
311    sw_remove_window(seamless_window * win)
312    {
313            seamless_window *sw, **prevnext = &g_seamless_windows;
314            for (sw = g_seamless_windows; sw; sw = sw->next)
315            {
316                    if (sw == win)
317                    {
318                            *prevnext = sw->next;
319                            sw->group->refcnt--;
320                            if (sw->group->refcnt == 0)
321                            {
322                                    XDestroyWindow(g_display, sw->group->wnd);
323                                    xfree(sw->group);
324                            }
325                            xfree(sw->position_timer);
326                            xfree(sw);
327                            return;
328                    }
329                    prevnext = &sw->next;
330            }
331            return;
332    }
333    
334    
335    /* Move all windows except wnd to new desktop */
336  static void  static void
337  mwm_hide_decorations(void)  sw_all_to_desktop(Window wnd, unsigned int desktop)
338    {
339            seamless_window *sw;
340            for (sw = g_seamless_windows; sw; sw = sw->next)
341            {
342                    if (sw->wnd == wnd)
343                            continue;
344                    if (sw->desktop != desktop)
345                    {
346                            ewmh_move_to_desktop(sw->wnd, desktop);
347                            sw->desktop = desktop;
348                    }
349            }
350    }
351    
352    
353    /* Send our position */
354    static void
355    sw_update_position(seamless_window * sw)
356    {
357            XWindowAttributes wa;
358            int x, y;
359            Window child_return;
360            unsigned int serial;
361    
362            XGetWindowAttributes(g_display, sw->wnd, &wa);
363            XTranslateCoordinates(g_display, sw->wnd, wa.root,
364                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
365    
366            serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
367    
368            sw->outstanding_position = True;
369            sw->outpos_serial = serial;
370    
371            sw->outpos_xoffset = x;
372            sw->outpos_yoffset = y;
373            sw->outpos_width = wa.width;
374            sw->outpos_height = wa.height;
375    }
376    
377    
378    /* Check if it's time to send our position */
379    static void
380    sw_check_timers()
381    {
382            seamless_window *sw;
383            struct timeval now;
384    
385            gettimeofday(&now, NULL);
386            for (sw = g_seamless_windows; sw; sw = sw->next)
387            {
388                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
389                    {
390                            timerclear(sw->position_timer);
391                            sw_update_position(sw);
392                    }
393            }
394    }
395    
396    
397    static void
398    sw_restack_window(seamless_window * sw, unsigned long behind)
399    {
400            seamless_window *sw_above;
401    
402            /* Remove window from stack */
403            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
404            {
405                    if (sw_above->behind == sw->id)
406                            break;
407            }
408    
409            if (sw_above)
410                    sw_above->behind = sw->behind;
411    
412            /* And then add it at the new position */
413            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
414            {
415                    if (sw_above->behind == behind)
416                            break;
417            }
418    
419            if (sw_above)
420                    sw_above->behind = sw->id;
421    
422            sw->behind = behind;
423    }
424    
425    
426    static void
427    sw_handle_restack(seamless_window * sw)
428    {
429            Status status;
430            Window root, parent, *children;
431            unsigned int nchildren, i;
432            seamless_window *sw_below;
433    
434            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
435                                &root, &parent, &children, &nchildren);
436            if (!status || !nchildren)
437                    return;
438    
439            sw_below = NULL;
440    
441            i = 0;
442            while (children[i] != sw->wnd)
443            {
444                    i++;
445                    if (i >= nchildren)
446                            goto end;
447            }
448    
449            for (i++; i < nchildren; i++)
450            {
451                    sw_below = sw_get_window_by_wnd(children[i]);
452                    if (sw_below)
453                            break;
454            }
455    
456            if (!sw_below && !sw->behind)
457                    goto end;
458            if (sw_below && (sw_below->id == sw->behind))
459                    goto end;
460    
461            if (sw_below)
462            {
463                    seamless_send_zchange(sw->id, sw_below->id, 0);
464                    sw_restack_window(sw, sw_below->id);
465            }
466            else
467            {
468                    seamless_send_zchange(sw->id, 0, 0);
469                    sw_restack_window(sw, 0);
470            }
471    
472          end:
473            XFree(children);
474    }
475    
476    
477    static seamless_group *
478    sw_find_group(unsigned long id, BOOL dont_create)
479    {
480            seamless_window *sw;
481            seamless_group *sg;
482            XSetWindowAttributes attribs;
483    
484            for (sw = g_seamless_windows; sw; sw = sw->next)
485            {
486                    if (sw->group->id == id)
487                            return sw->group;
488            }
489    
490            if (dont_create)
491                    return NULL;
492    
493            sg = xmalloc(sizeof(seamless_group));
494    
495            sg->wnd =
496                    XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0,
497                                  CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
498    
499            sg->id = id;
500            sg->refcnt = 0;
501    
502            return sg;
503    }
504    
505    
506    static void
507    mwm_hide_decorations(Window wnd)
508  {  {
509          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
510          Atom hintsatom;          Atom hintsatom;
# Line 208  mwm_hide_decorations(void) Line 521  mwm_hide_decorations(void)
521                  return;                  return;
522          }          }
523    
524          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
525                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
526    
527  }  }
528    
529  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 243  mwm_hide_decorations(void) Line 557  mwm_hide_decorations(void)
557  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
558                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
559    
560    /* The following macros output the same octet sequences
561       on both BE and LE hosts: */
562    
563  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
564  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
565  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
# Line 322  translate8to16(const uint8 * data, uint8 Line 639  translate8to16(const uint8 * data, uint8
639  {  {
640          uint16 value;          uint16 value;
641    
642          if (g_compatible_depth)          if (g_compatible_arch)
643          {          {
644                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
645                  REPEAT2                  REPEAT2
# Line 356  translate8to24(const uint8 * data, uint8 Line 673  translate8to24(const uint8 * data, uint8
673  {  {
674          uint32 value;          uint32 value;
675    
676          if (g_compatible_depth)          if (g_compatible_arch)
677          {          {
678                  while (out < end)                  while (out < end)
679                  {                  {
# Line 379  translate8to32(const uint8 * data, uint8 Line 696  translate8to32(const uint8 * data, uint8
696  {  {
697          uint32 value;          uint32 value;
698    
699          if (g_compatible_depth)          if (g_compatible_arch)
700          {          {
701                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
702                  REPEAT4                  REPEAT4
# Line 451  translate15to24(const uint16 * data, uin Line 768  translate15to24(const uint16 * data, uin
768          uint16 pixel;          uint16 pixel;
769          PixelColour pc;          PixelColour pc;
770    
771          if (g_compatible_depth)          if (g_compatible_arch)
772          {          {
773                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
774                  REPEAT3                  REPEAT3
# Line 501  translate15to32(const uint16 * data, uin Line 818  translate15to32(const uint16 * data, uin
818          uint32 value;          uint32 value;
819          PixelColour pc;          PixelColour pc;
820    
821          if (g_compatible_depth)          if (g_compatible_arch)
822          {          {
823                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
824                  REPEAT4                  REPEAT4
# Line 609  translate16to24(const uint16 * data, uin Line 926  translate16to24(const uint16 * data, uin
926          uint16 pixel;          uint16 pixel;
927          PixelColour pc;          PixelColour pc;
928    
929          if (g_compatible_depth)          if (g_compatible_arch)
930          {          {
931                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
932                  REPEAT3                  REPEAT3
# Line 679  translate16to32(const uint16 * data, uin Line 996  translate16to32(const uint16 * data, uin
996          uint32 value;          uint32 value;
997          PixelColour pc;          PixelColour pc;
998    
999          if (g_compatible_depth)          if (g_compatible_arch)
1000          {          {
1001                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
1002                  REPEAT4                  REPEAT4
# Line 808  translate24to32(const uint8 * data, uint Line 1125  translate24to32(const uint8 * data, uint
1125          uint32 value;          uint32 value;
1126          PixelColour pc;          PixelColour pc;
1127    
1128          if (g_compatible_depth)          if (g_compatible_arch)
1129          {          {
1130                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
1131  #ifdef NEED_ALIGN  #ifdef NEED_ALIGN
# Line 1021  select_visual() Line 1338  select_visual()
1338          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1339          g_visual = NULL;          g_visual = NULL;
1340          g_no_translate_image = False;          g_no_translate_image = False;
1341          g_compatible_depth = False;          g_compatible_arch = False;
1342          if (vmatches != NULL)          if (vmatches != NULL)
1343          {          {
1344                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
# Line 1048  select_visual() Line 1365  select_visual()
1365                          {                          {
1366                                  g_visual = visual_info->visual;                                  g_visual = visual_info->visual;
1367                                  g_depth = visual_info->depth;                                  g_depth = visual_info->depth;
1368                                  g_compatible_depth = True;                                  g_compatible_arch = !g_host_be;
1369                                  g_no_translate_image = (visual_info->depth == g_server_depth);                                  g_no_translate_image = (visual_info->depth == g_server_depth);
1370                                  if (g_no_translate_image)                                  if (g_no_translate_image)
1371                                          /* We found the best visual */                                          /* We found the best visual */
# Line 1056  select_visual() Line 1373  select_visual()
1373                          }                          }
1374                          else                          else
1375                          {                          {
1376                                  g_compatible_depth = False;                                  g_compatible_arch = False;
1377                          }                          }
1378    
1379                          if (visual_info->depth > 24)                          if (visual_info->depth > 24)
# Line 1183  select_visual() Line 1500  select_visual()
1500          return True;          return True;
1501  }  }
1502    
1503    static XErrorHandler g_old_error_handler;
1504    
1505    static int
1506    error_handler(Display * dpy, XErrorEvent * eev)
1507    {
1508            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1509            {
1510                    fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1511                    fprintf(stderr,
1512                            "This is most likely caused by a broken window manager (commonly KWin).\n");
1513                    return 0;
1514            }
1515    
1516            return g_old_error_handler(dpy, eev);
1517    }
1518    
1519  BOOL  BOOL
1520  ui_init(void)  ui_init(void)
1521  {  {
# Line 1200  ui_init(void) Line 1533  ui_init(void)
1533                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1534          }          }
1535    
1536            g_old_error_handler = XSetErrorHandler(error_handler);
1537          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1538          screen_num = DefaultScreen(g_display);          screen_num = DefaultScreen(g_display);
1539          g_x_socket = ConnectionNumber(g_display);          g_x_socket = ConnectionNumber(g_display);
# Line 1245  ui_init(void) Line 1579  ui_init(void)
1579          {          {
1580                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1581                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1582                    g_using_full_workarea = True;
1583          }          }
1584          else if (g_width < 0)          else if (g_width < 0)
1585          {          {
# Line 1258  ui_init(void) Line 1593  ui_init(void)
1593          {          {
1594                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1595                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
                 g_using_full_workarea = True;  
   
1596                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1597                  {                  {
1598                          g_width = cx;                          g_width = cx;
1599                          g_height = cy;                          g_height = cy;
1600                            g_using_full_workarea = True;
1601                  }                  }
1602                  else                  else
1603                  {                  {
1604                          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");
1605                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1606                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1607                  }                  }
1608          }          }
1609    
# Line 1284  ui_init(void) Line 1618  ui_init(void)
1618                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1619    
1620          xclip_init();          xclip_init();
1621            ewmh_init();
1622            if (g_seamless_rdp)
1623                    seamless_init();
1624    
1625          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));
1626    
# Line 1293  ui_init(void) Line 1630  ui_init(void)
1630  void  void
1631  ui_deinit(void)  ui_deinit(void)
1632  {  {
1633            while (g_seamless_windows)
1634            {
1635                    XDestroyWindow(g_display, g_seamless_windows->wnd);
1636                    sw_remove_window(g_seamless_windows);
1637            }
1638    
1639            xclip_deinit();
1640    
1641          if (g_IM != NULL)          if (g_IM != NULL)
1642                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1643    
# Line 1309  ui_deinit(void) Line 1654  ui_deinit(void)
1654          g_display = NULL;          g_display = NULL;
1655  }  }
1656    
1657    
1658    static void
1659    get_window_attribs(XSetWindowAttributes * attribs)
1660    {
1661            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1662            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1663            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1664            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1665            attribs->override_redirect = g_fullscreen;
1666            attribs->colormap = g_xcolmap;
1667    }
1668    
1669    static void
1670    get_input_mask(long *input_mask)
1671    {
1672            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1673                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1674    
1675            if (g_sendmotion)
1676                    *input_mask |= PointerMotionMask;
1677            if (g_ownbackstore)
1678                    *input_mask |= ExposureMask;
1679            if (g_fullscreen || g_grab_keyboard)
1680                    *input_mask |= EnterWindowMask;
1681            if (g_grab_keyboard)
1682                    *input_mask |= LeaveWindowMask;
1683    }
1684    
1685  BOOL  BOOL
1686  ui_create_window(void)  ui_create_window(void)
1687  {  {
# Line 1331  ui_create_window(void) Line 1704  ui_create_window(void)
1704          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1705                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1706    
1707          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;  
1708    
1709          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,
1710                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1343  ui_create_window(void) Line 1712  ui_create_window(void)
1712                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1713    
1714          if (g_gc == NULL)          if (g_gc == NULL)
1715            {
1716                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1717                    ui_reset_clip();
1718            }
1719    
1720          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1721                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 1360  ui_create_window(void) Line 1732  ui_create_window(void)
1732          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1733    
1734          if (g_hide_decorations)          if (g_hide_decorations)
1735                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1736    
1737          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1738          if (classhints != NULL)          if (classhints != NULL)
# Line 1387  ui_create_window(void) Line 1759  ui_create_window(void)
1759                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1760          }          }
1761    
1762          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;  
1763    
1764          if (g_IM != NULL)          if (g_IM != NULL)
1765          {          {
# Line 1482  xwin_toggle_fullscreen(void) Line 1844  xwin_toggle_fullscreen(void)
1844  {  {
1845          Pixmap contents = 0;          Pixmap contents = 0;
1846    
1847            if (g_seamless_active)
1848                    /* Turn off SeamlessRDP mode */
1849                    ui_seamless_toggle();
1850    
1851          if (!g_ownbackstore)          if (!g_ownbackstore)
1852          {          {
1853                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1570  handle_button_event(XEvent xevent, BOOL Line 1936  handle_button_event(XEvent xevent, BOOL
1936                  }                  }
1937          }          }
1938    
1939          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1940                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1941                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1942                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1943            }
1944            else
1945            {
1946                    /* SeamlessRDP */
1947                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1948                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1949            }
1950  }  }
1951    
1952    
1953  /* Process events in Xlib queue  /* Process events in Xlib queue
1954     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1955  static int  static int
# Line 1585  xwin_process_events(void) Line 1961  xwin_process_events(void)
1961          char str[256];          char str[256];
1962          Status status;          Status status;
1963          int events = 0;          int events = 0;
1964            seamless_window *sw;
1965    
1966          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1967          {          {
# Line 1599  xwin_process_events(void) Line 1976  xwin_process_events(void)
1976                  switch (xevent.type)                  switch (xevent.type)
1977                  {                  {
1978                          case VisibilityNotify:                          case VisibilityNotify:
1979                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1980                                            g_Unobscured =
1981                                                    xevent.xvisibility.state == VisibilityUnobscured;
1982    
1983                                  break;                                  break;
1984                          case ClientMessage:                          case ClientMessage:
1985                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1679  xwin_process_events(void) Line 2059  xwin_process_events(void)
2059                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
2060                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2061                                                         CurrentTime);                                                         CurrentTime);
2062                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
2063                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
2064                                    {
2065                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2066                                                           xevent.xmotion.x, xevent.xmotion.y);
2067                                    }
2068                                    else
2069                                    {
2070                                            /* SeamlessRDP */
2071                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2072                                                           xevent.xmotion.x_root,
2073                                                           xevent.xmotion.y_root);
2074                                    }
2075                                  break;                                  break;
2076    
2077                          case FocusIn:                          case FocusIn:
# Line 1691  xwin_process_events(void) Line 2082  xwin_process_events(void)
2082                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2083                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2084                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2085    
2086                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2087                                    if (!sw)
2088                                            break;
2089    
2090                                    if (sw->id != g_seamless_focused)
2091                                    {
2092                                            seamless_send_focus(sw->id, 0);
2093                                            g_seamless_focused = sw->id;
2094                                    }
2095                                  break;                                  break;
2096    
2097                          case FocusOut:                          case FocusOut:
# Line 1723  xwin_process_events(void) Line 2124  xwin_process_events(void)
2124                                  break;                                  break;
2125    
2126                          case Expose:                          case Expose:
2127                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2128                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2129                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2130                                            xevent.xexpose.height,                                                    g_gc,
2131                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2132                                                      xevent.xexpose.width, xevent.xexpose.height,
2133                                                      xevent.xexpose.x, xevent.xexpose.y);
2134                                    }
2135                                    else
2136                                    {
2137                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2138                                            if (!sw)
2139                                                    break;
2140                                            XCopyArea(g_display, g_backstore,
2141                                                      xevent.xexpose.window, g_gc,
2142                                                      xevent.xexpose.x + sw->xoffset,
2143                                                      xevent.xexpose.y + sw->yoffset,
2144                                                      xevent.xexpose.width,
2145                                                      xevent.xexpose.height, xevent.xexpose.x,
2146                                                      xevent.xexpose.y);
2147                                    }
2148    
2149                                  break;                                  break;
2150    
2151                          case MappingNotify:                          case MappingNotify:
# Line 1756  xwin_process_events(void) Line 2174  xwin_process_events(void)
2174                                  break;                                  break;
2175                          case PropertyNotify:                          case PropertyNotify:
2176                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2177                                    if (xevent.xproperty.window == g_wnd)
2178                                            break;
2179                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2180                                            break;
2181    
2182                                    /* seamless */
2183                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2184                                    if (!sw)
2185                                            break;
2186    
2187                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2188                                        && (xevent.xproperty.state == PropertyNewValue))
2189                                    {
2190                                            sw->state = ewmh_get_window_state(sw->wnd);
2191                                            seamless_send_state(sw->id, sw->state, 0);
2192                                    }
2193    
2194                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2195                                        && (xevent.xproperty.state == PropertyNewValue))
2196                                    {
2197                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2198                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2199                                    }
2200    
2201                                  break;                                  break;
2202                          case MapNotify:                          case MapNotify:
2203                                  rdp_send_client_window_status(1);                                  if (!g_seamless_active)
2204                                            rdp_send_client_window_status(1);
2205                                  break;                                  break;
2206                          case UnmapNotify:                          case UnmapNotify:
2207                                  rdp_send_client_window_status(0);                                  if (!g_seamless_active)
2208                                            rdp_send_client_window_status(0);
2209                                    break;
2210                            case ConfigureNotify:
2211                                    if (!g_seamless_active)
2212                                            break;
2213    
2214                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2215                                    if (!sw)
2216                                            break;
2217    
2218                                    gettimeofday(sw->position_timer, NULL);
2219                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2220                                        1000000)
2221                                    {
2222                                            sw->position_timer->tv_usec +=
2223                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2224                                            sw->position_timer->tv_sec += 1;
2225                                    }
2226                                    else
2227                                    {
2228                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2229                                    }
2230    
2231                                    sw_handle_restack(sw);
2232                                  break;                                  break;
2233                  }                  }
2234          }          }
# Line 1786  ui_select(int rdp_socket) Line 2253  ui_select(int rdp_socket)
2253                          /* User quit */                          /* User quit */
2254                          return 0;                          return 0;
2255    
2256                    if (g_seamless_active)
2257                            sw_check_timers();
2258    
2259                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2260                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2261                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
# Line 1805  ui_select(int rdp_socket) Line 2275  ui_select(int rdp_socket)
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 1898  ui_paint_bitmap(int x, int y, int cx, in Line 2369  ui_paint_bitmap(int x, int y, int cx, in
2369          {          {
2370                  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);
2371                  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);
2372                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2373                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2374                                             x - sw->xoffset, y - sw->yoffset));
2375          }          }
2376          else          else
2377          {          {
2378                  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);
2379                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2380                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2381                                             x - sw->xoffset, y - sw->yoffset));
2382          }          }
2383    
2384          XFree(image);          XFree(image);
# Line 2022  ui_set_cursor(HCURSOR cursor) Line 2499  ui_set_cursor(HCURSOR cursor)
2499  {  {
2500          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2501          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2502            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2503  }  }
2504    
2505  void  void
# Line 2163  ui_set_colourmap(HCOLOURMAP map) Line 2641  ui_set_colourmap(HCOLOURMAP map)
2641                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2642          }          }
2643          else          else
2644            {
2645                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2646                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2647            }
2648  }  }
2649    
2650  void  void
2651  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2652  {  {
2653          XRectangle rect;          g_clip_rectangle.x = x;
2654            g_clip_rectangle.y = y;
2655          rect.x = x;          g_clip_rectangle.width = cx;
2656          rect.y = y;          g_clip_rectangle.height = cy;
2657          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);  
2658  }  }
2659    
2660  void  void
2661  ui_reset_clip(void)  ui_reset_clip(void)
2662  {  {
2663          XRectangle rect;          g_clip_rectangle.x = 0;
2664            g_clip_rectangle.y = 0;
2665          rect.x = 0;          g_clip_rectangle.width = g_width;
2666          rect.y = 0;          g_clip_rectangle.height = g_height;
2667          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);  
2668  }  }
2669    
2670  void  void
# Line 2268  ui_patblt(uint8 opcode, Line 2745  ui_patblt(uint8 opcode,
2745    
2746          if (g_ownbackstore)          if (g_ownbackstore)
2747                  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);
2748            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2749                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2750                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2751  }  }
2752    
2753  void  void
# Line 2278  ui_screenblt(uint8 opcode, Line 2758  ui_screenblt(uint8 opcode,
2758          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2759          if (g_ownbackstore)          if (g_ownbackstore)
2760          {          {
2761                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2762                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2763                          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);  
                 }  
2764          }          }
2765          else          else
2766          {          {
2767                  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);
2768          }          }
2769    
2770            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2771                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2772                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2773    
2774          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2775  }  }
2776    
# Line 2305  ui_memblt(uint8 opcode, Line 2781  ui_memblt(uint8 opcode,
2781  {  {
2782          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2783          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);
2784            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2785                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2786                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2787          if (g_ownbackstore)          if (g_ownbackstore)
2788                  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);
2789          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2351  ui_line(uint8 opcode, Line 2830  ui_line(uint8 opcode,
2830          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2831          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2832          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2833            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2834                                                startx - sw->xoffset, starty - sw->yoffset,
2835                                                endx - sw->xoffset, endy - sw->yoffset));
2836          if (g_ownbackstore)          if (g_ownbackstore)
2837                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2838          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2448  ui_polyline(uint8 opcode, Line 2930  ui_polyline(uint8 opcode,
2930          if (g_ownbackstore)          if (g_ownbackstore)
2931                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2932                             CoordModePrevious);                             CoordModePrevious);
2933    
2934            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2935                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2936    
2937          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2938  }  }
2939    
# Line 2668  ui_draw_text(uint8 font, uint8 flags, ui Line 3154  ui_draw_text(uint8 font, uint8 flags, ui
3154          if (g_ownbackstore)          if (g_ownbackstore)
3155          {          {
3156                  if (boxcx > 1)                  if (boxcx > 1)
3157                    {
3158                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3159                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3160                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3161                                                    (g_display, g_backstore, sw->wnd, g_gc,
3162                                                     boxx, boxy,
3163                                                     boxcx, boxcy,
3164                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3165                    }
3166                  else                  else
3167                    {
3168                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3169                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3170                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3171                                                    (g_display, g_backstore, sw->wnd, g_gc,
3172                                                     clipx, clipy,
3173                                                     clipcx, clipcy, clipx - sw->xoffset,
3174                                                     clipy - sw->yoffset));
3175                    }
3176          }          }
3177  }  }
3178    
# Line 2718  ui_desktop_restore(uint32 offset, int x, Line 3218  ui_desktop_restore(uint32 offset, int x,
3218          {          {
3219                  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);
3220                  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);
3221                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3222                                            (g_display, g_backstore, sw->wnd, g_gc,
3223                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3224          }          }
3225          else          else
3226          {          {
3227                  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);
3228                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3229                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3230                                             x - sw->xoffset, y - sw->yoffset));
3231          }          }
3232    
3233          XFree(image);          XFree(image);
# Line 2737  void Line 3243  void
3243  ui_end_update(void)  ui_end_update(void)
3244  {  {
3245  }  }
3246    
3247    
3248    void
3249    ui_seamless_begin(BOOL hidden)
3250    {
3251            if (!g_seamless_rdp)
3252                    return;
3253    
3254            if (g_seamless_started)
3255                    return;
3256    
3257            g_seamless_started = True;
3258            g_seamless_hidden = hidden;
3259    
3260            if (!hidden)
3261                    ui_seamless_toggle();
3262    }
3263    
3264    
3265    void
3266    ui_seamless_hide_desktop()
3267    {
3268            if (!g_seamless_rdp)
3269                    return;
3270    
3271            if (!g_seamless_started)
3272                    return;
3273    
3274            if (g_seamless_active)
3275                    ui_seamless_toggle();
3276    
3277            g_seamless_hidden = True;
3278    }
3279    
3280    
3281    void
3282    ui_seamless_unhide_desktop()
3283    {
3284            if (!g_seamless_rdp)
3285                    return;
3286    
3287            if (!g_seamless_started)
3288                    return;
3289    
3290            g_seamless_hidden = False;
3291    
3292            ui_seamless_toggle();
3293    }
3294    
3295    
3296    void
3297    ui_seamless_toggle()
3298    {
3299            if (!g_seamless_rdp)
3300                    return;
3301    
3302            if (!g_seamless_started)
3303                    return;
3304    
3305            if (g_seamless_hidden)
3306                    return;
3307    
3308            if (g_seamless_active)
3309            {
3310                    /* Deactivate */
3311                    while (g_seamless_windows)
3312                    {
3313                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3314                            sw_remove_window(g_seamless_windows);
3315                    }
3316                    XMapWindow(g_display, g_wnd);
3317            }
3318            else
3319            {
3320                    /* Activate */
3321                    XUnmapWindow(g_display, g_wnd);
3322                    seamless_send_sync();
3323            }
3324    
3325            g_seamless_active = !g_seamless_active;
3326    }
3327    
3328    
3329    void
3330    ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3331                              unsigned long flags)
3332    {
3333            Window wnd;
3334            XSetWindowAttributes attribs;
3335            XClassHint *classhints;
3336            XSizeHints *sizehints;
3337            XWMHints *wmhints;
3338            long input_mask;
3339            seamless_window *sw, *sw_parent;
3340    
3341            if (!g_seamless_active)
3342                    return;
3343    
3344            /* Ignore CREATEs for existing windows */
3345            sw = sw_get_window_by_id(id);
3346            if (sw)
3347                    return;
3348    
3349            get_window_attribs(&attribs);
3350            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3351                                InputOutput, g_visual,
3352                                CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3353    
3354            XStoreName(g_display, wnd, "SeamlessRDP");
3355            ewmh_set_wm_name(wnd, "SeamlessRDP");
3356    
3357            mwm_hide_decorations(wnd);
3358    
3359            classhints = XAllocClassHint();
3360            if (classhints != NULL)
3361            {
3362                    classhints->res_name = "rdesktop";
3363                    classhints->res_class = "SeamlessRDP";
3364                    XSetClassHint(g_display, wnd, classhints);
3365                    XFree(classhints);
3366            }
3367    
3368            /* WM_NORMAL_HINTS */
3369            sizehints = XAllocSizeHints();
3370            if (sizehints != NULL)
3371            {
3372                    sizehints->flags = USPosition;
3373                    XSetWMNormalHints(g_display, wnd, sizehints);
3374                    XFree(sizehints);
3375            }
3376    
3377            /* Parent-less transient windows */
3378            if (parent == 0xFFFFFFFF)
3379            {
3380                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3381                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3382                       using some other hints. */
3383                    ewmh_set_window_popup(wnd);
3384            }
3385            /* Normal transient windows */
3386            else if (parent != 0x00000000)
3387            {
3388                    sw_parent = sw_get_window_by_id(parent);
3389                    if (sw_parent)
3390                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3391                    else
3392                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3393            }
3394    
3395            if (flags & SEAMLESSRDP_CREATE_MODAL)
3396            {
3397                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3398                       somewhat at least */
3399                    if (parent == 0x00000000)
3400                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3401                    ewmh_set_window_modal(wnd);
3402            }
3403    
3404            /* FIXME: Support for Input Context:s */
3405    
3406            get_input_mask(&input_mask);
3407            input_mask |= PropertyChangeMask;
3408    
3409            XSelectInput(g_display, wnd, input_mask);
3410    
3411            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3412               seamless window, we could try to close the window on the
3413               serverside, instead of terminating rdesktop */
3414            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3415    
3416            sw = xmalloc(sizeof(seamless_window));
3417            sw->wnd = wnd;
3418            sw->id = id;
3419            sw->behind = 0;
3420            sw->group = sw_find_group(group, False);
3421            sw->group->refcnt++;
3422            sw->xoffset = 0;
3423            sw->yoffset = 0;
3424            sw->width = 0;
3425            sw->height = 0;
3426            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3427            sw->desktop = 0;
3428            sw->position_timer = xmalloc(sizeof(struct timeval));
3429            timerclear(sw->position_timer);
3430    
3431            sw->outstanding_position = False;
3432            sw->outpos_serial = 0;
3433            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3434            sw->outpos_width = sw->outpos_height = 0;
3435    
3436            sw->next = g_seamless_windows;
3437            g_seamless_windows = sw;
3438    
3439            /* WM_HINTS */
3440            wmhints = XAllocWMHints();
3441            if (wmhints)
3442            {
3443                    wmhints->flags = WindowGroupHint;
3444                    wmhints->window_group = sw->group->wnd;
3445                    XSetWMHints(g_display, sw->wnd, wmhints);
3446                    XFree(wmhints);
3447            }
3448    }
3449    
3450    
3451    void
3452    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3453    {
3454            seamless_window *sw;
3455    
3456            if (!g_seamless_active)
3457                    return;
3458    
3459            sw = sw_get_window_by_id(id);
3460            if (!sw)
3461            {
3462                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3463                    return;
3464            }
3465    
3466            XDestroyWindow(g_display, sw->wnd);
3467            sw_remove_window(sw);
3468    }
3469    
3470    
3471    void
3472    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3473    {
3474            seamless_window *sw;
3475    
3476            if (!g_seamless_active)
3477                    return;
3478    
3479            sw = sw_get_window_by_id(id);
3480            if (!sw)
3481            {
3482                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3483                    return;
3484            }
3485    
3486            /* We ignore server updates until it has handled our request. */
3487            if (sw->outstanding_position)
3488                    return;
3489    
3490            if (!width || !height)
3491                    /* X11 windows must be at least 1x1 */
3492                    return;
3493    
3494            sw->xoffset = x;
3495            sw->yoffset = y;
3496            sw->width = width;
3497            sw->height = height;
3498    
3499            /* If we move the window in a maximized state, then KDE won't
3500               accept restoration */
3501            switch (sw->state)
3502            {
3503                    case SEAMLESSRDP_MINIMIZED:
3504                    case SEAMLESSRDP_MAXIMIZED:
3505                            return;
3506            }
3507    
3508            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3509            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3510    }
3511    
3512    
3513    void
3514    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3515    {
3516            seamless_window *sw;
3517    
3518            if (!g_seamless_active)
3519                    return;
3520    
3521            sw = sw_get_window_by_id(id);
3522            if (!sw)
3523            {
3524                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3525                    return;
3526            }
3527    
3528            if (behind)
3529            {
3530                    seamless_window *sw_behind;
3531                    Window wnds[2];
3532    
3533                    sw_behind = sw_get_window_by_id(behind);
3534                    if (!sw_behind)
3535                    {
3536                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3537                                    behind);
3538                            return;
3539                    }
3540    
3541                    wnds[1] = sw_behind->wnd;
3542                    wnds[0] = sw->wnd;
3543    
3544                    XRestackWindows(g_display, wnds, 2);
3545            }
3546            else
3547            {
3548                    XRaiseWindow(g_display, sw->wnd);
3549            }
3550    
3551            sw_restack_window(sw, behind);
3552    }
3553    
3554    
3555    void
3556    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3557    {
3558            seamless_window *sw;
3559    
3560            if (!g_seamless_active)
3561                    return;
3562    
3563            sw = sw_get_window_by_id(id);
3564            if (!sw)
3565            {
3566                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3567                    return;
3568            }
3569    
3570            /* FIXME: Might want to convert the name for non-EWMH WMs */
3571            XStoreName(g_display, sw->wnd, title);
3572            ewmh_set_wm_name(sw->wnd, title);
3573    }
3574    
3575    
3576    void
3577    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3578    {
3579            seamless_window *sw;
3580    
3581            if (!g_seamless_active)
3582                    return;
3583    
3584            sw = sw_get_window_by_id(id);
3585            if (!sw)
3586            {
3587                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3588                    return;
3589            }
3590    
3591            switch (state)
3592            {
3593                    case SEAMLESSRDP_NORMAL:
3594                    case SEAMLESSRDP_MAXIMIZED:
3595                            ewmh_change_state(sw->wnd, state);
3596                            XMapWindow(g_display, sw->wnd);
3597                            break;
3598                    case SEAMLESSRDP_MINIMIZED:
3599                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3600                               the Window Manager should probably just ignore the request, since
3601                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3602                               such as minimization, rather than an independent state." Besides,
3603                               XIconifyWindow is easier. */
3604                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3605                            {
3606                                    XWMHints *hints;
3607                                    hints = XGetWMHints(g_display, sw->wnd);
3608                                    if (hints)
3609                                    {
3610                                            hints->flags |= StateHint;
3611                                            hints->initial_state = IconicState;
3612                                            XSetWMHints(g_display, sw->wnd, hints);
3613                                            XFree(hints);
3614                                    }
3615                                    XMapWindow(g_display, sw->wnd);
3616                            }
3617                            else
3618                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3619                            break;
3620                    default:
3621                            warning("SeamlessRDP: Invalid state %d\n", state);
3622                            break;
3623            }
3624    
3625            sw->state = state;
3626    }
3627    
3628    
3629    void
3630    ui_seamless_syncbegin(unsigned long flags)
3631    {
3632            if (!g_seamless_active)
3633                    return;
3634    
3635            /* Destroy all seamless windows */
3636            while (g_seamless_windows)
3637            {
3638                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3639                    sw_remove_window(g_seamless_windows);
3640            }
3641    }
3642    
3643    
3644    void
3645    ui_seamless_ack(unsigned int serial)
3646    {
3647            seamless_window *sw;
3648            for (sw = g_seamless_windows; sw; sw = sw->next)
3649            {
3650                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3651                    {
3652                            sw->xoffset = sw->outpos_xoffset;
3653                            sw->yoffset = sw->outpos_yoffset;
3654                            sw->width = sw->outpos_width;
3655                            sw->height = sw->outpos_height;
3656                            sw->outstanding_position = False;
3657    
3658                            /* Do a complete redraw of the window as part of the
3659                               completion of the move. This is to remove any
3660                               artifacts caused by our lack of synchronization. */
3661                            XCopyArea(g_display, g_backstore,
3662                                      sw->wnd, g_gc,
3663                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3664    
3665                            break;
3666                    }
3667            }
3668    }

Legend:
Removed from v.1042  
changed lines
  Added in v.1214

  ViewVC Help
Powered by ViewVC 1.1.26