/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

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

sourceforge.net/trunk/rdesktop/xwin.c revision 695 by stargo, Tue May 11 07:34:03 2004 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1183 by ossman_, Wed Mar 22 09:49:21 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2002     Copyright (C) Matthew Chapman 1999-2005
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 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;
37    extern int g_ypos;
38    extern int g_pos;
39  extern BOOL g_sendmotion;  extern BOOL g_sendmotion;
40  extern BOOL g_fullscreen;  extern BOOL g_fullscreen;
41  extern BOOL g_grab_keyboard;  extern BOOL g_grab_keyboard;
42  extern BOOL g_hide_decorations;  extern BOOL g_hide_decorations;
43  extern char g_title[];  extern char g_title[];
44  extern int g_server_bpp;  /* Color depth of the RDP session.
45       As of RDP 5.1, it may be 8, 15, 16 or 24. */
46    extern int g_server_depth;
47  extern int g_win_button_size;  extern int g_win_button_size;
48    
49  Display *g_display;  Display *g_display;
# Line 43  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    extern BOOL g_seamless_rdp;
86    
87  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
88  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
89  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
90  static GC g_gc = NULL;  static GC g_gc = NULL;
91    static GC g_create_bitmap_gc = NULL;
92    static GC g_create_glyph_gc = NULL;
93    static XRectangle g_clip_rectangle;
94  static Visual *g_visual;  static Visual *g_visual;
95    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
96       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
97       as far as we're concerned. */
98  static int g_depth;  static int g_depth;
99    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
100       This may be larger than g_depth, in which case some of the bits would
101       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
102  static int g_bpp;  static int g_bpp;
103  static XIM g_IM;  static XIM g_IM;
104  static XIC g_IC;  static XIC g_IC;
# Line 56  static XModifierKeymap *g_mod_map; Line 106  static XModifierKeymap *g_mod_map;
106  static Cursor g_current_cursor;  static Cursor g_current_cursor;
107  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
108  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
109    extern Atom g_net_wm_state_atom;
110    extern Atom g_net_wm_desktop_atom;
111  static BOOL g_focused;  static BOOL g_focused;
112  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
113  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* Indicates that:
114       1) visual has 15, 16 or 24 depth and the same color channel masks
115          as its RDP equivalent (implies X server is LE),
116       2) host is LE
117       This will trigger an optimization whose real value is questionable.
118    */
119    static BOOL g_compatible_arch;
120    /* Indicates whether RDP's bitmaps and our XImages have the same
121       binary format. If so, we can avoid an expensive translation.
122       Note that this can be true when g_compatible_arch is false,
123       e.g.:
124      
125         RDP(LE) <-> host(BE) <-> X-Server(LE)
126        
127       ('host' is the machine running rdesktop; the host simply memcpy's
128        so its endianess doesn't matter)
129     */
130    static BOOL g_no_translate_image = False;
131    
132  /* endianness */  /* endianness */
133  static BOOL g_host_be;  static BOOL g_host_be;
# Line 74  static Pixmap g_backstore = 0; Line 143  static Pixmap g_backstore = 0;
143  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
144  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
145  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
146    static BOOL g_using_full_workarea = False;
147    
148  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
149  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 86  extern BOOL g_rdpsnd; Line 156  extern BOOL g_rdpsnd;
156  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
157  typedef struct  typedef struct
158  {  {
159          uint32 flags;          unsigned long flags;
160          uint32 functions;          unsigned long functions;
161          uint32 decorations;          unsigned long decorations;
162          sint32 inputMode;          long inputMode;
163          uint32 status;          unsigned long status;
164  }  }
165  PropMotifWmHints;  PropMotifWmHints;
166    
# Line 102  typedef struct Line 172  typedef struct
172  }  }
173  PixelColour;  PixelColour;
174    
175    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
176            do { \
177                    seamless_window *sw; \
178                    XRectangle rect; \
179                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
180                        rect.x = g_clip_rectangle.x - sw->xoffset; \
181                        rect.y = g_clip_rectangle.y - sw->yoffset; \
182                        rect.width = g_clip_rectangle.width; \
183                        rect.height = g_clip_rectangle.height; \
184                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
185                        func args; \
186                    } \
187                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
188            } while (0)
189    
190    static void
191    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
192    {
193            points[0].x -= xoffset;
194            points[0].y -= yoffset;
195            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
196            points[0].x += xoffset;
197            points[0].y += yoffset;
198    }
199    
200    static void
201    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
202    {
203            points[0].x -= xoffset;
204            points[0].y -= yoffset;
205            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
206            points[0].x += xoffset;
207            points[0].y += yoffset;
208    }
209    
210  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
211  { \  { \
212          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
213            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
214          if (g_ownbackstore) \          if (g_ownbackstore) \
215                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
216  }  }
# Line 115  PixelColour; Line 220  PixelColour;
220          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
221  }  }
222    
223    #define FILL_POLYGON(p,np)\
224    { \
225            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
226            if (g_ownbackstore) \
227                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
228            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
229    }
230    
231    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
232    { \
233            switch (m) \
234            { \
235                    case 0: /* Outline */ \
236                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
237                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
238                            if (g_ownbackstore) \
239                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
240                            break; \
241                    case 1: /* Filled */ \
242                            XFillArc(g_display, g_wnd, g_gc, x, y, \
243                                     cx, cy, 0, 360*64); \
244                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc, x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \
245                            if (g_ownbackstore) \
246                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
247                            break; \
248            } \
249    }
250    
251  /* colour maps */  /* colour maps */
252  extern BOOL g_owncolmap;  extern BOOL g_owncolmap;
253  static Colormap g_xcolmap;  static Colormap g_xcolmap;
254  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
255    
256  #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
257  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
258  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
259    
# Line 146  static int rop2_map[] = { Line 279  static int rop2_map[] = {
279  #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]); }
280  #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); }
281    
282    static seamless_window *
283    sw_get_window_by_id(unsigned long id)
284    {
285            seamless_window *sw;
286            for (sw = g_seamless_windows; sw; sw = sw->next)
287            {
288                    if (sw->id == id)
289                            return sw;
290            }
291            return NULL;
292    }
293    
294    
295    static seamless_window *
296    sw_get_window_by_wnd(Window wnd)
297    {
298            seamless_window *sw;
299            for (sw = g_seamless_windows; sw; sw = sw->next)
300            {
301                    if (sw->wnd == wnd)
302                            return sw;
303            }
304            return NULL;
305    }
306    
307    
308    static void
309    sw_remove_window(seamless_window * win)
310    {
311            seamless_window *sw, **prevnext = &g_seamless_windows;
312            for (sw = g_seamless_windows; sw; sw = sw->next)
313            {
314                    if (sw == win)
315                    {
316                            *prevnext = sw->next;
317                            sw->group->refcnt--;
318                            if (sw->group->refcnt == 0)
319                            {
320                                    XDestroyWindow(g_display, sw->group->wnd);
321                                    xfree(sw->group);
322                            }
323                            xfree(sw->position_timer);
324                            xfree(sw);
325                            return;
326                    }
327                    prevnext = &sw->next;
328            }
329            return;
330    }
331    
332    
333    /* Move all windows except wnd to new desktop */
334    static void
335    sw_all_to_desktop(Window wnd, unsigned int desktop)
336    {
337            seamless_window *sw;
338            for (sw = g_seamless_windows; sw; sw = sw->next)
339            {
340                    if (sw->wnd == wnd)
341                            continue;
342                    if (sw->desktop != desktop)
343                    {
344                            ewmh_move_to_desktop(sw->wnd, desktop);
345                            sw->desktop = desktop;
346                    }
347            }
348    }
349    
350    
351    /* Send our position */
352    static void
353    sw_update_position(seamless_window * sw)
354    {
355            XWindowAttributes wa;
356            int x, y;
357            Window child_return;
358            unsigned int serial;
359    
360            XGetWindowAttributes(g_display, sw->wnd, &wa);
361            XTranslateCoordinates(g_display, sw->wnd, wa.root,
362                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
363    
364            serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
365    
366            sw->outstanding_position = True;
367            sw->outpos_serial = serial;
368    
369            sw->outpos_xoffset = x;
370            sw->outpos_yoffset = y;
371            sw->outpos_width = wa.width;
372            sw->outpos_height = wa.height;
373    }
374    
375    
376    /* Check if it's time to send our position */
377    static void
378    sw_check_timers()
379    {
380            seamless_window *sw;
381            struct timeval now;
382    
383            gettimeofday(&now, NULL);
384            for (sw = g_seamless_windows; sw; sw = sw->next)
385            {
386                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
387                    {
388                            timerclear(sw->position_timer);
389                            sw_update_position(sw);
390                    }
391            }
392    }
393    
394    
395    static void
396    sw_restack_window(seamless_window * sw, unsigned long behind)
397    {
398            seamless_window *sw_above;
399    
400            /* Remove window from stack */
401            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
402            {
403                    if (sw_above->behind == sw->id)
404                            break;
405            }
406    
407            if (sw_above)
408                    sw_above->behind = sw->behind;
409    
410            /* And then add it at the new position */
411    
412            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
413            {
414                    if (sw_above->behind == behind)
415                            break;
416            }
417    
418            if (sw_above)
419                    sw_above->behind = sw->id;
420    
421            sw->behind = behind;
422    }
423    
424    
425    static void
426    sw_handle_restack(seamless_window * sw)
427    {
428            Status status;
429            Window root, parent, *children;
430            unsigned int nchildren, i;
431            seamless_window *sw_below;
432    
433            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
434                                &root, &parent, &children, &nchildren);
435            if (!status || !nchildren)
436                    return;
437    
438            sw_below = NULL;
439    
440            i = 0;
441            while (children[i] != sw->wnd)
442            {
443                    i++;
444                    if (i >= nchildren)
445                            goto end;
446            }
447    
448            for (i++; i < nchildren; i++)
449            {
450                    sw_below = sw_get_window_by_wnd(children[i]);
451                    if (sw_below)
452                            break;
453            }
454    
455            if (!sw_below && !sw->behind)
456                    goto end;
457            if (sw_below && (sw_below->id == sw->behind))
458                    goto end;
459    
460            if (sw_below)
461            {
462                    seamless_send_zchange(sw->id, sw_below->id, 0);
463                    sw_restack_window(sw, sw_below->id);
464            }
465            else
466            {
467                    seamless_send_zchange(sw->id, 0, 0);
468                    sw_restack_window(sw, 0);
469            }
470    
471          end:
472            XFree(children);
473    }
474    
475    
476    static seamless_group *
477    sw_find_group(unsigned long id, BOOL dont_create)
478    {
479            seamless_window *sw;
480            seamless_group *sg;
481            XSetWindowAttributes attribs;
482    
483            for (sw = g_seamless_windows; sw; sw = sw->next)
484            {
485                    if (sw->group->id == id)
486                            return sw->group;
487            }
488    
489            if (dont_create)
490                    return NULL;
491    
492            sg = xmalloc(sizeof(seamless_group));
493    
494            sg->wnd =
495                    XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0,
496                                  CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
497    
498            sg->id = id;
499            sg->refcnt = 0;
500    
501            return sg;
502    }
503    
504    
505  static void  static void
506  mwm_hide_decorations(void)  mwm_hide_decorations(Window wnd)
507  {  {
508          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
509          Atom hintsatom;          Atom hintsatom;
# Line 164  mwm_hide_decorations(void) Line 520  mwm_hide_decorations(void)
520                  return;                  return;
521          }          }
522    
523          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
524                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
525    
526  }  }
527    
528  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
529  split_colour15(uint32 colour)  { \
530  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
531          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
532          rv.red = (colour & 0x7c00) >> 7;          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
         rv.green = (colour & 0x03e0) >> 2;  
         rv.blue = (colour & 0x001f) << 3;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = (colour & 0xf800) >> 8;  
         rv.green = (colour & 0x07e0) >> 3;  
         rv.blue = (colour & 0x001f) << 3;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour24(uint32 colour)  
 {  
         PixelColour rv;  
         rv.blue = (colour & 0xff0000) >> 16;  
         rv.green = (colour & 0x00ff00) >> 8;  
         rv.red = (colour & 0x0000ff);  
         return rv;  
533  }  }
534    
535  static uint32  #define SPLITCOLOUR16(colour, rv) \
536  make_colour(PixelColour pc)  { \
537  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
538          return (((pc.red >> g_red_shift_r) << g_red_shift_l)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
539                  | ((pc.green >> g_green_shift_r) << g_green_shift_l)          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
540                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));  } \
541    
542    #define SPLITCOLOUR24(colour, rv) \
543    { \
544            rv.blue = (colour & 0xff0000) >> 16; \
545            rv.green = (colour & 0x00ff00) >> 8; \
546            rv.red = (colour & 0x0000ff); \
547  }  }
548    
549    #define MAKECOLOUR(pc) \
550            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
551                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
552                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
553    
554  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
555  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
556  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
557                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
558    
559    /* The following macros output the same octet sequences
560       on both BE and LE hosts: */
561    
562    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
563    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
564    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
565    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
566    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
567    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
568    
569  static uint32  static uint32
570  translate_colour(uint32 colour)  translate_colour(uint32 colour)
571  {  {
572          PixelColour pc;          PixelColour pc;
573          switch (g_server_bpp)          switch (g_server_depth)
574          {          {
575                  case 15:                  case 15:
576                          pc = split_colour15(colour);                          SPLITCOLOUR15(colour, pc);
577                          break;                          break;
578                  case 16:                  case 16:
579                          pc = split_colour16(colour);                          SPLITCOLOUR16(colour, pc);
580                          break;                          break;
581                  case 24:                  case 24:
582                          pc = split_colour24(colour);                          SPLITCOLOUR24(colour, pc);
583                            break;
584                    default:
585                            /* Avoid warning */
586                            pc.red = 0;
587                            pc.green = 0;
588                            pc.blue = 0;
589                          break;                          break;
590          }          }
591          return make_colour(pc);          return MAKECOLOUR(pc);
592  }  }
593    
594    /* indent is confused by UNROLL8 */
595    /* *INDENT-OFF* */
596    
597    /* repeat and unroll, similar to bitmap.c */
598    /* potentialy any of the following translate */
599    /* functions can use repeat but just doing */
600    /* the most common ones */
601    
602  #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }  #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
603  #define REPEAT(stm) \  /* 2 byte output repeat */
604    #define REPEAT2(stm) \
605    { \
606            while (out <= end - 8 * 2) \
607                    UNROLL8(stm) \
608            while (out < end) \
609                    { stm } \
610    }
611    /* 3 byte output repeat */
612    #define REPEAT3(stm) \
613    { \
614            while (out <= end - 8 * 3) \
615                    UNROLL8(stm) \
616            while (out < end) \
617                    { stm } \
618    }
619    /* 4 byte output repeat */
620    #define REPEAT4(stm) \
621  { \  { \
622          while (out <= end - 8 * 4) \          while (out <= end - 8 * 4) \
623                  UNROLL8(stm) \                  UNROLL8(stm) \
624          while (out < end) \          while (out < end) \
625                  { stm } \                  { stm } \
626  }  }
627    /* *INDENT-ON* */
628    
629  static void  static void
630  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
631  {  {
632          while (out < end)          while (out < end)
633                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
634  }  }
635    
636  static void  static void
637  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
638  {  {
639          uint16 value;          uint16 value;
640    
641          if (g_arch_match)          if (g_compatible_arch)
642                  REPEAT(*((uint16*)out) = g_colmap[*(data++)]; out += 2;          {
643                    /* *INDENT-OFF* */
644                    REPEAT2
645                    (
646                            *((uint16 *) out) = g_colmap[*(data++)];
647                            out += 2;
648                  )                  )
649                    /* *INDENT-ON* */
650            }
651          else if (g_xserver_be)          else if (g_xserver_be)
652          {          {
653                  while (out < end)                  while (out < end)
654                  {                  {
655                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
656                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
657                  }                  }
658          }          }
659          else          else
# Line 268  translate8to16(uint8 * data, uint8 * out Line 661  translate8to16(uint8 * data, uint8 * out
661                  while (out < end)                  while (out < end)
662                  {                  {
663                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
664                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
665                  }                  }
666          }          }
667  }  }
668    
669  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
670  static void  static void
671  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
672  {  {
673          uint32 value;          uint32 value;
674    
675          if (g_xserver_be)          if (g_compatible_arch)
676          {          {
677                  while (out < end)                  while (out < end)
678                  {                  {
679                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
680                          *(out++) = value >> 16;                          BOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
681                  }                  }
682          }          }
683          else          else
# Line 295  translate8to24(uint8 * data, uint8 * out Line 685  translate8to24(uint8 * data, uint8 * out
685                  while (out < end)                  while (out < end)
686                  {                  {
687                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
688                          *(out++) = value;                          LOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
689                  }                  }
690          }          }
691  }  }
692    
693  static void  static void
694  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
695  {  {
696          uint32 value;          uint32 value;
697    
698          if (g_arch_match)          if (g_compatible_arch)
699                  REPEAT(*((uint32 *)out) = g_colmap[*(data++)]; out += 4;          {
700                    /* *INDENT-OFF* */
701                    REPEAT4
702                    (
703                            *((uint32 *) out) = g_colmap[*(data++)];
704                            out += 4;
705                  )                  )
706                    /* *INDENT-ON* */
707            }
708          else if (g_xserver_be)          else if (g_xserver_be)
709          {          {
710                  while (out < end)                  while (out < end)
711                  {                  {
712                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
713                          *(out++) = value >> 24;                          BOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 8;  
                         *(out++) = value;  
714                  }                  }
715          }          }
716          else          else
# Line 326  translate8to32(uint8 * data, uint8 * out Line 718  translate8to32(uint8 * data, uint8 * out
718                  while (out < end)                  while (out < end)
719                  {                  {
720                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
721                          *(out++) = value;                          LOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
722                  }                  }
723          }          }
724  }  }
725    
726  static void  static void
727  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
728  {  {
729          uint16 pixel;          uint16 pixel;
730          uint16 value;          uint16 value;
731            PixelColour pc;
732    
733          while (out < end)          if (g_xserver_be)
734          {          {
735                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel);  
                 }  
   
                 value = make_colour(split_colour15(pixel));  
   
                 if (g_xserver_be)  
736                  {                  {
737                          *(out++) = value >> 8;                          pixel = *(data++);
738                          *(out++) = value;                          if (g_host_be)
739                            {
740                                    BSWAP16(pixel);
741                            }
742                            SPLITCOLOUR15(pixel, pc);
743                            value = MAKECOLOUR(pc);
744                            BOUT16(out, value);
745                  }                  }
746                  else          }
747            else
748            {
749                    while (out < end)
750                  {                  {
751                          *(out++) = value;                          pixel = *(data++);
752                          *(out++) = value >> 8;                          if (g_host_be)
753                            {
754                                    BSWAP16(pixel);
755                            }
756                            SPLITCOLOUR15(pixel, pc);
757                            value = MAKECOLOUR(pc);
758                            LOUT16(out, value);
759                  }                  }
760          }          }
761  }  }
762    
763  static void  static void
764  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
765  {  {
766          uint32 value;          uint32 value;
767          uint16 pixel;          uint16 pixel;
768            PixelColour pc;
769    
770          while (out < end)          if (g_compatible_arch)
771          {          {
772                  pixel = *(data++);                  /* *INDENT-OFF* */
773                    REPEAT3
774                  if (g_host_be)                  (
775                  {                          pixel = *(data++);
776                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
777                  }                          *(out++) = pc.blue;
778                            *(out++) = pc.green;
779                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
780                  if (g_xserver_be)                  )
781                    /* *INDENT-ON* */
782            }
783            else if (g_xserver_be)
784            {
785                    while (out < end)
786                  {                  {
787                          *(out++) = value >> 16;                          pixel = *(data++);
788                          *(out++) = value >> 8;                          if (g_host_be)
789                          *(out++) = value;                          {
790                                    BSWAP16(pixel);
791                            }
792                            SPLITCOLOUR15(pixel, pc);
793                            value = MAKECOLOUR(pc);
794                            BOUT24(out, value);
795                  }                  }
796                  else          }
797            else
798            {
799                    while (out < end)
800                  {                  {
801                          *(out++) = value;                          pixel = *(data++);
802                          *(out++) = value >> 8;                          if (g_host_be)
803                          *(out++) = value >> 16;                          {
804                                    BSWAP16(pixel);
805                            }
806                            SPLITCOLOUR15(pixel, pc);
807                            value = MAKECOLOUR(pc);
808                            LOUT24(out, value);
809                  }                  }
810          }          }
811  }  }
812    
813  static void  static void
814  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
815  {  {
816          uint16 pixel;          uint16 pixel;
817          uint32 value;          uint32 value;
818            PixelColour pc;
819    
820          while (out < end)          if (g_compatible_arch)
821          {          {
822                  pixel = *(data++);                  /* *INDENT-OFF* */
823                    REPEAT4
824                  if (g_host_be)                  (
825                  {                          pixel = *(data++);
826                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
827                  }                          *(out++) = pc.blue;
828                            *(out++) = pc.green;
829                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
830                            *(out++) = 0;
831                  if (g_xserver_be)                  )
832                    /* *INDENT-ON* */
833            }
834            else if (g_xserver_be)
835            {
836                    while (out < end)
837                  {                  {
838                          *(out++) = value >> 24;                          pixel = *(data++);
839                          *(out++) = value >> 16;                          if (g_host_be)
840                          *(out++) = value >> 8;                          {
841                          *(out++) = value;                                  BSWAP16(pixel);
842                            }
843                            SPLITCOLOUR15(pixel, pc);
844                            value = MAKECOLOUR(pc);
845                            BOUT32(out, value);
846                  }                  }
847                  else          }
848            else
849            {
850                    while (out < end)
851                  {                  {
852                          *(out++) = value;                          pixel = *(data++);
853                          *(out++) = value >> 8;                          if (g_host_be)
854                          *(out++) = value >> 16;                          {
855                          *(out++) = value >> 24;                                  BSWAP16(pixel);
856                            }
857                            SPLITCOLOUR15(pixel, pc);
858                            value = MAKECOLOUR(pc);
859                            LOUT32(out, value);
860                  }                  }
861          }          }
862  }  }
863    
864  static void  static void
865  translate16to16(uint16 * data, uint8 * out, uint8 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
866  {  {
867          uint16 pixel;          uint16 pixel;
868          uint16 value;          uint16 value;
869            PixelColour pc;
870    
871          while (out < end)          if (g_xserver_be)
872          {          {
                 pixel = *(data++);  
   
873                  if (g_host_be)                  if (g_host_be)
874                  {                  {
875                          BSWAP16(pixel);                          while (out < end)
876                            {
877                                    pixel = *(data++);
878                                    BSWAP16(pixel);
879                                    SPLITCOLOUR16(pixel, pc);
880                                    value = MAKECOLOUR(pc);
881                                    BOUT16(out, value);
882                            }
883                  }                  }
884                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
885                  {                  {
886                          *(out++) = value >> 8;                          while (out < end)
887                          *(out++) = value;                          {
888                                    pixel = *(data++);
889                                    SPLITCOLOUR16(pixel, pc);
890                                    value = MAKECOLOUR(pc);
891                                    BOUT16(out, value);
892                            }
893                    }
894            }
895            else
896            {
897                    if (g_host_be)
898                    {
899                            while (out < end)
900                            {
901                                    pixel = *(data++);
902                                    BSWAP16(pixel);
903                                    SPLITCOLOUR16(pixel, pc);
904                                    value = MAKECOLOUR(pc);
905                                    LOUT16(out, value);
906                            }
907                  }                  }
908                  else                  else
909                  {                  {
910                          *(out++) = value;                          while (out < end)
911                          *(out++) = value >> 8;                          {
912                                    pixel = *(data++);
913                                    SPLITCOLOUR16(pixel, pc);
914                                    value = MAKECOLOUR(pc);
915                                    LOUT16(out, value);
916                            }
917                  }                  }
918          }          }
919  }  }
920    
921  static void  static void
922  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
923  {  {
924          uint32 value;          uint32 value;
925          uint16 pixel;          uint16 pixel;
926            PixelColour pc;
927    
928          while (out < end)          if (g_compatible_arch)
929            {
930                    /* *INDENT-OFF* */
931                    REPEAT3
932                    (
933                            pixel = *(data++);
934                            SPLITCOLOUR16(pixel, pc);
935                            *(out++) = pc.blue;
936                            *(out++) = pc.green;
937                            *(out++) = pc.red;
938                    )
939                    /* *INDENT-ON* */
940            }
941            else if (g_xserver_be)
942          {          {
                 pixel = *(data++);  
   
943                  if (g_host_be)                  if (g_host_be)
944                  {                  {
945                          BSWAP16(pixel);                          while (out < end)
946                            {
947                                    pixel = *(data++);
948                                    BSWAP16(pixel);
949                                    SPLITCOLOUR16(pixel, pc);
950                                    value = MAKECOLOUR(pc);
951                                    BOUT24(out, value);
952                            }
953                  }                  }
954                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
955                  {                  {
956                          *(out++) = value >> 16;                          while (out < end)
957                          *(out++) = value >> 8;                          {
958                          *(out++) = value;                                  pixel = *(data++);
959                                    SPLITCOLOUR16(pixel, pc);
960                                    value = MAKECOLOUR(pc);
961                                    BOUT24(out, value);
962                            }
963                    }
964            }
965            else
966            {
967                    if (g_host_be)
968                    {
969                            while (out < end)
970                            {
971                                    pixel = *(data++);
972                                    BSWAP16(pixel);
973                                    SPLITCOLOUR16(pixel, pc);
974                                    value = MAKECOLOUR(pc);
975                                    LOUT24(out, value);
976                            }
977                  }                  }
978                  else                  else
979                  {                  {
980                          *(out++) = value;                          while (out < end)
981                          *(out++) = value >> 8;                          {
982                          *(out++) = value >> 16;                                  pixel = *(data++);
983                                    SPLITCOLOUR16(pixel, pc);
984                                    value = MAKECOLOUR(pc);
985                                    LOUT24(out, value);
986                            }
987                  }                  }
988          }          }
989  }  }
990    
991  static void  static void
992  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
993  {  {
994          uint16 pixel;          uint16 pixel;
995          uint32 value;          uint32 value;
996            PixelColour pc;
997    
998          while (out < end)          if (g_compatible_arch)
999            {
1000                    /* *INDENT-OFF* */
1001                    REPEAT4
1002                    (
1003                            pixel = *(data++);
1004                            SPLITCOLOUR16(pixel, pc);
1005                            *(out++) = pc.blue;
1006                            *(out++) = pc.green;
1007                            *(out++) = pc.red;
1008                            *(out++) = 0;
1009                    )
1010                    /* *INDENT-ON* */
1011            }
1012            else if (g_xserver_be)
1013          {          {
                 pixel = *(data++);  
   
1014                  if (g_host_be)                  if (g_host_be)
1015                  {                  {
1016                          BSWAP16(pixel);                          while (out < end)
1017                            {
1018                                    pixel = *(data++);
1019                                    BSWAP16(pixel);
1020                                    SPLITCOLOUR16(pixel, pc);
1021                                    value = MAKECOLOUR(pc);
1022                                    BOUT32(out, value);
1023                            }
1024                  }                  }
1025                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
1026                  {                  {
1027                          *(out++) = value >> 24;                          while (out < end)
1028                          *(out++) = value >> 16;                          {
1029                          *(out++) = value >> 8;                                  pixel = *(data++);
1030                          *(out++) = value;                                  SPLITCOLOUR16(pixel, pc);
1031                                    value = MAKECOLOUR(pc);
1032                                    BOUT32(out, value);
1033                            }
1034                    }
1035            }
1036            else
1037            {
1038                    if (g_host_be)
1039                    {
1040                            while (out < end)
1041                            {
1042                                    pixel = *(data++);
1043                                    BSWAP16(pixel);
1044                                    SPLITCOLOUR16(pixel, pc);
1045                                    value = MAKECOLOUR(pc);
1046                                    LOUT32(out, value);
1047                            }
1048                  }                  }
1049                  else                  else
1050                  {                  {
1051                          *(out++) = value;                          while (out < end)
1052                          *(out++) = value >> 8;                          {
1053                          *(out++) = value >> 16;                                  pixel = *(data++);
1054                          *(out++) = value >> 24;                                  SPLITCOLOUR16(pixel, pc);
1055                                    value = MAKECOLOUR(pc);
1056                                    LOUT32(out, value);
1057                            }
1058                  }                  }
1059          }          }
1060  }  }
1061    
1062  static void  static void
1063  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
1064  {  {
1065          uint32 pixel = 0;          uint32 pixel = 0;
1066          uint16 value;          uint16 value;
1067            PixelColour pc;
1068    
1069          while (out < end)          while (out < end)
1070          {          {
1071                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
1072                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
1073                  pixel |= *(data++);                  pixel |= *(data++);
1074                    SPLITCOLOUR24(pixel, pc);
1075                  value = (uint16) make_colour(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
1076                  if (g_xserver_be)                  if (g_xserver_be)
1077                  {                  {
1078                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
1079                  }                  }
1080                  else                  else
1081                  {                  {
1082                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
1083                  }                  }
1084          }          }
1085  }  }
1086    
1087  static void  static void
1088  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
1089  {  {
1090          uint32 pixel;          uint32 pixel;
1091          uint32 value;          uint32 value;
1092            PixelColour pc;
1093    
1094          while (out < end)          if (g_xserver_be)
1095          {          {
1096                  pixel = *(data++) << 16;                  while (out < end)
                 pixel |= *(data++) << 8;  
                 pixel |= *(data++);  
   
                 value = make_colour(split_colour24(pixel));  
   
                 if (g_xserver_be)  
1097                  {                  {
1098                          *(out++) = value >> 16;                          pixel = *(data++) << 16;
1099                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
1100                          *(out++) = value;                          pixel |= *(data++);
1101                            SPLITCOLOUR24(pixel, pc);
1102                            value = MAKECOLOUR(pc);
1103                            BOUT24(out, value);
1104                  }                  }
1105                  else          }
1106            else
1107            {
1108                    while (out < end)
1109                  {                  {
1110                          *(out++) = value;                          pixel = *(data++) << 16;
1111                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
1112                          *(out++) = value >> 16;                          pixel |= *(data++);
1113                            SPLITCOLOUR24(pixel, pc);
1114                            value = MAKECOLOUR(pc);
1115                            LOUT24(out, value);
1116                  }                  }
1117          }          }
1118  }  }
1119    
1120  static void  static void
1121  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
1122  {  {
1123          uint32 pixel;          uint32 pixel;
1124          uint32 value;          uint32 value;
1125            PixelColour pc;
1126    
1127          while (out < end)          if (g_compatible_arch)
1128          {          {
1129                  pixel = *(data++) << 16;                  /* *INDENT-OFF* */
1130                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
1131                  pixel |= *(data++);                  REPEAT4
1132                    (
1133                  value = make_colour(split_colour24(pixel));                          *(out++) = *(data++);
1134                            *(out++) = *(data++);
1135                  if (g_xserver_be)                          *(out++) = *(data++);
1136                            *(out++) = 0;
1137                    )
1138    #else
1139                    REPEAT4
1140                    (
1141                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
1142                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
1143                     out += 4;
1144                     data += 3;
1145                    )
1146    #endif
1147                    /* *INDENT-ON* */
1148            }
1149            else if (g_xserver_be)
1150            {
1151                    while (out < end)
1152                  {                  {
1153                          *(out++) = value >> 24;                          pixel = *(data++) << 16;
1154                          *(out++) = value >> 16;                          pixel |= *(data++) << 8;
1155                          *(out++) = value >> 8;                          pixel |= *(data++);
1156                          *(out++) = value;                          SPLITCOLOUR24(pixel, pc);
1157                            value = MAKECOLOUR(pc);
1158                            BOUT32(out, value);
1159                  }                  }
1160                  else          }
1161            else
1162            {
1163                    while (out < end)
1164                  {                  {
1165                          *(out++) = value;                          pixel = *(data++) << 16;
1166                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
1167                          *(out++) = value >> 16;                          pixel |= *(data++);
1168                          *(out++) = value >> 24;                          SPLITCOLOUR24(pixel, pc);
1169                            value = MAKECOLOUR(pc);
1170                            LOUT32(out, value);
1171                  }                  }
1172          }          }
1173  }  }
# Line 618  translate_image(int width, int height, u Line 1179  translate_image(int width, int height, u
1179          uint8 *out;          uint8 *out;
1180          uint8 *end;          uint8 *end;
1181    
1182          /* if server and xserver bpp match, */          /*
1183          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
1184          /* just return data */             and arch(endian) matches, no need to translate:
1185          if (g_arch_match)             just return data.
1186               Note: select_visual should've already ensured g_no_translate
1187               is only set for compatible depths, but the RDP depth might've
1188               changed during connection negotiations.
1189             */
1190            if (g_no_translate_image)
1191          {          {
1192                  if (g_depth == 15 && g_server_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
1193                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
1194                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
1195                          return data;                          return data;
1196          }          }
1197    
# Line 633  translate_image(int width, int height, u Line 1199  translate_image(int width, int height, u
1199          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
1200          end = out + size;          end = out + size;
1201    
1202          switch (g_server_bpp)          switch (g_server_depth)
1203          {          {
1204                  case 24:                  case 24:
1205                          switch (g_bpp)                          switch (g_bpp)
# Line 731  calculate_shifts(uint32 mask, int *shift Line 1297  calculate_shifts(uint32 mask, int *shift
1297          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
1298  }  }
1299    
1300  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1301  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1302     */
1303    static unsigned
1304    calculate_mask_weight(uint32 mask)
1305    {
1306            unsigned weight = 0;
1307            do
1308            {
1309                    weight += (mask & 1);
1310            }
1311            while (mask >>= 1);
1312            return weight;
1313    }
1314    
1315    static BOOL
1316    select_visual()
1317  {  {
         XVisualInfo vi;  
1318          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1319          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1320          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1321          XVisualInfo template;          XVisualInfo template;
1322          Bool TrueColorVisual = False;          int i;
1323            unsigned red_weight, blue_weight, green_weight;
1324    
1325          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1326          if (g_display == NULL)  
1327            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1328            if (pfm == NULL)
1329          {          {
1330                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1331                    XCloseDisplay(g_display);
1332                  return False;                  return False;
1333          }          }
1334    
1335          screen_num = DefaultScreen(g_display);          /* Search for best TrueColor visual */
         g_x_socket = ConnectionNumber(g_display);  
         g_screen = ScreenOfDisplay(g_display, screen_num);  
         g_depth = DefaultDepthOfScreen(g_screen);  
   
         /* Search for best TrueColor depth */  
1336          template.class = TrueColor;          template.class = TrueColor;
1337          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1338            g_visual = NULL;
1339            g_no_translate_image = False;
1340            g_compatible_arch = False;
1341            if (vmatches != NULL)
1342            {
1343                    for (i = 0; i < visuals_count; ++i)
1344                    {
1345                            XVisualInfo *visual_info = &vmatches[i];
1346    
1347                            /* Try to find a no-translation visual that'll
1348                               allow us to use RDP bitmaps directly as ZPixmaps. */
1349                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1350                                                   /* R5G5B5 */
1351                                                   (visual_info->red_mask == 0x7c00) &&
1352                                                   (visual_info->green_mask == 0x3e0) &&
1353                                                   (visual_info->blue_mask == 0x1f)) ||
1354                                                  ((visual_info->depth == 16) &&
1355                                                   /* R5G6B5 */
1356                                                   (visual_info->red_mask == 0xf800) &&
1357                                                   (visual_info->green_mask == 0x7e0) &&
1358                                                   (visual_info->blue_mask == 0x1f)) ||
1359                                                  ((visual_info->depth == 24) &&
1360                                                   /* R8G8B8 */
1361                                                   (visual_info->red_mask == 0xff0000) &&
1362                                                   (visual_info->green_mask == 0xff00) &&
1363                                                   (visual_info->blue_mask == 0xff))))
1364                            {
1365                                    g_visual = visual_info->visual;
1366                                    g_depth = visual_info->depth;
1367                                    g_compatible_arch = !g_host_be;
1368                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1369                                    if (g_no_translate_image)
1370                                            /* We found the best visual */
1371                                            break;
1372                            }
1373                            else
1374                            {
1375                                    g_compatible_arch = False;
1376                            }
1377    
1378          nvisuals--;                          if (visual_info->depth > 24)
1379          while (nvisuals >= 0)                          {
1380          {                                  /* Avoid 32-bit visuals and likes like the plague.
1381                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1382                  {                                     (e.g. nvidia's Composite 32-bit visual).
1383                          g_depth = (vmatches + nvisuals)->depth;                                     Most implementation offer a 24-bit visual anyway. */
1384                                    continue;
1385                            }
1386    
1387                            /* Only care for visuals, for whose BPPs (not depths!)
1388                               we have a translateXtoY function. */
1389                            BOOL can_translate_to_bpp = False;
1390                            int j;
1391                            for (j = 0; j < pixmap_formats_count; ++j)
1392                            {
1393                                    if (pfm[j].depth == visual_info->depth)
1394                                    {
1395                                            if ((pfm[j].bits_per_pixel == 16) ||
1396                                                (pfm[j].bits_per_pixel == 24) ||
1397                                                (pfm[j].bits_per_pixel == 32))
1398                                            {
1399                                                    can_translate_to_bpp = True;
1400                                            }
1401                                            break;
1402                                    }
1403                            }
1404    
1405                            /* Prefer formats which have the most colour depth.
1406                               We're being truly aristocratic here, minding each
1407                               weight on its own. */
1408                            if (can_translate_to_bpp)
1409                            {
1410                                    unsigned vis_red_weight =
1411                                            calculate_mask_weight(visual_info->red_mask);
1412                                    unsigned vis_green_weight =
1413                                            calculate_mask_weight(visual_info->green_mask);
1414                                    unsigned vis_blue_weight =
1415                                            calculate_mask_weight(visual_info->blue_mask);
1416                                    if ((vis_red_weight >= red_weight)
1417                                        && (vis_green_weight >= green_weight)
1418                                        && (vis_blue_weight >= blue_weight))
1419                                    {
1420                                            red_weight = vis_red_weight;
1421                                            green_weight = vis_green_weight;
1422                                            blue_weight = vis_blue_weight;
1423                                            g_visual = visual_info->visual;
1424                                            g_depth = visual_info->depth;
1425                                    }
1426                            }
1427                  }                  }
1428                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1429          }          }
1430    
1431          test = 1;          if (g_visual != NULL)
         g_host_be = !(BOOL) (*(uint8 *) (&test));  
         g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);  
   
         if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))  
