/[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 1246 by stargo, Tue Jul 11 17:22:24 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
337    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  static void
427  mwm_hide_decorations(void)  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 997  calculate_mask_weight(uint32 mask) Line 1314  calculate_mask_weight(uint32 mask)
1314  }  }
1315    
1316  static BOOL  static BOOL
1317  select_visual()  select_visual(int screen_num)
1318  {  {
1319          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1320          int pixmap_formats_count, visuals_count;          int pixmap_formats_count, visuals_count;
# Line 1008  select_visual() Line 1325  select_visual()
1325    
1326          red_weight = blue_weight = green_weight = 0;          red_weight = blue_weight = green_weight = 0;
1327    
1328            if (g_server_depth == -1)
1329            {
1330                    g_server_depth = DisplayPlanes(g_display, DefaultScreen(g_display));
1331            }
1332    
1333          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1334          if (pfm == NULL)          if (pfm == NULL)
1335          {          {
# Line 1018  select_visual() Line 1340  select_visual()
1340    
1341          /* Search for best TrueColor visual */          /* Search for best TrueColor visual */
1342          template.class = TrueColor;          template.class = TrueColor;
1343          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);          template.screen = screen_num;
1344            vmatches = XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template, &visuals_count);
1345          g_visual = NULL;          g_visual = NULL;
1346          g_no_translate_image = False;          g_no_translate_image = False;
1347          g_compatible_depth = False;          g_compatible_arch = False;
1348          if (vmatches != NULL)          if (vmatches != NULL)
1349          {          {
1350                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
1351                  {                  {
1352                          XVisualInfo *visual_info = &vmatches[i];                          XVisualInfo *visual_info = &vmatches[i];
1353                            BOOL can_translate_to_bpp = False;
1354                            int j;
1355    
1356                          /* Try to find a no-translation visual that'll                          /* Try to find a no-translation visual that'll
1357                             allow us to use RDP bitmaps directly as ZPixmaps. */                             allow us to use RDP bitmaps directly as ZPixmaps. */
# Line 1048  select_visual() Line 1373  select_visual()
1373                          {                          {
1374                                  g_visual = visual_info->visual;                                  g_visual = visual_info->visual;
1375                                  g_depth = visual_info->depth;                                  g_depth = visual_info->depth;
1376                                  g_compatible_depth = True;                                  g_compatible_arch = !g_host_be;
1377                                  g_no_translate_image = (visual_info->depth == g_server_depth);                                  g_no_translate_image = (visual_info->depth == g_server_depth);
1378                                  if (g_no_translate_image)                                  if (g_no_translate_image)
1379                                          /* We found the best visual */                                          /* We found the best visual */
# Line 1056  select_visual() Line 1381  select_visual()
1381                          }                          }
1382                          else                          else
1383                          {                          {
1384                                  g_compatible_depth = False;                                  g_compatible_arch = False;
1385                          }                          }
1386    
1387                          if (visual_info->depth > 24)                          if (visual_info->depth > 24)
# Line 1070  select_visual() Line 1395  select_visual()
1395    
1396                          /* Only care for visuals, for whose BPPs (not depths!)                          /* Only care for visuals, for whose BPPs (not depths!)
1397                             we have a translateXtoY function. */                             we have a translateXtoY function. */
                         BOOL can_translate_to_bpp = False;  
                         int j;  
1398                          for (j = 0; j < pixmap_formats_count; ++j)                          for (j = 0; j < pixmap_formats_count; ++j)
1399                          {                          {
1400                                  if (pfm[j].depth == visual_info->depth)                                  if (pfm[j].depth == visual_info->depth)
# Line 1183  select_visual() Line 1506  select_visual()
1506          return True;          return True;
1507  }  }
1508    
1509    static XErrorHandler g_old_error_handler;
1510    
1511    static int
1512    error_handler(Display * dpy, XErrorEvent * eev)
1513    {
1514            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1515            {
1516                    fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1517                    fprintf(stderr,
1518                            "This is most likely caused by a broken window manager (commonly KWin).\n");
1519                    return 0;
1520            }
1521    
1522            return g_old_error_handler(dpy, eev);
1523    }
1524    
1525  BOOL  BOOL
1526  ui_init(void)  ui_init(void)
1527  {  {
# Line 1200  ui_init(void) Line 1539  ui_init(void)
1539                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1540          }          }
1541    
1542            g_old_error_handler = XSetErrorHandler(error_handler);
1543          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1544          screen_num = DefaultScreen(g_display);          screen_num = DefaultScreen(g_display);
1545          g_x_socket = ConnectionNumber(g_display);          g_x_socket = ConnectionNumber(g_display);
1546          g_screen = ScreenOfDisplay(g_display, screen_num);          g_screen = ScreenOfDisplay(g_display, screen_num);
1547          g_depth = DefaultDepthOfScreen(g_screen);          g_depth = DefaultDepthOfScreen(g_screen);
1548    
1549          if (!select_visual())          if (!select_visual(screen_num))
1550                  return False;                  return False;
1551    
1552          if (g_no_translate_image)          if (g_no_translate_image)
# Line 1245  ui_init(void) Line 1585  ui_init(void)
1585          {          {
1586                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1587                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1588                    g_using_full_workarea = True;
1589          }          }
1590          else if (g_width < 0)          else if (g_width < 0)
1591          {          {
# Line 1258  ui_init(void) Line 1599  ui_init(void)
1599          {          {
1600                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1601                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
                 g_using_full_workarea = True;  
   
1602                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1603                  {                  {
1604                          g_width = cx;                          g_width = cx;
1605                          g_height = cy;                          g_height = cy;
1606                            g_using_full_workarea = True;
1607                  }                  }
1608                  else                  else
1609                  {                  {
1610                          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");
1611                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1612                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1613                  }                  }
1614          }          }
1615    
# Line 1284  ui_init(void) Line 1624  ui_init(void)
1624                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1625    
1626          xclip_init();          xclip_init();
1627            ewmh_init();
1628            if (g_seamless_rdp)
1629                    seamless_init();
1630    
1631          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));
1632    
# Line 1293  ui_init(void) Line 1636  ui_init(void)
1636  void  void
1637  ui_deinit(void)  ui_deinit(void)
1638  {  {
1639            while (g_seamless_windows)
1640            {
1641                    XDestroyWindow(g_display, g_seamless_windows->wnd);
1642                    sw_remove_window(g_seamless_windows);
1643            }
1644    
1645            xclip_deinit();
1646    
1647          if (g_IM != NULL)          if (g_IM != NULL)
1648                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1649    
# Line 1309  ui_deinit(void) Line 1660  ui_deinit(void)
1660          g_display = NULL;          g_display = NULL;
1661  }  }
1662    
1663    
1664    static void
1665    get_window_attribs(XSetWindowAttributes * attribs)
1666    {
1667            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1668            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1669            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1670            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1671            attribs->override_redirect = g_fullscreen;
1672            attribs->colormap = g_xcolmap;
1673    }
1674    
1675    static void
1676    get_input_mask(long *input_mask)
1677    {
1678            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1679                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1680    
1681            if (g_sendmotion)
1682                    *input_mask |= PointerMotionMask;
1683            if (g_ownbackstore)
1684                    *input_mask |= ExposureMask;
1685            if (g_fullscreen || g_grab_keyboard)
1686                    *input_mask |= EnterWindowMask;
1687            if (g_grab_keyboard)
1688                    *input_mask |= LeaveWindowMask;
1689    }
1690    
1691  BOOL  BOOL
1692  ui_create_window(void)  ui_create_window(void)
1693  {  {
# Line 1331  ui_create_window(void) Line 1710  ui_create_window(void)
1710          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1711                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1712    
1713          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;  
1714    
1715          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,
1716                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1343  ui_create_window(void) Line 1718  ui_create_window(void)
1718                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1719    
1720          if (g_gc == NULL)          if (g_gc == NULL)
1721            {
1722                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1723                    ui_reset_clip();
1724            }
1725    
1726          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1727                  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 1738  ui_create_window(void)
1738          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1739    
1740          if (g_hide_decorations)          if (g_hide_decorations)
1741                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1742    
1743          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1744          if (classhints != NULL)          if (classhints != NULL)
# Line 1387  ui_create_window(void) Line 1765  ui_create_window(void)
1765                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1766          }          }
1767    
1768          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;  
1769    
1770          if (g_IM != NULL)          if (g_IM != NULL)
1771          {          {
# Line 1482  xwin_toggle_fullscreen(void) Line 1850  xwin_toggle_fullscreen(void)
1850  {  {
1851          Pixmap contents = 0;          Pixmap contents = 0;
1852    
1853            if (g_seamless_active)
1854                    /* Turn off SeamlessRDP mode */
1855                    ui_seamless_toggle();
1856    
1857          if (!g_ownbackstore)          if (!g_ownbackstore)
1858          {          {
1859                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1570  handle_button_event(XEvent xevent, BOOL Line 1942  handle_button_event(XEvent xevent, BOOL
1942                  }                  }
1943          }          }
1944    
1945          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1946                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1947                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1948                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1949            }
1950            else
1951            {
1952                    /* SeamlessRDP */
1953                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1954                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1955            }
1956  }  }
1957    
1958    
1959  /* Process events in Xlib queue  /* Process events in Xlib queue
1960     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1961  static int  static int
# Line 1585  xwin_process_events(void) Line 1967  xwin_process_events(void)
1967          char str[256];          char str[256];
1968          Status status;          Status status;
1969          int events = 0;          int events = 0;
1970            seamless_window *sw;
1971    
1972          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1973          {          {
# Line 1599  xwin_process_events(void) Line 1982  xwin_process_events(void)
1982                  switch (xevent.type)                  switch (xevent.type)
1983                  {                  {
1984                          case VisibilityNotify:                          case VisibilityNotify:
1985                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1986                                            g_Unobscured =
1987                                                    xevent.xvisibility.state == VisibilityUnobscured;
1988    
1989                                  break;                                  break;
1990                          case ClientMessage:                          case ClientMessage:
1991                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1679  xwin_process_events(void) Line 2065  xwin_process_events(void)
2065                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
2066                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2067                                                         CurrentTime);                                                         CurrentTime);
2068                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
2069                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
2070                                    {
2071                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2072                                                           xevent.xmotion.x, xevent.xmotion.y);
2073                                    }
2074                                    else
2075                                    {
2076                                            /* SeamlessRDP */
2077                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2078                                                           xevent.xmotion.x_root,
2079                                                           xevent.xmotion.y_root);
2080                                    }
2081                                  break;                                  break;
2082    
2083                          case FocusIn:                          case FocusIn:
# Line 1691  xwin_process_events(void) Line 2088  xwin_process_events(void)
2088                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2089                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2090                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2091    
2092                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2093                                    if (!sw)
2094                                            break;
2095    
2096                                    if (sw->id != g_seamless_focused)
2097                                    {
2098                                            seamless_send_focus(sw->id, 0);
2099                                            g_seamless_focused = sw->id;
2100                                    }
2101                                  break;                                  break;
2102    
2103                          case FocusOut:                          case FocusOut:
# Line 1723  xwin_process_events(void) Line 2130  xwin_process_events(void)
2130                                  break;                                  break;
2131    
2132                          case Expose:                          case Expose:
2133                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2134                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2135                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2136                                            xevent.xexpose.height,                                                    g_gc,
2137                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2138                                                      xevent.xexpose.width, xevent.xexpose.height,
2139                                                      xevent.xexpose.x, xevent.xexpose.y);
2140                                    }
2141                                    else
2142                                    {
2143                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2144                                            if (!sw)
2145                                                    break;
2146                                            XCopyArea(g_display, g_backstore,
2147                                                      xevent.xexpose.window, g_gc,
2148                                                      xevent.xexpose.x + sw->xoffset,
2149                                                      xevent.xexpose.y + sw->yoffset,
2150                                                      xevent.xexpose.width,
2151                                                      xevent.xexpose.height, xevent.xexpose.x,
2152                                                      xevent.xexpose.y);
2153                                    }
2154    
2155                                  break;                                  break;
2156    
2157                          case MappingNotify:                          case MappingNotify:
# Line 1756  xwin_process_events(void) Line 2180  xwin_process_events(void)
2180                                  break;                                  break;
2181                          case PropertyNotify:                          case PropertyNotify:
2182                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2183                                    if (xevent.xproperty.window == g_wnd)
2184                                            break;
2185                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2186                                            break;
2187    
2188                                    /* seamless */
2189                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2190                                    if (!sw)
2191                                            break;
2192    
2193                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2194                                        && (xevent.xproperty.state == PropertyNewValue))
2195                                    {
2196                                            sw->state = ewmh_get_window_state(sw->wnd);
2197                                            seamless_send_state(sw->id, sw->state, 0);
2198                                    }
2199    
2200                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2201                                        && (xevent.xproperty.state == PropertyNewValue))
2202                                    {
2203                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2204                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2205                                    }
2206    
2207                                  break;                                  break;
2208                          case MapNotify:                          case MapNotify:
2209                                  rdp_send_client_window_status(1);                                  if (!g_seamless_active)
2210                                            rdp_send_client_window_status(1);
2211                                  break;                                  break;
2212                          case UnmapNotify:                          case UnmapNotify:
2213                                  rdp_send_client_window_status(0);                                  if (!g_seamless_active)
2214                                            rdp_send_client_window_status(0);
2215                                    break;
2216                            case ConfigureNotify:
2217                                    if (!g_seamless_active)
2218                                            break;
2219    
2220                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2221                                    if (!sw)
2222                                            break;
2223    
2224                                    gettimeofday(sw->position_timer, NULL);
2225                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2226                                        1000000)
2227                                    {
2228                                            sw->position_timer->tv_usec +=
2229                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2230                                            sw->position_timer->tv_sec += 1;
2231                                    }
2232                                    else
2233                                    {
2234                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2235                                    }
2236    
2237                                    sw_handle_restack(sw);
2238                                  break;                                  break;
2239                  }                  }
2240          }          }
# Line 1786  ui_select(int rdp_socket) Line 2259  ui_select(int rdp_socket)
2259                          /* User quit */                          /* User quit */
2260                          return 0;                          return 0;
2261    
2262                    if (g_seamless_active)
2263                            sw_check_timers();
2264    
2265                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2266                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2267                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
# Line 1805  ui_select(int rdp_socket) Line 2281  ui_select(int rdp_socket)
2281    
2282                  /* add redirection handles */                  /* add redirection handles */
2283                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2284                    seamless_select_timeout(&tv);
2285    
2286                  n++;                  n++;
2287    
# Line 1898  ui_paint_bitmap(int x, int y, int cx, in Line 2375  ui_paint_bitmap(int x, int y, int cx, in
2375          {          {
2376                  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);
2377                  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);
2378                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2379                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2380                                             x - sw->xoffset, y - sw->yoffset));
2381          }          }
2382          else          else
2383          {          {
2384                  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);
2385                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2386                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2387                                             x - sw->xoffset, y - sw->yoffset));
2388          }          }
2389    
2390          XFree(image);          XFree(image);
# Line 2022  ui_set_cursor(HCURSOR cursor) Line 2505  ui_set_cursor(HCURSOR cursor)
2505  {  {
2506          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2507          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2508            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2509  }  }
2510    
2511  void  void
# Line 2163  ui_set_colourmap(HCOLOURMAP map) Line 2647  ui_set_colourmap(HCOLOURMAP map)
2647                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2648          }          }
2649          else          else
2650            {
2651                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2652                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2653            }
2654  }  }
2655    
2656  void  void
2657  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2658  {  {
2659          XRectangle rect;          g_clip_rectangle.x = x;
2660            g_clip_rectangle.y = y;
2661          rect.x = x;          g_clip_rectangle.width = cx;
2662          rect.y = y;          g_clip_rectangle.height = cy;
2663          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);  
2664  }  }
2665    
2666  void  void
2667  ui_reset_clip(void)  ui_reset_clip(void)
2668  {  {
2669          XRectangle rect;          g_clip_rectangle.x = 0;
2670            g_clip_rectangle.y = 0;
2671          rect.x = 0;          g_clip_rectangle.width = g_width;
2672          rect.y = 0;          g_clip_rectangle.height = g_height;
2673          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);  
2674  }  }
2675    
2676  void  void
# Line 2268  ui_patblt(uint8 opcode, Line 2751  ui_patblt(uint8 opcode,
2751    
2752          if (g_ownbackstore)          if (g_ownbackstore)
2753                  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);
2754            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2755                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2756                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2757  }  }
2758    
2759  void  void
# Line 2278  ui_screenblt(uint8 opcode, Line 2764  ui_screenblt(uint8 opcode,
2764          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2765          if (g_ownbackstore)          if (g_ownbackstore)
2766          {          {
2767                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2768                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2769                          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);  
                 }  