1432          {          {
1433                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1434                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1435                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1436                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
                 /* Do not allocate colours on a TrueColor visual */  
                 if (g_visual->class == TrueColor)  
                 {  
                         g_owncolmap = False;  
                 }  
1437          }          }
1438          else          else
1439          {          {
1440                  /* need a truecolour visual */                  template.class = PseudoColor;
1441                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1442                  {                  template.colormap_size = 256;
1443                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1444                            XGetVisualInfo(g_display,
1445                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1446                                           &template, &visuals_count);
1447                    if (vmatches == NULL)
1448                    {
1449                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1450                            XCloseDisplay(g_display);
1451                            XFree(pfm);
1452                          return False;                          return False;
1453                  }                  }
1454    
1455                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1456                  g_owncolmap = False;                  g_owncolmap = True;
1457                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1458                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
                 calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);  
   
                 /* if RGB video and averything is little endian */  
                 if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask)  
                         if (!g_xserver_be && !g_host_be)  
                                 g_arch_match = True;  
1459          }          }
1460    
1461          pfm = XListPixmapFormats(g_display, &i);          g_bpp = 0;
1462          if (pfm != NULL)          for (i = 0; i < pixmap_formats_count; ++i)
1463          {          {
1464                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1465                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1466                  {                  {
1467                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1468    
1469                            if (g_no_translate_image)
1470                          {                          {
1471                                  g_bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1472                                    {
1473                                            case 15:
1474                                            case 16:
1475                                                    if (g_bpp != 16)
1476                                                            g_no_translate_image = False;
1477                                                    break;
1478                                            case 24:
1479                                                    /* Yes, this will force image translation
1480                                                       on most modern servers which use 32 bits
1481                                                       for R8G8B8. */
1482                                                    if (g_bpp != 24)
1483                                                            g_no_translate_image = False;
1484                                                    break;
1485                                            default:
1486                                                    g_no_translate_image = False;
1487                                                    break;
1488                                    }
1489                          }                          }
1490    
1491                            /* Pixmap formats list is a depth-to-bpp mapping --
1492                               there's just a single entry for every depth,
1493                               so we can safely break here */
1494                            break;
1495                  }                  }
1496                  XFree(pfm);          }
1497            XFree(pfm);
1498            pfm = NULL;
1499            return True;
1500    }
1501    
1502    static XErrorHandler g_old_error_handler;
1503    
1504    static int
1505    error_handler(Display * dpy, XErrorEvent * eev)
1506    {
1507            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1508            {
1509                    fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1510                    fprintf(stderr,
1511                            "This is most likely caused by a broken window manager (commonly KWin).\n");
1512                    return 0;
1513            }
1514    
1515            return g_old_error_handler(dpy, eev);
1516    }
1517    
1518    BOOL
1519    ui_init(void)
1520    {
1521            int screen_num;
1522    
1523            g_display = XOpenDisplay(NULL);
1524            if (g_display == NULL)
1525            {
1526                    error("Failed to open display: %s\n", XDisplayName(NULL));
1527                    return False;
1528          }          }
1529    
         if (g_bpp < 8)  
1530          {          {
1531                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1532                  XCloseDisplay(g_display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1533            }
1534    
1535            g_old_error_handler = XSetErrorHandler(error_handler);
1536    
1537            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1538            screen_num = DefaultScreen(g_display);
1539            g_x_socket = ConnectionNumber(g_display);
1540            g_screen = ScreenOfDisplay(g_display, screen_num);
1541            g_depth = DefaultDepthOfScreen(g_screen);
1542    
1543            if (!select_visual())
1544                  return False;                  return False;
1545    
1546            if (g_no_translate_image)
1547            {
1548                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1549            }
1550    
1551            if (g_server_depth > g_bpp)
1552            {
1553                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1554                            g_server_depth, g_bpp);
1555          }          }
1556    
1557            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1558                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1559    
1560          if (!g_owncolmap)          if (!g_owncolmap)
1561          {          {
1562                  g_xcolmap =                  g_xcolmap =
1563                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1564                                          AllocNone);                                          AllocNone);
1565                  if (g_depth <= 8)                  if (g_depth <= 8)
1566                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");                          warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1567          }          }
1568    
1569          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1570          {          {
1571                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1572                  g_ownbackstore = True;                  g_ownbackstore = True;
1573          }          }
1574    
# Line 850  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          {          {
1586                  /* Percent of screen */                  /* Percent of screen */
1587                    if (-g_width >= 100)
1588                            g_using_full_workarea = True;
1589                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1590                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1591          }          }
# Line 861  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;
   
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 886  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_bpp, g_bpp, g_depth));          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1626    
1627          return True;          return True;
1628  }  }
# Line 895  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          if (g_IM != NULL)          if (g_IM != NULL)
1640                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1641    
# Line 911  ui_deinit(void) Line 1652  ui_deinit(void)
1652          g_display = NULL;          g_display = NULL;
1653  }  }
1654    
1655    
1656    static void
1657    get_window_attribs(XSetWindowAttributes * attribs)
1658    {
1659            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1660            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1661            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1662            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1663            attribs->override_redirect = g_fullscreen;
1664            attribs->colormap = g_xcolmap;
1665    }
1666    
1667    static void
1668    get_input_mask(long *input_mask)
1669    {
1670            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1671                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1672    
1673            if (g_sendmotion)
1674                    *input_mask |= PointerMotionMask;
1675            if (g_ownbackstore)
1676                    *input_mask |= ExposureMask;
1677            if (g_fullscreen || g_grab_keyboard)
1678                    *input_mask |= EnterWindowMask;
1679            if (g_grab_keyboard)
1680                    *input_mask |= LeaveWindowMask;
1681    }
1682    
1683  BOOL  BOOL
1684  ui_create_window(void)  ui_create_window(void)
1685  {  {
1686          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
1687          uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };          uint8 null_pointer_data[24] = { 0x00 };
1688    
1689          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1690          XClassHint *classhints;          XClassHint *classhints;
1691          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 926  ui_create_window(void) Line 1696  ui_create_window(void)
1696          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1697          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1698    
1699          attribs.background_pixel = BlackPixelOfScreen(g_screen);          /* Handle -x-y portion of geometry string */
1700          attribs.border_pixel = WhitePixelOfScreen(g_screen);          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1701          attribs.backing_store = g_ownbackstore ? NotUseful : Always;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1702          attribs.override_redirect = g_fullscreen;          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1703          attribs.colormap = g_xcolmap;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1704    
1705          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,          get_window_attribs(&attribs);
1706                                0, g_depth, InputOutput, g_visual,  
1707                                CWBackPixel | CWBackingStore | CWOverrideRedirect |          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1708                                CWColormap | CWBorderPixel, &attribs);                                wndheight, 0, g_depth, InputOutput, g_visual,
1709                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1710                                  CWBorderPixel, &attribs);
1711    
1712          if (g_gc == NULL)          if (g_gc == NULL)
1713            {
1714                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1715                    ui_reset_clip();
1716            }
1717    
1718            if (g_create_bitmap_gc == NULL)
1719                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1720    
1721          if ((g_ownbackstore) && (g_backstore == 0))          if ((g_ownbackstore) && (g_backstore == 0))
1722          {          {
# Line 952  ui_create_window(void) Line 1730  ui_create_window(void)
1730          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1731    
1732          if (g_hide_decorations)          if (g_hide_decorations)
1733                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1734    
1735          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1736          if (classhints != NULL)          if (classhints != NULL)
# Line 966  ui_create_window(void) Line 1744  ui_create_window(void)
1744          if (sizehints)          if (sizehints)
1745          {          {
1746                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1747                    if (g_pos)
1748                            sizehints->flags |= PPosition;
1749                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1750                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1751                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
# Line 977  ui_create_window(void) Line 1757  ui_create_window(void)
1757                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1758          }          }
1759    
1760          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          get_input_mask(&input_mask);
                 VisibilityChangeMask | FocusChangeMask;  
   
         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;  
1761    
1762          if (g_IM != NULL)          if (g_IM != NULL)
1763          {          {
# Line 1000  ui_create_window(void) Line 1770  ui_create_window(void)
1770          }          }
1771    
1772          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
         XMapWindow(g_display, g_wnd);  
1773    
1774            XMapWindow(g_display, g_wnd);
1775          /* wait for VisibilityNotify */          /* wait for VisibilityNotify */
1776          do          do
1777          {          {
# Line 1029  void Line 1799  void
1799  ui_resize_window()  ui_resize_window()
1800  {  {
1801          XSizeHints *sizehints;          XSizeHints *sizehints;
1802            Pixmap bs;
1803    
1804          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
1805          if (sizehints)          if (sizehints)
# Line 1044  ui_resize_window() Line 1815  ui_resize_window()
1815          {          {
1816                  XResizeWindow(g_display, g_wnd, g_width, g_height);                  XResizeWindow(g_display, g_wnd, g_width, g_height);
1817          }          }
1818    
1819            /* create new backstore pixmap */
1820            if (g_backstore != 0)
1821            {
1822                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1823                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1824                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1825                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1826                    XFreePixmap(g_display, g_backstore);
1827                    g_backstore = bs;
1828            }
1829  }  }
1830    
1831  void  void
# Line 1060  xwin_toggle_fullscreen(void) Line 1842  xwin_toggle_fullscreen(void)
1842  {  {
1843          Pixmap contents = 0;          Pixmap contents = 0;
1844    
1845            if (g_seamless_active)
1846                    /* Turn off SeamlessRDP mode */
1847                    ui_seamless_toggle();
1848    
1849          if (!g_ownbackstore)          if (!g_ownbackstore)
1850          {          {
1851                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1080  xwin_toggle_fullscreen(void) Line 1866  xwin_toggle_fullscreen(void)
1866          }          }
1867  }  }
1868    
1869  /* Process all events in Xlib queue  static void
1870    handle_button_event(XEvent xevent, BOOL down)
1871    {
1872            uint16 button, flags = 0;
1873            g_last_gesturetime = xevent.xbutton.time;
1874            button = xkeymap_translate_button(xevent.xbutton.button);
1875            if (button == 0)
1876                    return;
1877    
1878            if (down)
1879                    flags = MOUSE_FLAG_DOWN;
1880    
1881            /* Stop moving window when button is released, regardless of cursor position */
1882            if (g_moving_wnd && (xevent.type == ButtonRelease))
1883                    g_moving_wnd = False;
1884    
1885            /* If win_button_size is nonzero, enable single app mode */
1886            if (xevent.xbutton.y < g_win_button_size)
1887            {
1888                    /*  Check from right to left: */
1889                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1890                    {
1891                            /* The close button, continue */
1892                            ;
1893                    }
1894                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1895                    {
1896                            /* The maximize/restore button. Do not send to
1897                               server.  It might be a good idea to change the
1898                               cursor or give some other visible indication
1899                               that rdesktop inhibited this click */
1900                            if (xevent.type == ButtonPress)
1901                                    return;
1902                    }
1903                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1904                    {
1905                            /* The minimize button. Iconify window. */
1906                            if (xevent.type == ButtonRelease)
1907                            {
1908                                    /* Release the mouse button outside the minimize button, to prevent the
1909                                       actual minimazation to happen */
1910                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1911                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1912                                    return;
1913                            }
1914                    }
1915                    else if (xevent.xbutton.x <= g_win_button_size)
1916                    {
1917                            /* The system menu. Ignore. */
1918                            if (xevent.type == ButtonPress)
1919                                    return;
1920                    }
1921                    else
1922                    {
1923                            /* The title bar. */
1924                            if (xevent.type == ButtonPress)
1925                            {
1926                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1927                                    {
1928                                            g_moving_wnd = True;
1929                                            g_move_x_offset = xevent.xbutton.x;
1930                                            g_move_y_offset = xevent.xbutton.y;
1931                                    }
1932                                    return;
1933                            }
1934                    }
1935            }
1936    
1937            if (xevent.xmotion.window == g_wnd)
1938            {
1939                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1940                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1941            }
1942            else
1943            {
1944                    /* SeamlessRDP */
1945                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1946                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1947            }
1948    }
1949    
1950    
1951    /* Process events in Xlib queue
1952     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1953  static int  static int
1954  xwin_process_events(void)  xwin_process_events(void)
1955  {  {
1956          XEvent xevent;          XEvent xevent;
1957          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1958          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1959          char str[256];          char str[256];
1960          Status status;          Status status;
1961            int events = 0;
1962            seamless_window *sw;
1963    
1964          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1965          {          {
1966                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1967    
# Line 1103  xwin_process_events(void) Line 1971  xwin_process_events(void)
1971                          continue;                          continue;
1972                  }                  }
1973    
                 flags = 0;  
   
1974                  switch (xevent.type)                  switch (xevent.type)
1975                  {                  {
1976                          case VisibilityNotify:                          case VisibilityNotify:
1977                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1978                                            g_Unobscured =
1979                                                    xevent.xvisibility.state == VisibilityUnobscured;
1980    
1981                                  break;                                  break;
1982                          case ClientMessage:                          case ClientMessage:
1983                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1141  xwin_process_events(void) Line 2010  xwin_process_events(void)
2010                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
2011                                  }                                  }
2012    
2013                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
2014                                             get_ksname(keysym)));                                             get_ksname(keysym)));
2015    
2016                                  ev_time = time(NULL);                                  ev_time = time(NULL);
2017                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
2018                                          break;                                          break;
2019    
2020                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
2021                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, True, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 save_remote_modifiers(tr.scancode);  
                                 ensure_remote_modifiers(ev_time, tr);  
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);  
                                 restore_remote_modifiers(ev_time, tr.scancode);  
   
2022                                  break;                                  break;
2023    
2024                          case KeyRelease:                          case KeyRelease:
# Line 1166  xwin_process_events(void) Line 2026  xwin_process_events(void)
2026                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
2027                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
2028    
2029                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
2030                                             get_ksname(keysym)));                                             get_ksname(keysym)));
2031    
2032                                  ev_time = time(NULL);                                  ev_time = time(NULL);
2033                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
2034                                          break;                                          break;
2035    
2036                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
2037                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
2038                                  break;                                  break;
2039    
2040                          case ButtonPress:                          case ButtonPress:
2041                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
2042                                  /* fall through */                                  break;
2043    
2044                          case ButtonRelease:                          case ButtonRelease:
2045                                  g_last_gesturetime = xevent.xbutton.time;                                  handle_button_event(xevent, False);
                                 button = xkeymap_translate_button(xevent.xbutton.button);  
                                 if (button == 0)  
                                         break;  
   
                                 /* If win_button_size is nonzero, enable single app mode */  
                                 if (xevent.xbutton.y < g_win_button_size)  
                                 {  
                                         /* Stop moving window when button is released, regardless of cursor position */  
                                         if (g_moving_wnd && (xevent.type == ButtonRelease))  
                                                 g_moving_wnd = False;  
   
                                         /*  Check from right to left: */  
   
                                         if (xevent.xbutton.x >= g_width - g_win_button_size)  
                                         {  
                                                 /* The close button, continue */  
                                                 ;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 2)  
                                         {  
                                                 /* The maximize/restore button. Do not send to  
                                                    server.  It might be a good idea to change the  
                                                    cursor or give some other visible indication  
                                                    that rdesktop inhibited this click */  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 3)  
                                         {  
                                                 /* The minimize button. Iconify window. */  
                                                 XIconifyWindow(g_display, g_wnd,  
                                                                DefaultScreen(g_display));  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x <= g_win_button_size)  
                                         {  
                                                 /* The system menu. Ignore. */  
                                                 break;  
                                         }  
                                         else  
                                         {  
                                                 /* The title bar. */  
                                                 if ((xevent.type == ButtonPress) && !g_fullscreen  
                                                     && g_hide_decorations)  
                                                 {  
                                                         g_moving_wnd = True;  
                                                         g_move_x_offset = xevent.xbutton.x;  
                                                         g_move_y_offset = xevent.xbutton.y;  
                                                 }  
                                                 break;  
   
                                         }  
                                 }  
   
                                 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
                                                flags | button, xevent.xbutton.x, xevent.xbutton.y);  
2046                                  break;                                  break;
2047    
2048                          case MotionNotify:                          case MotionNotify:
# Line 1259  xwin_process_events(void) Line 2057  xwin_process_events(void)
2057                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
2058                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2059                                                         CurrentTime);                                                         CurrentTime);
2060                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
2061                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
2062                                    {
2063                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2064                                                           xevent.xmotion.x, xevent.xmotion.y);
2065                                    }
2066                                    else
2067                                    {
2068                                            /* SeamlessRDP */
2069                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
2070                                                           xevent.xmotion.x_root,
2071                                                           xevent.xmotion.y_root);
2072                                    }
2073                                  break;                                  break;
2074    
2075                          case FocusIn:                          case FocusIn:
# Line 1271  xwin_process_events(void) Line 2080  xwin_process_events(void)
2080                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2081                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2082                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2083    
2084                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2085                                    if (!sw)
2086                                            break;
2087    
2088                                    if (sw->id != g_seamless_focused)
2089                                    {
2090                                            seamless_send_focus(sw->id, 0);
2091                                            g_seamless_focused = sw->id;
2092                                    }
2093                                  break;                                  break;
2094    
2095                          case FocusOut:                          case FocusOut:
# Line 1303  xwin_process_events(void) Line 2122  xwin_process_events(void)
2122                                  break;                                  break;
2123    
2124                          case Expose:                          case Expose:
2125                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2126                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2127                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2128                                            xevent.xexpose.height,                                                    g_gc,
2129                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2130                                                      xevent.xexpose.width, xevent.xexpose.height,
2131                                                      xevent.xexpose.x, xevent.xexpose.y);
2132                                    }
2133                                    else
2134                                    {
2135                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2136                                            if (sw)
2137                                                    XCopyArea(g_display, g_backstore,
2138                                                              xevent.xexpose.window, g_gc,
2139                                                              xevent.xexpose.x + sw->xoffset,
2140                                                              xevent.xexpose.y + sw->yoffset,
2141                                                              xevent.xexpose.width,
2142                                                              xevent.xexpose.height, xevent.xexpose.x,
2143                                                              xevent.xexpose.y);
2144                                            else
2145                                            {
2146                                                    error("Expose for unknown window 0x%lx\n",
2147                                                          xevent.xexpose.window);
2148                                            }
2149                                    }
2150    
2151                                  break;                                  break;
2152    
2153                          case MappingNotify:                          case MappingNotify:
# Line 1336  xwin_process_events(void) Line 2176  xwin_process_events(void)
2176                                  break;                                  break;
2177                          case PropertyNotify:                          case PropertyNotify:
2178                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2179                                    if (xevent.xproperty.window == g_wnd)
2180                                            break;
2181                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2182                                            break;
2183    
2184                                    /* seamless */
2185                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2186                                    if (!sw)
2187                                            break;
2188    
2189                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2190                                        && (xevent.xproperty.state == PropertyNewValue))
2191                                    {
2192                                            sw->state = ewmh_get_window_state(sw->wnd);
2193                                            seamless_send_state(sw->id, sw->state, 0);
2194                                    }
2195    
2196                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2197                                        && (xevent.xproperty.state == PropertyNewValue))
2198                                    {
2199                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2200                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2201                                    }
2202    
2203                                    break;
2204                            case MapNotify:
2205                                    if (!g_seamless_active)
2206                                            rdp_send_client_window_status(1);
2207                                    break;
2208                            case UnmapNotify:
2209                                    if (!g_seamless_active)
2210                                            rdp_send_client_window_status(0);
2211                                    break;
2212                            case ConfigureNotify:
2213                                    if (!g_seamless_active)
2214                                            break;
2215    
2216                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2217                                    if (!sw)
2218                                    {
2219                                            error("ConfigureNotify for unknown window 0x%lx\n",
2220                                                  xevent.xconfigure.window);
2221                                    }
2222    
2223                                    gettimeofday(sw->position_timer, NULL);
2224                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2225                                        1000000)
2226                                    {
2227                                            sw->position_timer->tv_usec +=
2228                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2229                                            sw->position_timer->tv_sec += 1;
2230                                    }
2231                                    else
2232                                    {
2233                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2234                                    }
2235    
2236                                    sw_handle_restack(sw);
2237                                  break;                                  break;
2238                  }                  }
2239          }          }
# Line 1360  ui_select(int rdp_socket) Line 2258  ui_select(int rdp_socket)
2258                          /* User quit */                          /* User quit */
2259                          return 0;                          return 0;
2260    
2261                    if (g_seamless_active)
2262                            sw_check_timers();
2263    
2264                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2265                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2266                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
# Line 1379  ui_select(int rdp_socket) Line 2280  ui_select(int rdp_socket)
2280    
2281                  /* add redirection handles */                  /* add redirection handles */
2282                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2283                    seamless_select_timeout(&tv);
2284    
2285                  n++;                  n++;
2286    
# Line 1388  ui_select(int rdp_socket) Line 2290  ui_select(int rdp_socket)
2290                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2291    
2292                          case 0:                          case 0:
2293                                  /* TODO: if tv.tv_sec just times out                                  /* Abort serial read calls */
2294                                   * we will segfault.                                  if (s_timeout)
2295                                   * FIXME:                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
                                  */  
                                 //s_timeout = True;  
                                 //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);  