2770          }          }
2771          else          else
2772          {          {
2773                  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);
2774          }          }
2775    
2776            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2777                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2778                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2779    
2780          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2781  }  }
2782    
# Line 2305  ui_memblt(uint8 opcode, Line 2787  ui_memblt(uint8 opcode,
2787  {  {
2788          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2789          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);
2790            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2791                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2792                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2793          if (g_ownbackstore)          if (g_ownbackstore)
2794                  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);
2795          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2351  ui_line(uint8 opcode, Line 2836  ui_line(uint8 opcode,
2836          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2837          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2838          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2839            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2840                                                startx - sw->xoffset, starty - sw->yoffset,
2841                                                endx - sw->xoffset, endy - sw->yoffset));
2842          if (g_ownbackstore)          if (g_ownbackstore)
2843                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2844          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2448  ui_polyline(uint8 opcode, Line 2936  ui_polyline(uint8 opcode,
2936          if (g_ownbackstore)          if (g_ownbackstore)
2937                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2938                             CoordModePrevious);                             CoordModePrevious);
2939    
2940            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2941                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2942    
2943          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2944  }  }
2945    
# Line 2668  ui_draw_text(uint8 font, uint8 flags, ui Line 3160  ui_draw_text(uint8 font, uint8 flags, ui
3160          if (g_ownbackstore)          if (g_ownbackstore)
3161          {          {
3162                  if (boxcx > 1)                  if (boxcx > 1)
3163                    {
3164                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3165                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3166                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3167                                                    (g_display, g_backstore, sw->wnd, g_gc,
3168                                                     boxx, boxy,
3169                                                     boxcx, boxcy,
3170                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3171                    }
3172                  else                  else
3173                    {
3174                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3175                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3176                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3177                                                    (g_display, g_backstore, sw->wnd, g_gc,
3178                                                     clipx, clipy,
3179                                                     clipcx, clipcy, clipx - sw->xoffset,
3180                                                     clipy - sw->yoffset));
3181                    }
3182          }          }
3183  }  }
3184    
# Line 2718  ui_desktop_restore(uint32 offset, int x, Line 3224  ui_desktop_restore(uint32 offset, int x,
3224          {          {
3225                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
3226                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
3227                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3228                                            (g_display, g_backstore, sw->wnd, g_gc,
3229                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3230          }          }
3231          else          else
3232          {          {
3233                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
3234                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3235                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3236                                             x - sw->xoffset, y - sw->yoffset));
3237          }          }
3238    
3239          XFree(image);          XFree(image);
# Line 2737  void Line 3249  void
3249  ui_end_update(void)  ui_end_update(void)
3250  {  {
3251  }  }
3252    
3253    
3254    void
3255    ui_seamless_begin(BOOL hidden)
3256    {
3257            if (!g_seamless_rdp)
3258                    return;
3259    
3260            if (g_seamless_started)
3261                    return;
3262    
3263            g_seamless_started = True;
3264            g_seamless_hidden = hidden;
3265    
3266            if (!hidden)
3267                    ui_seamless_toggle();
3268    }
3269    
3270    
3271    void
3272    ui_seamless_hide_desktop()
3273    {
3274            if (!g_seamless_rdp)
3275                    return;
3276    
3277            if (!g_seamless_started)
3278                    return;
3279    
3280            if (g_seamless_active)
3281                    ui_seamless_toggle();
3282    
3283            g_seamless_hidden = True;
3284    }
3285    
3286    
3287    void
3288    ui_seamless_unhide_desktop()
3289    {
3290            if (!g_seamless_rdp)
3291                    return;
3292    
3293            if (!g_seamless_started)
3294                    return;
3295    
3296            g_seamless_hidden = False;
3297    
3298            ui_seamless_toggle();
3299    }
3300    
3301    
3302    void
3303    ui_seamless_toggle()
3304    {
3305            if (!g_seamless_rdp)
3306                    return;
3307    
3308            if (!g_seamless_started)
3309                    return;
3310    
3311            if (g_seamless_hidden)
3312                    return;
3313    
3314            if (g_seamless_active)
3315            {
3316                    /* Deactivate */
3317                    while (g_seamless_windows)
3318                    {
3319                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3320                            sw_remove_window(g_seamless_windows);
3321                    }
3322                    XMapWindow(g_display, g_wnd);
3323            }
3324            else
3325            {
3326                    /* Activate */
3327                    XUnmapWindow(g_display, g_wnd);
3328                    seamless_send_sync();
3329            }
3330    
3331            g_seamless_active = !g_seamless_active;
3332    }
3333    
3334    
3335    void
3336    ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3337                              unsigned long flags)
3338    {
3339            Window wnd;
3340            XSetWindowAttributes attribs;
3341            XClassHint *classhints;
3342            XSizeHints *sizehints;
3343            XWMHints *wmhints;
3344            long input_mask;
3345            seamless_window *sw, *sw_parent;
3346    
3347            if (!g_seamless_active)
3348                    return;
3349    
3350            /* Ignore CREATEs for existing windows */
3351            sw = sw_get_window_by_id(id);
3352            if (sw)
3353                    return;
3354    
3355            get_window_attribs(&attribs);
3356            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3357                                InputOutput, g_visual,
3358                                CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3359    
3360            XStoreName(g_display, wnd, "SeamlessRDP");
3361            ewmh_set_wm_name(wnd, "SeamlessRDP");
3362    
3363            mwm_hide_decorations(wnd);
3364    
3365            classhints = XAllocClassHint();
3366            if (classhints != NULL)
3367            {
3368                    classhints->res_name = "rdesktop";
3369                    classhints->res_class = "SeamlessRDP";
3370                    XSetClassHint(g_display, wnd, classhints);
3371                    XFree(classhints);
3372            }
3373    
3374            /* WM_NORMAL_HINTS */
3375            sizehints = XAllocSizeHints();
3376            if (sizehints != NULL)
3377            {
3378                    sizehints->flags = USPosition;
3379                    XSetWMNormalHints(g_display, wnd, sizehints);
3380                    XFree(sizehints);
3381            }
3382    
3383            /* Parent-less transient windows */
3384            if (parent == 0xFFFFFFFF)
3385            {
3386                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3387                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3388                       using some other hints. */
3389                    ewmh_set_window_popup(wnd);
3390            }
3391            /* Normal transient windows */
3392            else if (parent != 0x00000000)
3393            {
3394                    sw_parent = sw_get_window_by_id(parent);
3395                    if (sw_parent)
3396                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3397                    else
3398                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3399            }
3400    
3401            if (flags & SEAMLESSRDP_CREATE_MODAL)
3402            {
3403                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3404                       somewhat at least */
3405                    if (parent == 0x00000000)
3406                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3407                    ewmh_set_window_modal(wnd);
3408            }
3409    
3410            /* FIXME: Support for Input Context:s */
3411    
3412            get_input_mask(&input_mask);
3413            input_mask |= PropertyChangeMask;
3414    
3415            XSelectInput(g_display, wnd, input_mask);
3416    
3417            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3418               seamless window, we could try to close the window on the
3419               serverside, instead of terminating rdesktop */
3420            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3421    
3422            sw = xmalloc(sizeof(seamless_window));
3423            sw->wnd = wnd;
3424            sw->id = id;
3425            sw->behind = 0;
3426            sw->group = sw_find_group(group, False);
3427            sw->group->refcnt++;
3428            sw->xoffset = 0;
3429            sw->yoffset = 0;
3430            sw->width = 0;
3431            sw->height = 0;
3432            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3433            sw->desktop = 0;
3434            sw->position_timer = xmalloc(sizeof(struct timeval));
3435            timerclear(sw->position_timer);
3436    
3437            sw->outstanding_position = False;
3438            sw->outpos_serial = 0;
3439            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3440            sw->outpos_width = sw->outpos_height = 0;
3441    
3442            sw->next = g_seamless_windows;
3443            g_seamless_windows = sw;
3444    
3445            /* WM_HINTS */
3446            wmhints = XAllocWMHints();
3447            if (wmhints)
3448            {
3449                    wmhints->flags = WindowGroupHint;
3450                    wmhints->window_group = sw->group->wnd;
3451                    XSetWMHints(g_display, sw->wnd, wmhints);
3452                    XFree(wmhints);
3453            }
3454    }
3455    
3456    
3457    void
3458    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3459    {
3460            seamless_window *sw;
3461    
3462            if (!g_seamless_active)
3463                    return;
3464    
3465            sw = sw_get_window_by_id(id);
3466            if (!sw)
3467            {
3468                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3469                    return;
3470            }
3471    
3472            XDestroyWindow(g_display, sw->wnd);
3473            sw_remove_window(sw);
3474    }
3475    
3476    
3477    void
3478    ui_seamless_destroy_group(unsigned long id, unsigned long flags)
3479    {
3480            seamless_window *sw, *sw_next;
3481    
3482            if (!g_seamless_active)
3483                    return;
3484    
3485            for (sw = g_seamless_windows; sw; sw = sw_next)
3486            {
3487                    sw_next = sw->next;
3488    
3489                    if (sw->group->id == id)
3490                    {
3491                            XDestroyWindow(g_display, sw->wnd);
3492                            sw_remove_window(sw);
3493                    }
3494            }
3495    }
3496    
3497    
3498    void
3499    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3500    {
3501            seamless_window *sw;
3502    
3503            if (!g_seamless_active)
3504                    return;
3505    
3506            sw = sw_get_window_by_id(id);
3507            if (!sw)
3508            {
3509                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3510                    return;
3511            }
3512    
3513            /* We ignore server updates until it has handled our request. */
3514            if (sw->outstanding_position)
3515                    return;
3516    
3517            if (!width || !height)
3518                    /* X11 windows must be at least 1x1 */
3519                    return;
3520    
3521            sw->xoffset = x;
3522            sw->yoffset = y;
3523            sw->width = width;
3524            sw->height = height;
3525    
3526            /* If we move the window in a maximized state, then KDE won't
3527               accept restoration */
3528            switch (sw->state)
3529            {
3530                    case SEAMLESSRDP_MINIMIZED:
3531                    case SEAMLESSRDP_MAXIMIZED:
3532                            return;
3533            }
3534    
3535            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3536            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3537    }
3538    
3539    
3540    void
3541    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3542    {
3543            seamless_window *sw;
3544    
3545            if (!g_seamless_active)
3546                    return;
3547    
3548            sw = sw_get_window_by_id(id);
3549            if (!sw)
3550            {
3551                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3552                    return;
3553            }
3554    
3555            if (behind)
3556            {
3557                    seamless_window *sw_behind;
3558                    Window wnds[2];
3559    
3560                    sw_behind = sw_get_window_by_id(behind);
3561                    if (!sw_behind)
3562                    {
3563                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3564                                    behind);
3565                            return;
3566                    }
3567    
3568                    wnds[1] = sw_behind->wnd;
3569                    wnds[0] = sw->wnd;
3570    
3571                    XRestackWindows(g_display, wnds, 2);
3572            }
3573            else
3574            {
3575                    XRaiseWindow(g_display, sw->wnd);
3576            }
3577    
3578            sw_restack_window(sw, behind);
3579    }
3580    
3581    
3582    void
3583    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3584    {
3585            seamless_window *sw;
3586    
3587            if (!g_seamless_active)
3588                    return;
3589    
3590            sw = sw_get_window_by_id(id);
3591            if (!sw)
3592            {
3593                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3594                    return;
3595            }
3596    
3597            /* FIXME: Might want to convert the name for non-EWMH WMs */
3598            XStoreName(g_display, sw->wnd, title);
3599            ewmh_set_wm_name(sw->wnd, title);
3600    }
3601    
3602    
3603    void
3604    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3605    {
3606            seamless_window *sw;
3607    
3608            if (!g_seamless_active)
3609                    return;
3610    
3611            sw = sw_get_window_by_id(id);
3612            if (!sw)
3613            {
3614                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3615                    return;
3616            }
3617    
3618            switch (state)
3619            {
3620                    case SEAMLESSRDP_NORMAL:
3621                    case SEAMLESSRDP_MAXIMIZED:
3622                            ewmh_change_state(sw->wnd, state);
3623                            XMapWindow(g_display, sw->wnd);
3624                            break;
3625                    case SEAMLESSRDP_MINIMIZED:
3626                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3627                               the Window Manager should probably just ignore the request, since
3628                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3629                               such as minimization, rather than an independent state." Besides,
3630                               XIconifyWindow is easier. */
3631                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3632                            {
3633                                    XWMHints *hints;
3634                                    hints = XGetWMHints(g_display, sw->wnd);
3635                                    if (hints)
3636                                    {
3637                                            hints->flags |= StateHint;
3638                                            hints->initial_state = IconicState;
3639                                            XSetWMHints(g_display, sw->wnd, hints);
3640                                            XFree(hints);
3641                                    }
3642                                    XMapWindow(g_display, sw->wnd);
3643                            }
3644                            else
3645                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3646                            break;
3647                    default:
3648                            warning("SeamlessRDP: Invalid state %d\n", state);
3649                            break;
3650            }
3651    
3652            sw->state = state;
3653    }
3654    
3655    
3656    void
3657    ui_seamless_syncbegin(unsigned long flags)
3658    {
3659            if (!g_seamless_active)
3660                    return;
3661    
3662            /* Destroy all seamless windows */
3663            while (g_seamless_windows)
3664            {
3665                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3666                    sw_remove_window(g_seamless_windows);
3667            }
3668    }
3669    
3670    
3671    void
3672    ui_seamless_ack(unsigned int serial)
3673    {
3674            seamless_window *sw;
3675            for (sw = g_seamless_windows; sw; sw = sw->next)
3676            {
3677                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3678                    {
3679                            sw->xoffset = sw->outpos_xoffset;
3680                            sw->yoffset = sw->outpos_yoffset;
3681                            sw->width = sw->outpos_width;
3682                            sw->height = sw->outpos_height;
3683                            sw->outstanding_position = False;
3684    
3685                            /* Do a complete redraw of the window as part of the
3686                               completion of the move. This is to remove any
3687                               artifacts caused by our lack of synchronization. */
3688                            XCopyArea(g_display, g_backstore,
3689                                      sw->wnd, g_gc,
3690                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3691    
3692                            break;
3693                    }
3694            }
3695    }

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

  ViewVC Help
Powered by ViewVC 1.1.26