2296                                  continue;                                  continue;
2297                  }                  }
2298    
# Line 1423  ui_create_bitmap(int width, int height, Line 2322  ui_create_bitmap(int width, int height,
2322          uint8 *tdata;          uint8 *tdata;
2323          int bitmap_pad;          int bitmap_pad;
2324    
2325          if (g_server_bpp == 8)          if (g_server_depth == 8)
2326          {          {
2327                  bitmap_pad = 8;                  bitmap_pad = 8;
2328          }          }
# Line 1440  ui_create_bitmap(int width, int height, Line 2339  ui_create_bitmap(int width, int height,
2339          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2340                               (char *) tdata, width, height, bitmap_pad, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
2341    
2342          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
2343    
2344          XFree(image);          XFree(image);
2345          if (tdata != data)          if (tdata != data)
# Line 1455  ui_paint_bitmap(int x, int y, int cx, in Line 2354  ui_paint_bitmap(int x, int y, int cx, in
2354          uint8 *tdata;          uint8 *tdata;
2355          int bitmap_pad;          int bitmap_pad;
2356    
2357          if (g_server_bpp == 8)          if (g_server_depth == 8)
2358          {          {
2359                  bitmap_pad = 8;                  bitmap_pad = 8;
2360          }          }
# Line 1475  ui_paint_bitmap(int x, int y, int cx, in Line 2374  ui_paint_bitmap(int x, int y, int cx, in
2374          {          {
2375                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2376                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2377                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2378                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2379                                             x - sw->xoffset, y - sw->yoffset));
2380          }          }
2381          else          else
2382          {          {
2383                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2384                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2385                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2386                                             x - sw->xoffset, y - sw->yoffset));
2387          }          }
2388    
2389          XFree(image);          XFree(image);
# Line 1498  ui_create_glyph(int width, int height, u Line 2403  ui_create_glyph(int width, int height, u
2403          XImage *image;          XImage *image;
2404          Pixmap bitmap;          Pixmap bitmap;
2405          int scanline;          int scanline;
         GC gc;  
2406    
2407          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
2408    
2409          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
2410          gc = XCreateGC(g_display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
2411                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
2412    
2413          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
2414                               width, height, 8, scanline);                               width, height, 8, scanline);
# Line 1511  ui_create_glyph(int width, int height, u Line 2416  ui_create_glyph(int width, int height, u
2416          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
2417          XInitImage(image);          XInitImage(image);
2418    
2419          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
2420    
2421          XFree(image);          XFree(image);
         XFreeGC(g_display, gc);  
2422          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
2423  }  }
2424    
# Line 1600  ui_set_cursor(HCURSOR cursor) Line 2504  ui_set_cursor(HCURSOR cursor)
2504  {  {
2505          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2506          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2507            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2508  }  }
2509    
2510  void  void
# Line 1741  ui_set_colourmap(HCOLOURMAP map) Line 2646  ui_set_colourmap(HCOLOURMAP map)
2646                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2647          }          }
2648          else          else
2649            {
2650                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2651                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2652            }
2653  }  }
2654    
2655  void  void
2656  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2657  {  {
2658          XRectangle rect;          g_clip_rectangle.x = x;
2659            g_clip_rectangle.y = y;
2660          rect.x = x;          g_clip_rectangle.width = cx;
2661          rect.y = y;          g_clip_rectangle.height = cy;
2662          rect.width = cx;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = cy;  
         XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);  
2663  }  }
2664    
2665  void  void
2666  ui_reset_clip(void)  ui_reset_clip(void)
2667  {  {
2668          XRectangle rect;          g_clip_rectangle.x = 0;
2669            g_clip_rectangle.y = 0;
2670          rect.x = 0;          g_clip_rectangle.width = g_width;
2671          rect.y = 0;          g_clip_rectangle.height = g_height;
2672          rect.width = g_width;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = g_height;  
         XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);  
2673  }  }
2674    
2675  void  void
# Line 1846  ui_patblt(uint8 opcode, Line 2750  ui_patblt(uint8 opcode,
2750    
2751          if (g_ownbackstore)          if (g_ownbackstore)
2752                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2753            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2754                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2755                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2756  }  }
2757    
2758  void  void
# Line 1856  ui_screenblt(uint8 opcode, Line 2763  ui_screenblt(uint8 opcode,
2763          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2764          if (g_ownbackstore)          if (g_ownbackstore)
2765          {          {
2766                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2767                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2768                          XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                         XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,  
                                   y);  
                 }  
                 else  
                 {  
                         XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
                         XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,  
                                   y);  
                 }  
2769          }          }
2770          else          else
2771          {          {
2772                  XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2773          }          }
2774    
2775            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2776                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2777                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2778    
2779          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2780  }  }
2781    
# Line 1883  ui_memblt(uint8 opcode, Line 2786  ui_memblt(uint8 opcode,
2786  {  {
2787          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2788          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2789            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2790                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2791                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2792          if (g_ownbackstore)          if (g_ownbackstore)
2793                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2794          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1929  ui_line(uint8 opcode, Line 2835  ui_line(uint8 opcode,
2835          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2836          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2837          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2838            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2839                                                startx - sw->xoffset, starty - sw->yoffset,
2840                                                endx - sw->xoffset, endy - sw->yoffset));
2841          if (g_ownbackstore)          if (g_ownbackstore)
2842                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2843          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1943  ui_rect( Line 2852  ui_rect(
2852          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2853  }  }
2854    
2855    void
2856    ui_polygon(uint8 opcode,
2857               /* mode */ uint8 fillmode,
2858               /* dest */ POINT * point, int npoints,
2859               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2860    {
2861            uint8 style, i, ipattern[8];
2862            Pixmap fill;
2863    
2864            SET_FUNCTION(opcode);
2865    
2866            switch (fillmode)
2867            {
2868                    case ALTERNATE:
2869                            XSetFillRule(g_display, g_gc, EvenOddRule);
2870                            break;
2871                    case WINDING:
2872                            XSetFillRule(g_display, g_gc, WindingRule);
2873                            break;
2874                    default:
2875                            unimpl("fill mode %d\n", fillmode);
2876            }
2877    
2878            if (brush)
2879                    style = brush->style;
2880            else
2881                    style = 0;
2882    
2883            switch (style)
2884            {
2885                    case 0: /* Solid */
2886                            SET_FOREGROUND(fgcolour);
2887                            FILL_POLYGON((XPoint *) point, npoints);
2888                            break;
2889    
2890                    case 2: /* Hatch */
2891                            fill = (Pixmap) ui_create_glyph(8, 8,
2892                                                            hatch_patterns + brush->pattern[0] * 8);
2893                            SET_FOREGROUND(fgcolour);
2894                            SET_BACKGROUND(bgcolour);
2895                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2896                            XSetStipple(g_display, g_gc, fill);
2897                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2898                            FILL_POLYGON((XPoint *) point, npoints);
2899                            XSetFillStyle(g_display, g_gc, FillSolid);
2900                            XSetTSOrigin(g_display, g_gc, 0, 0);
2901                            ui_destroy_glyph((HGLYPH) fill);
2902                            break;
2903    
2904                    case 3: /* Pattern */
2905                            for (i = 0; i != 8; i++)
2906                                    ipattern[7 - i] = brush->pattern[i];
2907                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2908                            SET_FOREGROUND(bgcolour);
2909                            SET_BACKGROUND(fgcolour);
2910                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2911                            XSetStipple(g_display, g_gc, fill);
2912                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2913                            FILL_POLYGON((XPoint *) point, npoints);
2914                            XSetFillStyle(g_display, g_gc, FillSolid);
2915                            XSetTSOrigin(g_display, g_gc, 0, 0);
2916                            ui_destroy_glyph((HGLYPH) fill);
2917                            break;
2918    
2919                    default:
2920                            unimpl("brush %d\n", brush->style);
2921            }
2922    
2923            RESET_FUNCTION(opcode);
2924    }
2925    
2926    void
2927    ui_polyline(uint8 opcode,
2928                /* dest */ POINT * points, int npoints,
2929                /* pen */ PEN * pen)
2930    {
2931            /* TODO: set join style */
2932            SET_FUNCTION(opcode);
2933            SET_FOREGROUND(pen->colour);
2934            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2935            if (g_ownbackstore)
2936                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2937                               CoordModePrevious);
2938    
2939            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2940                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2941    
2942            RESET_FUNCTION(opcode);
2943    }
2944    
2945    void
2946    ui_ellipse(uint8 opcode,
2947               /* mode */ uint8 fillmode,
2948               /* dest */ int x, int y, int cx, int cy,
2949               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2950    {
2951            uint8 style, i, ipattern[8];
2952            Pixmap fill;
2953    
2954            SET_FUNCTION(opcode);
2955    
2956            if (brush)
2957                    style = brush->style;
2958            else
2959                    style = 0;
2960    
2961            switch (style)
2962            {
2963                    case 0: /* Solid */
2964                            SET_FOREGROUND(fgcolour);
2965                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2966                            break;
2967    
2968                    case 2: /* Hatch */
2969                            fill = (Pixmap) ui_create_glyph(8, 8,
2970                                                            hatch_patterns + brush->pattern[0] * 8);
2971                            SET_FOREGROUND(fgcolour);
2972                            SET_BACKGROUND(bgcolour);
2973                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2974                            XSetStipple(g_display, g_gc, fill);
2975                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2976                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2977                            XSetFillStyle(g_display, g_gc, FillSolid);
2978                            XSetTSOrigin(g_display, g_gc, 0, 0);
2979                            ui_destroy_glyph((HGLYPH) fill);
2980                            break;
2981    
2982                    case 3: /* Pattern */
2983                            for (i = 0; i != 8; i++)
2984                                    ipattern[7 - i] = brush->pattern[i];
2985                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2986                            SET_FOREGROUND(bgcolour);
2987                            SET_BACKGROUND(fgcolour);
2988                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2989                            XSetStipple(g_display, g_gc, fill);
2990                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2991                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2992                            XSetFillStyle(g_display, g_gc, FillSolid);
2993                            XSetTSOrigin(g_display, g_gc, 0, 0);
2994                            ui_destroy_glyph((HGLYPH) fill);
2995                            break;
2996    
2997                    default:
2998                            unimpl("brush %d\n", brush->style);
2999            }
3000    
3001            RESET_FUNCTION(opcode);
3002    }
3003    
3004  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
3005  void  void
3006  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1998  ui_draw_glyph(int mixmode, Line 3056  ui_draw_glyph(int mixmode,
3056  }  }
3057    
3058  void  void
3059  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
3060               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
3061               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
3062               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
3063  {  {
3064            /* TODO: use brush appropriately */
3065    
3066          FONTGLYPH *glyph;          FONTGLYPH *glyph;
3067          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
3068          DATABLOB *entry;          DATABLOB *entry;
# Line 2034  ui_draw_text(uint8 font, uint8 flags, in Line 3094  ui_draw_text(uint8 font, uint8 flags, in
3094                  switch (text[i])                  switch (text[i])
3095                  {                  {
3096                          case 0xff:                          case 0xff:
3097                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
3098                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
3099                                  {                                  {
3100                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
3101                                          exit(1);                                          for (j = 0; j < length; j++)
3102                                                    fprintf(stderr, "%02x ", text[j]);
3103                                            fprintf(stderr, "\n");
3104                                            i = length = 0;
3105                                            break;
3106                                  }                                  }
3107                                    cache_put_text(text[i + 1], text, text[i + 2]);
3108                                    i += 3;
3109                                    length -= i;
3110                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
3111                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
3112                                  i = 0;                                  i = 0;
3113                                  break;                                  break;
3114    
3115                          case 0xfe:                          case 0xfe:
3116                                    /* At least one byte needs to follow */
3117                                    if (i + 2 > length)
3118                                    {
3119                                            warning("Skipping short 0xfe command:");
3120                                            for (j = 0; j < length; j++)
3121                                                    fprintf(stderr, "%02x ", text[j]);
3122                                            fprintf(stderr, "\n");
3123                                            i = length = 0;
3124                                            break;
3125                                    }
3126                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
3127                                  if (entry != NULL)                                  if (entry->data != NULL)
3128                                  {                                  {
3129                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
3130                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
3131                                          {                                          {
3132                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
3133                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2084  ui_draw_text(uint8 font, uint8 flags, in Line 3159  ui_draw_text(uint8 font, uint8 flags, in
3159          if (g_ownbackstore)          if (g_ownbackstore)
3160          {          {
3161                  if (boxcx > 1)                  if (boxcx > 1)
3162                    {
3163                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3164                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3165                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3166                                                    (g_display, g_backstore, sw->wnd, g_gc,
3167                                                     boxx, boxy,
3168                                                     boxcx, boxcy,
3169                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3170                    }
3171                  else                  else
3172                    {
3173                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3174                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3175                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3176                                                    (g_display, g_backstore, sw->wnd, g_gc,
3177                                                     clipx, clipy,
3178                                                     clipcx, clipcy, clipx - sw->xoffset,
3179                                                     clipy - sw->yoffset));
3180                    }
3181          }          }
3182  }  }
3183    
# Line 2134  ui_desktop_restore(uint32 offset, int x, Line 3223  ui_desktop_restore(uint32 offset, int x,
3223          {          {
3224                  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);
3225                  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);
3226                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3227                                            (g_display, g_backstore, sw->wnd, g_gc,
3228                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3229          }          }
3230          else          else
3231          {          {
3232                  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);
3233                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3234                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3235                                             x - sw->xoffset, y - sw->yoffset));
3236          }          }
3237    
3238          XFree(image);          XFree(image);
3239  }  }
3240    
3241    /* these do nothing here but are used in uiports */
3242    void
3243    ui_begin_update(void)
3244    {
3245    }
3246    
3247    void
3248    ui_end_update(void)
3249    {
3250    }
3251    
3252    
3253    void
3254    ui_seamless_begin()
3255    {
3256            if (!g_seamless_rdp)
3257                    return;
3258    
3259            if (g_seamless_started)
3260                    return;
3261    
3262            g_seamless_started = True;
3263            ui_seamless_toggle();
3264    }
3265    
3266    
3267    void
3268    ui_seamless_toggle()
3269    {
3270            if (!g_seamless_rdp)
3271                    return;
3272    
3273            if (!g_seamless_started)
3274                    return;
3275    
3276            if (g_seamless_active)
3277            {
3278                    /* Deactivate */
3279                    while (g_seamless_windows)
3280                    {
3281                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3282                            sw_remove_window(g_seamless_windows);
3283                    }
3284                    XMapWindow(g_display, g_wnd);
3285            }
3286            else
3287            {
3288                    /* Activate */
3289                    XUnmapWindow(g_display, g_wnd);
3290                    seamless_send_sync();
3291            }
3292    
3293            g_seamless_active = !g_seamless_active;
3294    }
3295    
3296    
3297    void
3298    ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3299                              unsigned long flags)
3300    {
3301            Window wnd;
3302            XSetWindowAttributes attribs;
3303            XClassHint *classhints;
3304            XSizeHints *sizehints;
3305            XWMHints *wmhints;
3306            long input_mask;
3307            seamless_window *sw, *sw_parent;
3308    
3309            if (!g_seamless_active)
3310                    return;
3311    
3312            /* Ignore CREATEs for existing windows */
3313            sw = sw_get_window_by_id(id);
3314            if (sw)
3315                    return;
3316    
3317            get_window_attribs(&attribs);
3318            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3319                                InputOutput, g_visual,
3320                                CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3321    
3322            XStoreName(g_display, wnd, "SeamlessRDP");
3323            ewmh_set_wm_name(wnd, "SeamlessRDP");
3324    
3325            mwm_hide_decorations(wnd);
3326    
3327            classhints = XAllocClassHint();
3328            if (classhints != NULL)
3329            {
3330                    classhints->res_name = "rdesktop";
3331                    classhints->res_class = "SeamlessRDP";
3332                    XSetClassHint(g_display, wnd, classhints);
3333                    XFree(classhints);
3334            }
3335    
3336            /* WM_NORMAL_HINTS */
3337            sizehints = XAllocSizeHints();
3338            if (sizehints != NULL)
3339            {
3340                    sizehints->flags = USPosition;
3341                    XSetWMNormalHints(g_display, wnd, sizehints);
3342                    XFree(sizehints);
3343            }
3344    
3345            /* Parent-less transient windows */
3346            if (parent == 0xFFFFFFFF)
3347            {
3348                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3349                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3350                       using some other hints. */
3351                    ewmh_set_window_popup(wnd);
3352            }
3353            /* Normal transient windows */
3354            else if (parent != 0x00000000)
3355            {
3356                    sw_parent = sw_get_window_by_id(parent);
3357                    if (sw_parent)
3358                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3359                    else
3360                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3361            }
3362    
3363            if (flags & SEAMLESSRDP_CREATE_MODAL)
3364            {
3365                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3366                       somewhat at least */
3367                    if (parent == 0x00000000)
3368                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3369                    ewmh_set_window_modal(wnd);
3370            }
3371    
3372            /* FIXME: Support for Input Context:s */
3373    
3374            get_input_mask(&input_mask);
3375            input_mask |= PropertyChangeMask;
3376    
3377            XSelectInput(g_display, wnd, input_mask);
3378    
3379            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3380               seamless window, we could try to close the window on the
3381               serverside, instead of terminating rdesktop */
3382            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3383    
3384            sw = xmalloc(sizeof(seamless_window));
3385            sw->wnd = wnd;
3386            sw->id = id;
3387            sw->behind = 0;
3388            sw->group = sw_find_group(group, False);
3389            sw->group->refcnt++;
3390            sw->xoffset = 0;
3391            sw->yoffset = 0;
3392            sw->width = 0;
3393            sw->height = 0;
3394            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3395            sw->desktop = 0;
3396            sw->position_timer = xmalloc(sizeof(struct timeval));
3397            timerclear(sw->position_timer);
3398    
3399            sw->outstanding_position = False;
3400            sw->outpos_serial = 0;
3401            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3402            sw->outpos_width = sw->outpos_height = 0;
3403    
3404            sw->next = g_seamless_windows;
3405            g_seamless_windows = sw;
3406    
3407            /* WM_HINTS */
3408            wmhints = XAllocWMHints();
3409            if (wmhints)
3410            {
3411                    wmhints->flags = WindowGroupHint;
3412                    wmhints->window_group = sw->group->wnd;
3413                    XSetWMHints(g_display, sw->wnd, wmhints);
3414                    XFree(wmhints);
3415            }
3416    }
3417    
3418    
3419    void
3420    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3421    {
3422            seamless_window *sw;
3423    
3424            if (!g_seamless_active)
3425                    return;
3426    
3427            sw = sw_get_window_by_id(id);
3428            if (!sw)
3429            {
3430                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3431                    return;
3432            }
3433    
3434            XDestroyWindow(g_display, sw->wnd);
3435            sw_remove_window(sw);
3436    }
3437    
3438    
3439    void
3440    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3441    {
3442            seamless_window *sw;
3443    
3444            if (!g_seamless_active)
3445                    return;
3446    
3447            sw = sw_get_window_by_id(id);
3448            if (!sw)
3449            {
3450                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3451                    return;
3452            }
3453    
3454            /* We ignore server updates until it has handled our request. */
3455            if (sw->outstanding_position)
3456                    return;
3457    
3458            if (!width || !height)
3459                    /* X11 windows must be at least 1x1 */
3460                    return;
3461    
3462            sw->xoffset = x;
3463            sw->yoffset = y;
3464            sw->width = width;
3465            sw->height = height;
3466    
3467            /* If we move the window in a maximized state, then KDE won't
3468               accept restoration */
3469            switch (sw->state)
3470            {
3471                    case SEAMLESSRDP_MINIMIZED:
3472                    case SEAMLESSRDP_MAXIMIZED:
3473                            return;
3474            }
3475    
3476            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3477            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3478    }
3479    
3480    
3481    void
3482    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3483    {
3484            seamless_window *sw;
3485    
3486            if (!g_seamless_active)
3487                    return;
3488    
3489            sw = sw_get_window_by_id(id);
3490            if (!sw)
3491            {
3492                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3493                    return;
3494            }
3495    
3496            if (behind)
3497            {
3498                    seamless_window *sw_behind;
3499                    Window wnds[2];
3500    
3501                    sw_behind = sw_get_window_by_id(behind);
3502                    if (!sw_behind)
3503                    {
3504                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3505                                    behind);
3506                            return;
3507                    }
3508    
3509                    wnds[1] = sw_behind->wnd;
3510                    wnds[0] = sw->wnd;
3511    
3512                    XRestackWindows(g_display, wnds, 2);
3513            }
3514            else
3515            {
3516                    XRaiseWindow(g_display, sw->wnd);
3517            }
3518    
3519            sw_restack_window(sw, behind);
3520    }
3521    
3522    
3523    void
3524    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3525    {
3526            seamless_window *sw;
3527    
3528            if (!g_seamless_active)
3529                    return;
3530    
3531            sw = sw_get_window_by_id(id);
3532            if (!sw)
3533            {
3534                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3535                    return;
3536            }
3537    
3538            /* FIXME: Might want to convert the name for non-EWMH WMs */
3539            XStoreName(g_display, sw->wnd, title);
3540            ewmh_set_wm_name(sw->wnd, title);
3541    }
3542    
3543    
3544    void
3545    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3546    {
3547            seamless_window *sw;
3548    
3549            if (!g_seamless_active)
3550                    return;
3551    
3552            sw = sw_get_window_by_id(id);
3553            if (!sw)
3554            {
3555                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3556                    return;
3557            }
3558    
3559            switch (state)
3560            {
3561                    case SEAMLESSRDP_NORMAL:
3562                    case SEAMLESSRDP_MAXIMIZED:
3563                            ewmh_change_state(sw->wnd, state);
3564                            XMapWindow(g_display, sw->wnd);
3565                            break;
3566                    case SEAMLESSRDP_MINIMIZED:
3567                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3568                               the Window Manager should probably just ignore the request, since
3569                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3570                               such as minimization, rather than an independent state." Besides,
3571                               XIconifyWindow is easier. */
3572                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3573                            {
3574                                    XWMHints *hints;
3575                                    hints = XGetWMHints(g_display, sw->wnd);
3576                                    if (hints)
3577                                    {
3578                                            hints->flags |= StateHint;
3579                                            hints->initial_state = IconicState;
3580                                            XSetWMHints(g_display, sw->wnd, hints);
3581                                            XFree(hints);
3582                                    }
3583                                    XMapWindow(g_display, sw->wnd);
3584                            }
3585                            else
3586                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3587                            break;
3588                    default:
3589                            warning("SeamlessRDP: Invalid state %d\n", state);
3590                            break;
3591            }
3592    
3593            sw->state = state;
3594    }
3595    
3596    
3597    void
3598    ui_seamless_syncbegin(unsigned long flags)
3599    {
3600            if (!g_seamless_active)
3601                    return;
3602    
3603            /* Destroy all seamless windows */
3604            while (g_seamless_windows)
3605            {
3606                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3607                    sw_remove_window(g_seamless_windows);
3608            }
3609    }
3610    
3611    
3612    void
3613    ui_seamless_ack(unsigned int serial)
3614    {
3615            seamless_window *sw;
3616            for (sw = g_seamless_windows; sw; sw = sw->next)
3617            {
3618                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3619                    {
3620                            sw->xoffset = sw->outpos_xoffset;
3621                            sw->yoffset = sw->outpos_yoffset;
3622                            sw->width = sw->outpos_width;
3623                            sw->height = sw->outpos_height;
3624                            sw->outstanding_position = False;
3625    
3626                            /* Do a complete redraw of the window as part of the
3627                               completion of the move. This is to remove any
3628                               artifacts caused by our lack of synchronization. */
3629                            XCopyArea(g_display, g_backstore,
3630                                      sw->wnd, g_gc,
3631                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3632    
3633                            break;
3634                    }
3635            }
3636    }

Legend:
Removed from v.695  
changed lines
  Added in v.1183

  ViewVC Help
Powered by ViewVC 1.1.26