/[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 800 by stargo, Thu Nov 18 11:18:49 2004 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1151 by ossman_, Fri Mar 17 08:52:29 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 32  extern int g_width; Line 32  extern int g_width;
32  extern int g_height;  extern int g_height;
33  extern int g_xpos;  extern int g_xpos;
34  extern int g_ypos;  extern int g_ypos;
35    extern int g_pos;
36  extern BOOL g_sendmotion;  extern BOOL g_sendmotion;
37  extern BOOL g_fullscreen;  extern BOOL g_fullscreen;
38  extern BOOL g_grab_keyboard;  extern BOOL g_grab_keyboard;
39  extern BOOL g_hide_decorations;  extern BOOL g_hide_decorations;
40  extern char g_title[];  extern char g_title[];
41  extern int g_server_bpp;  /* Color depth of the RDP session.
42       As of RDP 5.1, it may be 8, 15, 16 or 24. */
43    extern int g_server_depth;
44  extern int g_win_button_size;  extern int g_win_button_size;
45    
46  Display *g_display;  Display *g_display;
# Line 45  Time g_last_gesturetime; Line 48  Time g_last_gesturetime;
48  static int g_x_socket;  static int g_x_socket;
49  static Screen *g_screen;  static Screen *g_screen;
50  Window g_wnd;  Window g_wnd;
51    
52    /* SeamlessRDP support */
53    typedef struct _seamless_window
54    {
55            Window wnd;
56            unsigned long id;
57            unsigned long parent;
58            int xoffset, yoffset;
59            int width, height;
60            int state;              /* normal/minimized/maximized. */
61            unsigned int desktop;
62            struct _seamless_window *next;
63    } seamless_window;
64    static seamless_window *g_seamless_windows = NULL;
65    static BOOL g_seamless_started = False; /* Server end is up and running */
66    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
67    extern BOOL g_seamless_rdp;
68    
69  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
70  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
71  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
72  static GC g_gc = NULL;  static GC g_gc = NULL;
73  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
74  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
75    static XRectangle g_clip_rectangle;
76  static Visual *g_visual;  static Visual *g_visual;
77    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
78       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
79       as far as we're concerned. */
80  static int g_depth;  static int g_depth;
81    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
82       This may be larger than g_depth, in which case some of the bits would
83       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
84  static int g_bpp;  static int g_bpp;
85  static XIM g_IM;  static XIM g_IM;
86  static XIC g_IC;  static XIC g_IC;
# Line 60  static XModifierKeymap *g_mod_map; Line 88  static XModifierKeymap *g_mod_map;
88  static Cursor g_current_cursor;  static Cursor g_current_cursor;
89  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
90  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
91    extern Atom g_net_wm_state_atom;
92    extern Atom g_net_wm_desktop_atom;
93  static BOOL g_focused;  static BOOL g_focused;
94  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
95  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* Indicates that:
96       1) visual has 15, 16 or 24 depth and the same color channel masks
97          as its RDP equivalent (implies X server is LE),
98       2) host is LE
99       This will trigger an optimization whose real value is questionable.
100    */
101    static BOOL g_compatible_arch;
102    /* Indicates whether RDP's bitmaps and our XImages have the same
103       binary format. If so, we can avoid an expensive translation.
104       Note that this can be true when g_compatible_arch is false,
105       e.g.:
106      
107         RDP(LE) <-> host(BE) <-> X-Server(LE)
108        
109       ('host' is the machine running rdesktop; the host simply memcpy's
110        so its endianess doesn't matter)
111     */
112    static BOOL g_no_translate_image = False;
113    
114  /* endianness */  /* endianness */
115  static BOOL g_host_be;  static BOOL g_host_be;
# Line 78  static Pixmap g_backstore = 0; Line 125  static Pixmap g_backstore = 0;
125  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
126  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
127  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
128    static BOOL g_using_full_workarea = False;
129    
130  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
131  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 90  extern BOOL g_rdpsnd; Line 138  extern BOOL g_rdpsnd;
138  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
139  typedef struct  typedef struct
140  {  {
141          uint32 flags;          unsigned long flags;
142          uint32 functions;          unsigned long functions;
143          uint32 decorations;          unsigned long decorations;
144          sint32 inputMode;          long inputMode;
145          uint32 status;          unsigned long status;
146  }  }
147  PropMotifWmHints;  PropMotifWmHints;
148    
# Line 106  typedef struct Line 154  typedef struct
154  }  }
155  PixelColour;  PixelColour;
156    
157    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
158            do { \
159                    seamless_window *sw; \
160                    XRectangle rect; \
161                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
162                        rect.x = g_clip_rectangle.x - sw->xoffset; \
163                        rect.y = g_clip_rectangle.y - sw->yoffset; \
164                        rect.width = g_clip_rectangle.width; \
165                        rect.height = g_clip_rectangle.height; \
166                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
167                        func args; \
168                    } \
169                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
170            } while (0)
171    
172    static void
173    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
174    {
175            points[0].x -= xoffset;
176            points[0].y -= yoffset;
177            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
178            points[0].x += xoffset;
179            points[0].y += yoffset;
180    }
181    
182    static void
183    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
184    {
185            points[0].x -= xoffset;
186            points[0].y -= yoffset;
187            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
188            points[0].x += xoffset;
189            points[0].y += yoffset;
190    }
191    
192  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
193  { \  { \
194          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
195            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
196          if (g_ownbackstore) \          if (g_ownbackstore) \
197                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
198  }  }
# Line 119  PixelColour; Line 202  PixelColour;
202          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); \
203  }  }
204    
205    #define FILL_POLYGON(p,np)\
206    { \
207            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
208            if (g_ownbackstore) \
209                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
210            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
211    }
212    
213    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
214    { \
215            switch (m) \
216            { \
217                    case 0: /* Outline */ \
218                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
219                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
220                            if (g_ownbackstore) \
221                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
222                            break; \
223                    case 1: /* Filled */ \
224                            XFillArc(g_display, g_wnd, g_gc, x, y, \
225                                     cx, cy, 0, 360*64); \
226                            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)); \
227                            if (g_ownbackstore) \
228                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
229                            break; \
230            } \
231    }
232    
233  /* colour maps */  /* colour maps */
234  extern BOOL g_owncolmap;  extern BOOL g_owncolmap;
235  static Colormap g_xcolmap;  static Colormap g_xcolmap;
236  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
237    
238  #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] )
239  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
240  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
241    
# Line 150  static int rop2_map[] = { Line 261  static int rop2_map[] = {
261  #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]); }
262  #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); }
263    
264    static seamless_window *
265    seamless_get_window_by_id(unsigned long id)
266    {
267            seamless_window *sw;
268            for (sw = g_seamless_windows; sw; sw = sw->next)
269            {
270                    if (sw->id == id)
271                            return sw;
272            }
273            return NULL;
274    }
275    
276    
277    static seamless_window *
278    seamless_get_window_by_wnd(Window wnd)
279    {
280            seamless_window *sw;
281            for (sw = g_seamless_windows; sw; sw = sw->next)
282            {
283                    if (sw->wnd == wnd)
284                            return sw;
285            }
286            return NULL;
287    }
288    
289    
290    static void
291    seamless_remove_window(seamless_window * win)
292    {
293            seamless_window *sw, **prevnext = &g_seamless_windows;
294            for (sw = g_seamless_windows; sw; sw = sw->next)
295            {
296                    if (sw == win)
297                    {
298                            *prevnext = sw->next;
299                            xfree(sw);
300                            return;
301                    }
302                    prevnext = &sw->next;
303            }
304            return;
305    }
306    
307    
308    /* Move all windows except wnd to new desktop */
309  static void  static void
310  mwm_hide_decorations(void)  seamless_all_to_desktop(Window wnd, unsigned int desktop)
311    {
312            seamless_window *sw;
313            for (sw = g_seamless_windows; sw; sw = sw->next)
314            {
315                    if (sw->wnd == wnd)
316                            continue;
317                    if (sw->desktop != desktop)
318                    {
319                            ewmh_move_to_desktop(sw->wnd, desktop);
320                            sw->desktop = desktop;
321                    }
322            }
323    }
324    
325    
326    static void
327    mwm_hide_decorations(Window wnd)
328  {  {
329          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
330          Atom hintsatom;          Atom hintsatom;
# Line 168  mwm_hide_decorations(void) Line 341  mwm_hide_decorations(void)
341                  return;                  return;
342          }          }
343    
344          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
345                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
346    
347  }  }
348    
349  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
350  split_colour15(uint32 colour)  { \
351  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
352          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
353          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7);          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
         rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7);  
         rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);  
         return rv;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7);  
         rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3);  
         rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);  
         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;  
354  }  }
355    
356  static uint32  #define SPLITCOLOUR16(colour, rv) \
357  make_colour(PixelColour pc)  { \
358  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
359          return (((pc.red >> g_red_shift_r) << g_red_shift_l)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
360                  | ((pc.green >> g_green_shift_r) << g_green_shift_l)          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
361                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));  } \
362    
363    #define SPLITCOLOUR24(colour, rv) \
364    { \
365            rv.blue = (colour & 0xff0000) >> 16; \
366            rv.green = (colour & 0x00ff00) >> 8; \
367            rv.red = (colour & 0x0000ff); \
368  }  }
369    
370    #define MAKECOLOUR(pc) \
371            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
372                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
373                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
374    
375  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
376  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
377  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
378                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
379    
380    /* The following macros output the same octet sequences
381       on both BE and LE hosts: */
382    
383    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
384    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
385    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
386    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
387    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
388    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
389    
390  static uint32  static uint32
391  translate_colour(uint32 colour)  translate_colour(uint32 colour)
392  {  {
393          PixelColour pc;          PixelColour pc;
394          switch (g_server_bpp)          switch (g_server_depth)
395          {          {
396                  case 15:                  case 15:
397                          pc = split_colour15(colour);                          SPLITCOLOUR15(colour, pc);
398                          break;                          break;
399                  case 16:                  case 16:
400                          pc = split_colour16(colour);                          SPLITCOLOUR16(colour, pc);
401                          break;                          break;
402                  case 24:                  case 24:
403                          pc = split_colour24(colour);                          SPLITCOLOUR24(colour, pc);
404                            break;
405                    default:
406                            /* Avoid warning */
407                            pc.red = 0;
408                            pc.green = 0;
409                            pc.blue = 0;
410                          break;                          break;
411          }          }
412          return make_colour(pc);          return MAKECOLOUR(pc);
413  }  }
414    
415  /* indent is confused by UNROLL8 */  /* indent is confused by UNROLL8 */
# Line 251  translate_colour(uint32 colour) Line 429  translate_colour(uint32 colour)
429          while (out < end) \          while (out < end) \
430                  { stm } \                  { stm } \
431  }  }
432    /* 3 byte output repeat */
433    #define REPEAT3(stm) \
434    { \
435            while (out <= end - 8 * 3) \
436                    UNROLL8(stm) \
437            while (out < end) \
438                    { stm } \
439    }
440  /* 4 byte output repeat */  /* 4 byte output repeat */
441  #define REPEAT4(stm) \  #define REPEAT4(stm) \
442  { \  { \
# Line 259  translate_colour(uint32 colour) Line 445  translate_colour(uint32 colour)
445          while (out < end) \          while (out < end) \
446                  { stm } \                  { stm } \
447  }  }
448    /* *INDENT-ON* */
449    
450  static void  static void
451  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
452  {  {
453          while (out < end)          while (out < end)
454                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
455  }  }
456    
457  static void  static void
458  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
459  {  {
460          uint16 value;          uint16 value;
461    
462          if (g_arch_match)          if (g_compatible_arch)
463          {          {
464                    /* *INDENT-OFF* */
465                  REPEAT2                  REPEAT2
466                  (                  (
467                          *((uint16 *) out) = g_colmap[*(data++)];                          *((uint16 *) out) = g_colmap[*(data++)];
468                          out += 2;                          out += 2;
469                  )                  )
470                    /* *INDENT-ON* */
471          }          }
472          else if (g_xserver_be)          else if (g_xserver_be)
473          {          {
474                  while (out < end)                  while (out < end)
475                  {                  {
476                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
477                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
478                  }                  }
479          }          }
480          else          else
# Line 294  translate8to16(uint8 * data, uint8 * out Line 482  translate8to16(uint8 * data, uint8 * out
482                  while (out < end)                  while (out < end)
483                  {                  {
484                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
485                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
486                  }                  }
487          }          }
488  }  }
489    
490  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
491  static void  static void
492  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
493  {  {
494          uint32 value;          uint32 value;
495    
496          if (g_xserver_be)          if (g_compatible_arch)
497          {          {
498                  while (out < end)                  while (out < end)
499                  {                  {
500                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
501                          *(out++) = value >> 16;                          BOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
502                  }                  }
503          }          }
504          else          else
# Line 321  translate8to24(uint8 * data, uint8 * out Line 506  translate8to24(uint8 * data, uint8 * out
506                  while (out < end)                  while (out < end)
507                  {                  {
508                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
509                          *(out++) = value;                          LOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
510                  }                  }
511          }          }
512  }  }
513    
514  static void  static void
515  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
516  {  {
517          uint32 value;          uint32 value;
518    
519          if (g_arch_match)          if (g_compatible_arch)
520          {          {
521                    /* *INDENT-OFF* */
522                  REPEAT4                  REPEAT4
523                  (                  (
524                          *((uint32 *) out) = g_colmap[*(data++)];                          *((uint32 *) out) = g_colmap[*(data++)];
525                          out += 4;                          out += 4;
526                  )                  )
527                    /* *INDENT-ON* */
528          }          }
529          else if (g_xserver_be)          else if (g_xserver_be)
530          {          {
531                  while (out < end)                  while (out < end)
532                  {                  {
533                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
534                          *(out++) = value >> 24;                          BOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 8;  
                         *(out++) = value;  
535                  }                  }
536          }          }
537          else          else
# Line 357  translate8to32(uint8 * data, uint8 * out Line 539  translate8to32(uint8 * data, uint8 * out
539                  while (out < end)                  while (out < end)
540                  {                  {
541                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
542                          *(out++) = value;                          LOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
543                  }                  }
544          }          }
545  }  }
546    
 /* *INDENT-ON* */  
   
547  static void  static void
548  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
549  {  {
550          uint16 pixel;          uint16 pixel;
551          uint16 value;          uint16 value;
552            PixelColour pc;
553    
554          while (out < end)          if (g_xserver_be)
555          {          {
556                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel);  
                 }  
   
                 value = make_colour(split_colour15(pixel));  
   
                 if (g_xserver_be)  
557                  {                  {
558                          *(out++) = value >> 8;                          pixel = *(data++);
559                          *(out++) = value;                          if (g_host_be)
560                            {
561                                    BSWAP16(pixel);
562                            }
563                            SPLITCOLOUR15(pixel, pc);
564                            value = MAKECOLOUR(pc);
565                            BOUT16(out, value);
566                  }                  }
567                  else          }
568            else
569            {
570                    while (out < end)
571                  {                  {
572                          *(out++) = value;                          pixel = *(data++);
573                          *(out++) = value >> 8;                          if (g_host_be)
574                            {
575                                    BSWAP16(pixel);
576                            }
577                            SPLITCOLOUR15(pixel, pc);
578                            value = MAKECOLOUR(pc);
579                            LOUT16(out, value);
580                  }                  }
581          }          }
582  }  }
583    
584  static void  static void
585  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
586  {  {
587          uint32 value;          uint32 value;
588          uint16 pixel;          uint16 pixel;
589            PixelColour pc;
590    
591          while (out < end)          if (g_compatible_arch)
592          {          {
593                  pixel = *(data++);                  /* *INDENT-OFF* */
594                    REPEAT3
595                  if (g_host_be)                  (
596                  {                          pixel = *(data++);
597                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
598                  }                          *(out++) = pc.blue;
599                            *(out++) = pc.green;
600                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
601                  if (g_xserver_be)                  )
602                    /* *INDENT-ON* */
603            }
604            else if (g_xserver_be)
605            {
606                    while (out < end)
607                  {                  {
608                          *(out++) = value >> 16;                          pixel = *(data++);
609                          *(out++) = value >> 8;                          if (g_host_be)
610                          *(out++) = value;                          {
611                                    BSWAP16(pixel);
612                            }
613                            SPLITCOLOUR15(pixel, pc);
614                            value = MAKECOLOUR(pc);
615                            BOUT24(out, value);
616                  }                  }
617                  else          }
618            else
619            {
620                    while (out < end)
621                  {                  {
622                          *(out++) = value;                          pixel = *(data++);
623                          *(out++) = value >> 8;                          if (g_host_be)
624                          *(out++) = value >> 16;                          {
625                                    BSWAP16(pixel);
626                            }
627                            SPLITCOLOUR15(pixel, pc);
628                            value = MAKECOLOUR(pc);
629                            LOUT24(out, value);
630                  }                  }
631          }          }
632  }  }
633    
634  static void  static void
635  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
636  {  {
637          uint16 pixel;          uint16 pixel;
638          uint32 value;          uint32 value;
639            PixelColour pc;
640    
641          while (out < end)          if (g_compatible_arch)
642          {          {
643                  pixel = *(data++);                  /* *INDENT-OFF* */
644                    REPEAT4
645                  if (g_host_be)                  (
646                  {                          pixel = *(data++);
647                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
648                  }                          *(out++) = pc.blue;
649                            *(out++) = pc.green;
650                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
651                            *(out++) = 0;
652                  if (g_xserver_be)                  )
653                    /* *INDENT-ON* */
654            }
655            else if (g_xserver_be)
656            {
657                    while (out < end)
658                  {                  {
659                          *(out++) = value >> 24;                          pixel = *(data++);
660                          *(out++) = value >> 16;                          if (g_host_be)
661                          *(out++) = value >> 8;                          {
662                          *(out++) = value;                                  BSWAP16(pixel);
663                            }
664                            SPLITCOLOUR15(pixel, pc);
665                            value = MAKECOLOUR(pc);
666                            BOUT32(out, value);
667                  }                  }
668                  else          }
669            else
670            {
671                    while (out < end)
672                  {                  {
673                          *(out++) = value;                          pixel = *(data++);
674                          *(out++) = value >> 8;                          if (g_host_be)
675                          *(out++) = value >> 16;                          {
676                          *(out++) = value >> 24;                                  BSWAP16(pixel);
677                            }
678                            SPLITCOLOUR15(pixel, pc);
679                            value = MAKECOLOUR(pc);
680                            LOUT32(out, value);
681                  }                  }
682          }          }
683  }  }
684    
685  static void  static void
686  translate16to16(uint16 * data, uint8 * out, uint8 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
687  {  {
688          uint16 pixel;          uint16 pixel;
689          uint16 value;          uint16 value;
690            PixelColour pc;
691    
692          while (out < end)          if (g_xserver_be)
693          {          {
                 pixel = *(data++);  
   
694                  if (g_host_be)                  if (g_host_be)
695                  {                  {
696                          BSWAP16(pixel);                          while (out < end)
697                            {
698                                    pixel = *(data++);
699                                    BSWAP16(pixel);
700                                    SPLITCOLOUR16(pixel, pc);
701                                    value = MAKECOLOUR(pc);
702                                    BOUT16(out, value);
703                            }
704                  }                  }
705                    else
706                  value = make_colour(split_colour16(pixel));                  {
707                            while (out < end)
708                  if (g_xserver_be)                          {
709                                    pixel = *(data++);
710                                    SPLITCOLOUR16(pixel, pc);
711                                    value = MAKECOLOUR(pc);
712                                    BOUT16(out, value);
713                            }
714                    }
715            }
716            else
717            {
718                    if (g_host_be)
719                  {                  {
720                          *(out++) = value >> 8;                          while (out < end)
721                          *(out++) = value;                          {
722                                    pixel = *(data++);
723                                    BSWAP16(pixel);
724                                    SPLITCOLOUR16(pixel, pc);
725                                    value = MAKECOLOUR(pc);
726                                    LOUT16(out, value);
727                            }
728                  }                  }
729                  else                  else
730                  {                  {
731                          *(out++) = value;                          while (out < end)
732                          *(out++) = value >> 8;                          {
733                                    pixel = *(data++);
734                                    SPLITCOLOUR16(pixel, pc);
735                                    value = MAKECOLOUR(pc);
736                                    LOUT16(out, value);
737                            }
738                  }                  }
739          }          }
740  }  }
741    
742  static void  static void
743  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
744  {  {
745          uint32 value;          uint32 value;
746          uint16 pixel;          uint16 pixel;
747            PixelColour pc;
748    
749          while (out < end)          if (g_compatible_arch)
750            {
751                    /* *INDENT-OFF* */
752                    REPEAT3
753                    (
754                            pixel = *(data++);
755                            SPLITCOLOUR16(pixel, pc);
756                            *(out++) = pc.blue;
757                            *(out++) = pc.green;
758                            *(out++) = pc.red;
759                    )
760                    /* *INDENT-ON* */
761            }
762            else if (g_xserver_be)
763          {          {
                 pixel = *(data++);  
   
764                  if (g_host_be)                  if (g_host_be)
765                  {                  {
766                          BSWAP16(pixel);                          while (out < end)
767                            {
768                                    pixel = *(data++);
769                                    BSWAP16(pixel);
770                                    SPLITCOLOUR16(pixel, pc);
771                                    value = MAKECOLOUR(pc);
772                                    BOUT24(out, value);
773                            }
774                  }                  }
775                    else
776                  value = make_colour(split_colour16(pixel));                  {
777                            while (out < end)
778                  if (g_xserver_be)                          {
779                                    pixel = *(data++);
780                                    SPLITCOLOUR16(pixel, pc);
781                                    value = MAKECOLOUR(pc);
782                                    BOUT24(out, value);
783                            }
784                    }
785            }
786            else
787            {
788                    if (g_host_be)
789                  {                  {
790                          *(out++) = value >> 16;                          while (out < end)
791                          *(out++) = value >> 8;                          {
792                          *(out++) = value;                                  pixel = *(data++);
793                                    BSWAP16(pixel);
794                                    SPLITCOLOUR16(pixel, pc);
795                                    value = MAKECOLOUR(pc);
796                                    LOUT24(out, value);
797                            }
798                  }                  }
799                  else                  else
800                  {                  {
801                          *(out++) = value;                          while (out < end)
802                          *(out++) = value >> 8;                          {
803                          *(out++) = value >> 16;                                  pixel = *(data++);
804                                    SPLITCOLOUR16(pixel, pc);
805                                    value = MAKECOLOUR(pc);
806                                    LOUT24(out, value);
807                            }
808                  }                  }
809          }          }
810  }  }
811    
812  static void  static void
813  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
814  {  {
815          uint16 pixel;          uint16 pixel;
816          uint32 value;          uint32 value;
817            PixelColour pc;
818    
819          while (out < end)          if (g_compatible_arch)
820            {
821                    /* *INDENT-OFF* */
822                    REPEAT4
823                    (
824                            pixel = *(data++);
825                            SPLITCOLOUR16(pixel, pc);
826                            *(out++) = pc.blue;
827                            *(out++) = pc.green;
828                            *(out++) = pc.red;
829                            *(out++) = 0;
830                    )
831                    /* *INDENT-ON* */
832            }
833            else if (g_xserver_be)
834          {          {
                 pixel = *(data++);  
   
835                  if (g_host_be)                  if (g_host_be)
836                  {                  {
837                          BSWAP16(pixel);                          while (out < end)
838                            {
839                                    pixel = *(data++);
840                                    BSWAP16(pixel);
841                                    SPLITCOLOUR16(pixel, pc);
842                                    value = MAKECOLOUR(pc);
843                                    BOUT32(out, value);
844                            }
845                  }                  }
846                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
847                  {                  {
848                          *(out++) = value >> 24;                          while (out < end)
849                          *(out++) = value >> 16;                          {
850                          *(out++) = value >> 8;                                  pixel = *(data++);
851                          *(out++) = value;                                  SPLITCOLOUR16(pixel, pc);
852                                    value = MAKECOLOUR(pc);
853                                    BOUT32(out, value);
854                            }
855                    }
856            }
857            else
858            {
859                    if (g_host_be)
860                    {
861                            while (out < end)
862                            {
863                                    pixel = *(data++);
864                                    BSWAP16(pixel);
865                                    SPLITCOLOUR16(pixel, pc);
866                                    value = MAKECOLOUR(pc);
867                                    LOUT32(out, value);
868                            }
869                  }                  }
870                  else                  else
871                  {                  {
872                          *(out++) = value;                          while (out < end)
873                          *(out++) = value >> 8;                          {
874                          *(out++) = value >> 16;                                  pixel = *(data++);
875                          *(out++) = value >> 24;                                  SPLITCOLOUR16(pixel, pc);
876                                    value = MAKECOLOUR(pc);
877                                    LOUT32(out, value);
878                            }
879                  }                  }
880          }          }
881  }  }
882    
883  static void  static void
884  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
885  {  {
886          uint32 pixel = 0;          uint32 pixel = 0;
887          uint16 value;          uint16 value;
888            PixelColour pc;
889    
890          while (out < end)          while (out < end)
891          {          {
892                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
893                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
894                  pixel |= *(data++);                  pixel |= *(data++);
895                    SPLITCOLOUR24(pixel, pc);
896                  value = (uint16) make_colour(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
897                  if (g_xserver_be)                  if (g_xserver_be)
898                  {                  {
899                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
900                  }                  }
901                  else                  else
902                  {                  {
903                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
904                  }                  }
905          }          }
906  }  }
907    
908  static void  static void
909  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
910  {  {
911          uint32 pixel;          uint32 pixel;
912          uint32 value;          uint32 value;
913            PixelColour pc;
914    
915          while (out < end)          if (g_xserver_be)
916          {          {
917                  pixel = *(data++) << 16;                  while (out < end)
                 pixel |= *(data++) << 8;  
                 pixel |= *(data++);  
   
                 value = make_colour(split_colour24(pixel));  
   
                 if (g_xserver_be)  
918                  {                  {
919                          *(out++) = value >> 16;                          pixel = *(data++) << 16;
920                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
921                          *(out++) = value;                          pixel |= *(data++);
922                            SPLITCOLOUR24(pixel, pc);
923                            value = MAKECOLOUR(pc);
924                            BOUT24(out, value);
925                  }                  }
926                  else          }
927            else
928            {
929                    while (out < end)
930                  {                  {
931                          *(out++) = value;                          pixel = *(data++) << 16;
932                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
933                          *(out++) = value >> 16;                          pixel |= *(data++);
934                            SPLITCOLOUR24(pixel, pc);
935                            value = MAKECOLOUR(pc);
936                            LOUT24(out, value);
937                  }                  }
938          }          }
939  }  }
940    
941  static void  static void
942  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
943  {  {
944          uint32 pixel;          uint32 pixel;
945          uint32 value;          uint32 value;
946            PixelColour pc;
947    
948          while (out < end)          if (g_compatible_arch)
949          {          {
950                  pixel = *(data++) << 16;                  /* *INDENT-OFF* */
951                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
952                  pixel |= *(data++);                  REPEAT4
953                    (
954                  value = make_colour(split_colour24(pixel));                          *(out++) = *(data++);
955                            *(out++) = *(data++);
956                  if (g_xserver_be)                          *(out++) = *(data++);
957                            *(out++) = 0;
958                    )
959    #else
960                    REPEAT4
961                    (
962                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
963                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
964                     out += 4;
965                     data += 3;
966                    )
967    #endif
968                    /* *INDENT-ON* */
969            }
970            else if (g_xserver_be)
971            {
972                    while (out < end)
973                  {                  {
974                          *(out++) = value >> 24;                          pixel = *(data++) << 16;
975                          *(out++) = value >> 16;                          pixel |= *(data++) << 8;
976                          *(out++) = value >> 8;                          pixel |= *(data++);
977                          *(out++) = value;                          SPLITCOLOUR24(pixel, pc);
978                            value = MAKECOLOUR(pc);
979                            BOUT32(out, value);
980                  }                  }
981                  else          }
982            else
983            {
984                    while (out < end)
985                  {                  {
986                          *(out++) = value;                          pixel = *(data++) << 16;
987                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
988                          *(out++) = value >> 16;                          pixel |= *(data++);
989                          *(out++) = value >> 24;                          SPLITCOLOUR24(pixel, pc);
990                            value = MAKECOLOUR(pc);
991                            LOUT32(out, value);
992                  }                  }
993          }          }
994  }  }
# Line 651  translate_image(int width, int height, u Line 1000  translate_image(int width, int height, u
1000          uint8 *out;          uint8 *out;
1001          uint8 *end;          uint8 *end;
1002    
1003          /* if server and xserver bpp match, */          /*
1004          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
1005          /* just return data */             and arch(endian) matches, no need to translate:
1006          if (g_arch_match)             just return data.
1007               Note: select_visual should've already ensured g_no_translate
1008               is only set for compatible depths, but the RDP depth might've
1009               changed during connection negotiations.
1010             */
1011            if (g_no_translate_image)
1012          {          {
1013                  if (g_depth == 15 && g_server_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
1014                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
1015                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
1016                          return data;                          return data;
1017          }          }
1018    
# Line 666  translate_image(int width, int height, u Line 1020  translate_image(int width, int height, u
1020          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
1021          end = out + size;          end = out + size;
1022    
1023          switch (g_server_bpp)          switch (g_server_depth)
1024          {          {
1025                  case 24:                  case 24:
1026                          switch (g_bpp)                          switch (g_bpp)
# Line 764  calculate_shifts(uint32 mask, int *shift Line 1118  calculate_shifts(uint32 mask, int *shift
1118          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
1119  }  }
1120    
1121  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1122  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1123     */
1124    static unsigned
1125    calculate_mask_weight(uint32 mask)
1126    {
1127            unsigned weight = 0;
1128            do
1129            {
1130                    weight += (mask & 1);
1131            }
1132            while (mask >>= 1);
1133            return weight;
1134    }
1135    
1136    static BOOL
1137    select_visual()
1138  {  {
         XVisualInfo vi;  
1139          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1140          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1141          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1142          XVisualInfo template;          XVisualInfo template;
1143          Bool TrueColorVisual = False;          int i;
1144            unsigned red_weight, blue_weight, green_weight;
1145    
1146          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1147          if (g_display == NULL)  
1148            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1149            if (pfm == NULL)
1150          {          {
1151                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1152                    XCloseDisplay(g_display);
1153                  return False;                  return False;
1154          }          }
1155    
1156          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 */  
1157          template.class = TrueColor;          template.class = TrueColor;
1158          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1159            g_visual = NULL;
1160            g_no_translate_image = False;
1161            g_compatible_arch = False;
1162            if (vmatches != NULL)
1163            {
1164                    for (i = 0; i < visuals_count; ++i)
1165                    {
1166                            XVisualInfo *visual_info = &vmatches[i];
1167    
1168                            /* Try to find a no-translation visual that'll
1169                               allow us to use RDP bitmaps directly as ZPixmaps. */
1170                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1171                                                   /* R5G5B5 */
1172                                                   (visual_info->red_mask == 0x7c00) &&
1173                                                   (visual_info->green_mask == 0x3e0) &&
1174                                                   (visual_info->blue_mask == 0x1f)) ||
1175                                                  ((visual_info->depth == 16) &&
1176                                                   /* R5G6B5 */
1177                                                   (visual_info->red_mask == 0xf800) &&
1178                                                   (visual_info->green_mask == 0x7e0) &&
1179                                                   (visual_info->blue_mask == 0x1f)) ||
1180                                                  ((visual_info->depth == 24) &&
1181                                                   /* R8G8B8 */
1182                                                   (visual_info->red_mask == 0xff0000) &&
1183                                                   (visual_info->green_mask == 0xff00) &&
1184                                                   (visual_info->blue_mask == 0xff))))
1185                            {
1186                                    g_visual = visual_info->visual;
1187                                    g_depth = visual_info->depth;
1188                                    g_compatible_arch = !g_host_be;
1189                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1190                                    if (g_no_translate_image)
1191                                            /* We found the best visual */
1192                                            break;
1193                            }
1194                            else
1195                            {
1196                                    g_compatible_arch = False;
1197                            }
1198    
1199          nvisuals--;                          if (visual_info->depth > 24)
1200          while (nvisuals >= 0)                          {
1201          {                                  /* Avoid 32-bit visuals and likes like the plague.
1202                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1203                  {                                     (e.g. nvidia's Composite 32-bit visual).
1204                          g_depth = (vmatches + nvisuals)->depth;                                     Most implementation offer a 24-bit visual anyway. */
1205                                    continue;
1206                            }
1207    
1208                            /* Only care for visuals, for whose BPPs (not depths!)
1209                               we have a translateXtoY function. */
1210                            BOOL can_translate_to_bpp = False;
1211                            int j;
1212                            for (j = 0; j < pixmap_formats_count; ++j)
1213                            {
1214                                    if (pfm[j].depth == visual_info->depth)
1215                                    {
1216                                            if ((pfm[j].bits_per_pixel == 16) ||
1217                                                (pfm[j].bits_per_pixel == 24) ||
1218                                                (pfm[j].bits_per_pixel == 32))
1219                                            {
1220                                                    can_translate_to_bpp = True;
1221                                            }
1222                                            break;
1223                                    }
1224                            }
1225    
1226                            /* Prefer formats which have the most colour depth.
1227                               We're being truly aristocratic here, minding each
1228                               weight on its own. */
1229                            if (can_translate_to_bpp)
1230                            {
1231                                    unsigned vis_red_weight =
1232                                            calculate_mask_weight(visual_info->red_mask);
1233                                    unsigned vis_green_weight =
1234                                            calculate_mask_weight(visual_info->green_mask);
1235                                    unsigned vis_blue_weight =
1236                                            calculate_mask_weight(visual_info->blue_mask);
1237                                    if ((vis_red_weight >= red_weight)
1238                                        && (vis_green_weight >= green_weight)
1239                                        && (vis_blue_weight >= blue_weight))
1240                                    {
1241                                            red_weight = vis_red_weight;
1242                                            green_weight = vis_green_weight;
1243                                            blue_weight = vis_blue_weight;
1244                                            g_visual = visual_info->visual;
1245                                            g_depth = visual_info->depth;
1246                                    }
1247                            }
1248                  }                  }
1249                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1250          }          }
1251    
1252          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)))  
1253          {          {
1254                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1255                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1256                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1257                    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;  
                 }  
1258          }          }
1259          else          else
1260          {          {
1261                  /* need a truecolour visual */                  template.class = PseudoColor;
1262                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1263                  {                  template.colormap_size = 256;
1264                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1265                            XGetVisualInfo(g_display,
1266                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1267                                           &template, &visuals_count);
1268                    if (vmatches == NULL)
1269                    {
1270                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1271                            XCloseDisplay(g_display);
1272                            XFree(pfm);
1273                          return False;                          return False;
1274                  }                  }
1275    
1276                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1277                  g_owncolmap = False;                  g_owncolmap = True;
1278                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1279                  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;  
1280          }          }
1281    
1282          pfm = XListPixmapFormats(g_display, &i);          g_bpp = 0;
1283          if (pfm != NULL)          for (i = 0; i < pixmap_formats_count; ++i)
1284          {          {
1285                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1286                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1287                  {                  {
1288                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1289    
1290                            if (g_no_translate_image)
1291                          {                          {
1292                                  g_bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1293                                    {
1294                                            case 15:
1295                                            case 16:
1296                                                    if (g_bpp != 16)
1297                                                            g_no_translate_image = False;
1298                                                    break;
1299                                            case 24:
1300                                                    /* Yes, this will force image translation
1301                                                       on most modern servers which use 32 bits
1302                                                       for R8G8B8. */
1303                                                    if (g_bpp != 24)
1304                                                            g_no_translate_image = False;
1305                                                    break;
1306                                            default:
1307                                                    g_no_translate_image = False;
1308                                                    break;
1309                                    }
1310                          }                          }
1311    
1312                            /* Pixmap formats list is a depth-to-bpp mapping --
1313                               there's just a single entry for every depth,
1314                               so we can safely break here */
1315                            break;
1316                  }                  }
1317                  XFree(pfm);          }
1318            XFree(pfm);
1319            pfm = NULL;
1320            return True;
1321    }
1322    
1323    BOOL
1324    ui_init(void)
1325    {
1326            int screen_num;
1327    
1328            g_display = XOpenDisplay(NULL);
1329            if (g_display == NULL)
1330            {
1331                    error("Failed to open display: %s\n", XDisplayName(NULL));
1332                    return False;
1333          }          }
1334    
         if (g_bpp < 8)  
1335          {          {
1336                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1337                  XCloseDisplay(g_display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1338            }
1339    
1340            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1341            screen_num = DefaultScreen(g_display);
1342            g_x_socket = ConnectionNumber(g_display);
1343            g_screen = ScreenOfDisplay(g_display, screen_num);
1344            g_depth = DefaultDepthOfScreen(g_screen);
1345    
1346            if (!select_visual())
1347                  return False;                  return False;
1348    
1349            if (g_no_translate_image)
1350            {
1351                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1352          }          }
1353    
1354            if (g_server_depth > g_bpp)
1355            {
1356                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1357                            g_server_depth, g_bpp);
1358            }
1359    
1360            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1361                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1362    
1363          if (!g_owncolmap)          if (!g_owncolmap)
1364          {          {
1365                  g_xcolmap =                  g_xcolmap =
1366                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1367                                          AllocNone);                                          AllocNone);
1368                  if (g_depth <= 8)                  if (g_depth <= 8)
1369                          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);
1370          }          }
1371    
1372          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1373          {          {
1374                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1375                  g_ownbackstore = True;                  g_ownbackstore = True;
1376          }          }
1377    
# Line 883  ui_init(void) Line 1382  ui_init(void)
1382          {          {
1383                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1384                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1385                    g_using_full_workarea = True;
1386          }          }
1387          else if (g_width < 0)          else if (g_width < 0)
1388          {          {
1389                  /* Percent of screen */                  /* Percent of screen */
1390                    if (-g_width >= 100)
1391                            g_using_full_workarea = True;
1392                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1393                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1394          }          }
# Line 894  ui_init(void) Line 1396  ui_init(void)
1396          {          {
1397                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1398                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1399                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1400                  {                  {
1401                          g_width = cx;                          g_width = cx;
1402                          g_height = cy;                          g_height = cy;
1403                            g_using_full_workarea = True;
1404                  }                  }
1405                  else                  else
1406                  {                  {
1407                          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");
1408                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1409                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1410                  }                  }
1411          }          }
1412    
# Line 919  ui_init(void) Line 1421  ui_init(void)
1421                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1422    
1423          xclip_init();          xclip_init();
1424            ewmh_init();
1425            if (g_seamless_rdp)
1426                    seamless_init();
1427    
1428          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));
1429    
1430          return True;          return True;
1431  }  }
# Line 944  ui_deinit(void) Line 1449  ui_deinit(void)
1449          g_display = NULL;          g_display = NULL;
1450  }  }
1451    
1452    
1453    static void
1454    get_window_attribs(XSetWindowAttributes * attribs)
1455    {
1456            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1457            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1458            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1459            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1460            attribs->override_redirect = g_fullscreen;
1461            attribs->colormap = g_xcolmap;
1462    }
1463    
1464    static void
1465    get_input_mask(long *input_mask)
1466    {
1467            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1468                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1469    
1470            if (g_sendmotion)
1471                    *input_mask |= PointerMotionMask;
1472            if (g_ownbackstore)
1473                    *input_mask |= ExposureMask;
1474            if (g_fullscreen || g_grab_keyboard)
1475                    *input_mask |= EnterWindowMask;
1476            if (g_grab_keyboard)
1477                    *input_mask |= LeaveWindowMask;
1478    }
1479    
1480  BOOL  BOOL
1481  ui_create_window(void)  ui_create_window(void)
1482  {  {
# Line 960  ui_create_window(void) Line 1493  ui_create_window(void)
1493          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1494          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1495    
1496          attribs.background_pixel = BlackPixelOfScreen(g_screen);          /* Handle -x-y portion of geometry string */
1497          attribs.border_pixel = WhitePixelOfScreen(g_screen);          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1498          attribs.backing_store = g_ownbackstore ? NotUseful : Always;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1499          attribs.override_redirect = g_fullscreen;          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1500          attribs.colormap = g_xcolmap;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1501    
1502          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth, wndheight,          get_window_attribs(&attribs);
1503                                0, g_depth, InputOutput, g_visual,  
1504                                CWBackPixel | CWBackingStore | CWOverrideRedirect |          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1505                                CWColormap | CWBorderPixel, &attribs);                                wndheight, 0, g_depth, InputOutput, g_visual,
1506                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1507                                  CWBorderPixel, &attribs);
1508    
1509          if (g_gc == NULL)          if (g_gc == NULL)
1510            {
1511                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1512                    ui_reset_clip();
1513            }
1514    
1515          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1516                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 989  ui_create_window(void) Line 1527  ui_create_window(void)
1527          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1528    
1529          if (g_hide_decorations)          if (g_hide_decorations)
1530                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1531    
1532          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1533          if (classhints != NULL)          if (classhints != NULL)
# Line 1003  ui_create_window(void) Line 1541  ui_create_window(void)
1541          if (sizehints)          if (sizehints)
1542          {          {
1543                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1544                    if (g_pos)
1545                            sizehints->flags |= PPosition;
1546                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1547                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1548                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
# Line 1014  ui_create_window(void) Line 1554  ui_create_window(void)
1554                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1555          }          }
1556    
1557          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;  
1558    
1559          if (g_IM != NULL)          if (g_IM != NULL)
1560          {          {
# Line 1037  ui_create_window(void) Line 1567  ui_create_window(void)
1567          }          }
1568    
1569          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
         XMapWindow(g_display, g_wnd);  
1570    
1571            XMapWindow(g_display, g_wnd);
1572          /* wait for VisibilityNotify */          /* wait for VisibilityNotify */
1573          do          do
1574          {          {
# Line 1109  xwin_toggle_fullscreen(void) Line 1639  xwin_toggle_fullscreen(void)
1639  {  {
1640          Pixmap contents = 0;          Pixmap contents = 0;
1641    
1642            if (g_seamless_active)
1643                    /* Turn off SeamlessRDP mode */
1644                    ui_seamless_toggle();
1645    
1646          if (!g_ownbackstore)          if (!g_ownbackstore)
1647          {          {
1648                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1129  xwin_toggle_fullscreen(void) Line 1663  xwin_toggle_fullscreen(void)
1663          }          }
1664  }  }
1665    
1666  /* Process all events in Xlib queue  static void
1667    handle_button_event(XEvent xevent, BOOL down)
1668    {
1669            uint16 button, flags = 0;
1670            g_last_gesturetime = xevent.xbutton.time;
1671            button = xkeymap_translate_button(xevent.xbutton.button);
1672            if (button == 0)
1673                    return;
1674    
1675            if (down)
1676                    flags = MOUSE_FLAG_DOWN;
1677    
1678            /* Stop moving window when button is released, regardless of cursor position */
1679            if (g_moving_wnd && (xevent.type == ButtonRelease))
1680                    g_moving_wnd = False;
1681    
1682            /* If win_button_size is nonzero, enable single app mode */
1683            if (xevent.xbutton.y < g_win_button_size)
1684            {
1685                    /*  Check from right to left: */
1686                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1687                    {
1688                            /* The close button, continue */
1689                            ;
1690                    }
1691                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1692                    {
1693                            /* The maximize/restore button. Do not send to
1694                               server.  It might be a good idea to change the
1695                               cursor or give some other visible indication
1696                               that rdesktop inhibited this click */
1697                            if (xevent.type == ButtonPress)
1698                                    return;
1699                    }
1700                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1701                    {
1702                            /* The minimize button. Iconify window. */
1703                            if (xevent.type == ButtonRelease)
1704                            {
1705                                    /* Release the mouse button outside the minimize button, to prevent the
1706                                       actual minimazation to happen */
1707                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1708                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1709                                    return;
1710                            }
1711                    }
1712                    else if (xevent.xbutton.x <= g_win_button_size)
1713                    {
1714                            /* The system menu. Ignore. */
1715                            if (xevent.type == ButtonPress)
1716                                    return;
1717                    }
1718                    else
1719                    {
1720                            /* The title bar. */
1721                            if (xevent.type == ButtonPress)
1722                            {
1723                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1724                                    {
1725                                            g_moving_wnd = True;
1726                                            g_move_x_offset = xevent.xbutton.x;
1727                                            g_move_y_offset = xevent.xbutton.y;
1728                                    }
1729                                    return;
1730                            }
1731                    }
1732            }
1733    
1734            if (xevent.xmotion.window == g_wnd)
1735            {
1736                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1737                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1738            }
1739            else
1740            {
1741                    /* SeamlessRDP */
1742                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1743                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1744            }
1745    }
1746    
1747    static void
1748    ui_seamless_handle_restack(seamless_window * sw)
1749    {
1750            Status status;
1751            Window root, parent, *children;
1752            unsigned int nchildren, i;
1753            seamless_window *sw_below;
1754    
1755            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
1756                                &root, &parent, &children, &nchildren);
1757            if (!status || !nchildren)
1758                    return;
1759    
1760            sw_below = NULL;
1761    
1762            i = 0;
1763            while (children[i] != sw->wnd)
1764            {
1765                    i++;
1766                    if (i >= nchildren)
1767                            return;
1768            }
1769    
1770            for (i++; i < nchildren; i++)
1771            {
1772                    sw_below = seamless_get_window_by_wnd(children[i]);
1773                    if (sw_below)
1774                            break;
1775            }
1776    
1777            if (sw_below)
1778                    seamless_send_zchange(sw->id, sw_below->id, 0);
1779            else
1780                    seamless_send_zchange(sw->id, 0, 0);
1781    }
1782    
1783    /* Process events in Xlib queue
1784     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1785  static int  static int
1786  xwin_process_events(void)  xwin_process_events(void)
1787  {  {
1788          XEvent xevent;          XEvent xevent;
1789          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1790          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1791          char str[256];          char str[256];
1792          Status status;          Status status;
1793            int events = 0;
1794            seamless_window *sw;
1795    
1796          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1797          {          {
1798                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1799    
# Line 1152  xwin_process_events(void) Line 1803  xwin_process_events(void)
1803                          continue;                          continue;
1804                  }                  }
1805    
                 flags = 0;  
   
1806                  switch (xevent.type)                  switch (xevent.type)
1807                  {                  {
1808                          case VisibilityNotify:                          case VisibilityNotify:
1809                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1810                                            g_Unobscured =
1811                                                    xevent.xvisibility.state == VisibilityUnobscured;
1812    
1813                                  break;                                  break;
1814                          case ClientMessage:                          case ClientMessage:
1815                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1190  xwin_process_events(void) Line 1842  xwin_process_events(void)
1842                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1843                                  }                                  }
1844    
1845                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1846                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1847    
1848                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1849                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1850                                          break;                                          break;
1851    
1852                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1853                                                             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);  
   
1854                                  break;                                  break;
1855    
1856                          case KeyRelease:                          case KeyRelease:
# Line 1215  xwin_process_events(void) Line 1858  xwin_process_events(void)
1858                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1859                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1860    
1861                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1862                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1863    
1864                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1865                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1866                                          break;                                          break;
1867    
1868                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1869                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1870                                  break;                                  break;
1871    
1872                          case ButtonPress:                          case ButtonPress:
1873                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1874                                  /* fall through */                                  break;
1875    
1876                          case ButtonRelease:                          case ButtonRelease:
1877                                  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);  
1878                                  break;                                  break;
1879    
1880                          case MotionNotify:                          case MotionNotify:
# Line 1308  xwin_process_events(void) Line 1889  xwin_process_events(void)
1889                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1890                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1891                                                         CurrentTime);                                                         CurrentTime);
1892                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1893                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1894                                    {
1895                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1896                                                           xevent.xmotion.x, xevent.xmotion.y);
1897                                    }
1898                                    else
1899                                    {
1900                                            /* SeamlessRDP */
1901                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1902                                                           xevent.xmotion.x_root,
1903                                                           xevent.xmotion.y_root);
1904                                    }
1905                                  break;                                  break;
1906    
1907                          case FocusIn:                          case FocusIn:
# Line 1352  xwin_process_events(void) Line 1944  xwin_process_events(void)
1944                                  break;                                  break;
1945    
1946                          case Expose:                          case Expose:
1947                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
1948                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1949                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1950                                            xevent.xexpose.height,                                                    g_gc,
1951                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1952                                                      xevent.xexpose.width, xevent.xexpose.height,
1953                                                      xevent.xexpose.x, xevent.xexpose.y);
1954                                    }
1955                                    else
1956                                    {
1957                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1958                                            if (sw)
1959                                                    XCopyArea(g_display, g_backstore,
1960                                                              xevent.xexpose.window, g_gc,
1961                                                              xevent.xexpose.x + sw->xoffset,
1962                                                              xevent.xexpose.y + sw->yoffset,
1963                                                              xevent.xexpose.width,
1964                                                              xevent.xexpose.height, xevent.xexpose.x,
1965                                                              xevent.xexpose.y);
1966                                            else
1967                                            {
1968                                                    error("Expose for unknown window 0x%lx\n",
1969                                                          xevent.xexpose.window);
1970                                            }
1971                                    }
1972    
1973                                  break;                                  break;
1974    
1975                          case MappingNotify:                          case MappingNotify:
# Line 1385  xwin_process_events(void) Line 1998  xwin_process_events(void)
1998                                  break;                                  break;
1999                          case PropertyNotify:                          case PropertyNotify:
2000                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2001                                    if (xevent.xproperty.window == g_wnd)
2002                                            break;
2003                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2004                                            break;
2005    
2006                                    /* seamless */
2007                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
2008                                    if (!sw)
2009                                            break;
2010    
2011                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2012                                        && (xevent.xproperty.state == PropertyNewValue))
2013                                    {
2014                                            sw->state = ewmh_get_window_state(sw->wnd);
2015                                            seamless_send_state(sw->id, sw->state, 0);
2016                                    }
2017    
2018                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2019                                        && (xevent.xproperty.state == PropertyNewValue))
2020                                    {
2021                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2022                                            seamless_all_to_desktop(sw->wnd, sw->desktop);
2023                                    }
2024    
2025                                    break;
2026                            case MapNotify:
2027                                    if (!g_seamless_active)
2028                                            rdp_send_client_window_status(1);
2029                                    break;
2030                            case UnmapNotify:
2031                                    if (!g_seamless_active)
2032                                            rdp_send_client_window_status(0);
2033                                  break;                                  break;
2034                            case ConfigureNotify:
2035                                    /* seamless */
2036                                    sw = seamless_get_window_by_wnd(xevent.xconfigure.window);
2037                                    if (!sw)
2038                                            break;
2039    
2040                                    ui_seamless_handle_restack(sw);
2041                  }                  }
2042          }          }
2043          /* Keep going */          /* Keep going */
# Line 1469  ui_create_bitmap(int width, int height, Line 2121  ui_create_bitmap(int width, int height,
2121          uint8 *tdata;          uint8 *tdata;
2122          int bitmap_pad;          int bitmap_pad;
2123    
2124          if (g_server_bpp == 8)          if (g_server_depth == 8)
2125          {          {
2126                  bitmap_pad = 8;                  bitmap_pad = 8;
2127          }          }
# Line 1501  ui_paint_bitmap(int x, int y, int cx, in Line 2153  ui_paint_bitmap(int x, int y, int cx, in
2153          uint8 *tdata;          uint8 *tdata;
2154          int bitmap_pad;          int bitmap_pad;
2155    
2156          if (g_server_bpp == 8)          if (g_server_depth == 8)
2157          {          {
2158                  bitmap_pad = 8;                  bitmap_pad = 8;
2159          }          }
# Line 1521  ui_paint_bitmap(int x, int y, int cx, in Line 2173  ui_paint_bitmap(int x, int y, int cx, in
2173          {          {
2174                  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);
2175                  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);
2176                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2177                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2178                                             x - sw->xoffset, y - sw->yoffset));
2179          }          }
2180          else          else
2181          {          {
2182                  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);
2183                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2184                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2185                                             x - sw->xoffset, y - sw->yoffset));
2186          }          }
2187    
2188          XFree(image);          XFree(image);
# Line 1645  ui_set_cursor(HCURSOR cursor) Line 2303  ui_set_cursor(HCURSOR cursor)
2303  {  {
2304          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2305          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2306            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2307  }  }
2308    
2309  void  void
# Line 1786  ui_set_colourmap(HCOLOURMAP map) Line 2445  ui_set_colourmap(HCOLOURMAP map)
2445                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2446          }          }
2447          else          else
2448            {
2449                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2450                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2451            }
2452  }  }
2453    
2454  void  void
2455  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2456  {  {
2457          XRectangle rect;          g_clip_rectangle.x = x;
2458            g_clip_rectangle.y = y;
2459          rect.x = x;          g_clip_rectangle.width = cx;
2460          rect.y = y;          g_clip_rectangle.height = cy;
2461          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);  
2462  }  }
2463    
2464  void  void
2465  ui_reset_clip(void)  ui_reset_clip(void)
2466  {  {
2467          XRectangle rect;          g_clip_rectangle.x = 0;
2468            g_clip_rectangle.y = 0;
2469          rect.x = 0;          g_clip_rectangle.width = g_width;
2470          rect.y = 0;          g_clip_rectangle.height = g_height;
2471          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);  
2472  }  }
2473    
2474  void  void
# Line 1891  ui_patblt(uint8 opcode, Line 2549  ui_patblt(uint8 opcode,
2549    
2550          if (g_ownbackstore)          if (g_ownbackstore)
2551                  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);
2552            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2553                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2554                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2555  }  }
2556    
2557  void  void
# Line 1901  ui_screenblt(uint8 opcode, Line 2562  ui_screenblt(uint8 opcode,
2562          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2563          if (g_ownbackstore)          if (g_ownbackstore)
2564          {          {
2565                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2566                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2567                          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);  
                 }  
2568          }          }
2569          else          else
2570          {          {
2571                  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);
2572          }          }
2573    
2574            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2575                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2576                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2577    
2578          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2579  }  }
2580    
# Line 1928  ui_memblt(uint8 opcode, Line 2585  ui_memblt(uint8 opcode,
2585  {  {
2586          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2587          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);
2588            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2589                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2590                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2591          if (g_ownbackstore)          if (g_ownbackstore)
2592                  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);
2593          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1974  ui_line(uint8 opcode, Line 2634  ui_line(uint8 opcode,
2634          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2635          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2636          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2637            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2638                                                startx - sw->xoffset, starty - sw->yoffset,
2639                                                endx - sw->xoffset, endy - sw->yoffset));
2640          if (g_ownbackstore)          if (g_ownbackstore)
2641                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2642          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1988  ui_rect( Line 2651  ui_rect(
2651          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2652  }  }
2653    
2654    void
2655    ui_polygon(uint8 opcode,
2656               /* mode */ uint8 fillmode,
2657               /* dest */ POINT * point, int npoints,
2658               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2659    {
2660            uint8 style, i, ipattern[8];
2661            Pixmap fill;
2662    
2663            SET_FUNCTION(opcode);
2664    
2665            switch (fillmode)
2666            {
2667                    case ALTERNATE:
2668                            XSetFillRule(g_display, g_gc, EvenOddRule);
2669                            break;
2670                    case WINDING:
2671                            XSetFillRule(g_display, g_gc, WindingRule);
2672                            break;
2673                    default:
2674                            unimpl("fill mode %d\n", fillmode);
2675            }
2676    
2677            if (brush)
2678                    style = brush->style;
2679            else
2680                    style = 0;
2681    
2682            switch (style)
2683            {
2684                    case 0: /* Solid */
2685                            SET_FOREGROUND(fgcolour);
2686                            FILL_POLYGON((XPoint *) point, npoints);
2687                            break;
2688    
2689                    case 2: /* Hatch */
2690                            fill = (Pixmap) ui_create_glyph(8, 8,
2691                                                            hatch_patterns + brush->pattern[0] * 8);
2692                            SET_FOREGROUND(fgcolour);
2693                            SET_BACKGROUND(bgcolour);
2694                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2695                            XSetStipple(g_display, g_gc, fill);
2696                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2697                            FILL_POLYGON((XPoint *) point, npoints);
2698                            XSetFillStyle(g_display, g_gc, FillSolid);
2699                            XSetTSOrigin(g_display, g_gc, 0, 0);
2700                            ui_destroy_glyph((HGLYPH) fill);
2701                            break;
2702    
2703                    case 3: /* Pattern */
2704                            for (i = 0; i != 8; i++)
2705                                    ipattern[7 - i] = brush->pattern[i];
2706                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2707                            SET_FOREGROUND(bgcolour);
2708                            SET_BACKGROUND(fgcolour);
2709                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2710                            XSetStipple(g_display, g_gc, fill);
2711                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2712                            FILL_POLYGON((XPoint *) point, npoints);
2713                            XSetFillStyle(g_display, g_gc, FillSolid);
2714                            XSetTSOrigin(g_display, g_gc, 0, 0);
2715                            ui_destroy_glyph((HGLYPH) fill);
2716                            break;
2717    
2718                    default:
2719                            unimpl("brush %d\n", brush->style);
2720            }
2721    
2722            RESET_FUNCTION(opcode);
2723    }
2724    
2725    void
2726    ui_polyline(uint8 opcode,
2727                /* dest */ POINT * points, int npoints,
2728                /* pen */ PEN * pen)
2729    {
2730            /* TODO: set join style */
2731            SET_FUNCTION(opcode);
2732            SET_FOREGROUND(pen->colour);
2733            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2734            if (g_ownbackstore)
2735                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2736                               CoordModePrevious);
2737    
2738            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2739                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2740    
2741            RESET_FUNCTION(opcode);
2742    }
2743    
2744    void
2745    ui_ellipse(uint8 opcode,
2746               /* mode */ uint8 fillmode,
2747               /* dest */ int x, int y, int cx, int cy,
2748               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2749    {
2750            uint8 style, i, ipattern[8];
2751            Pixmap fill;
2752    
2753            SET_FUNCTION(opcode);
2754    
2755            if (brush)
2756                    style = brush->style;
2757            else
2758                    style = 0;
2759    
2760            switch (style)
2761            {
2762                    case 0: /* Solid */
2763                            SET_FOREGROUND(fgcolour);
2764                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2765                            break;
2766    
2767                    case 2: /* Hatch */
2768                            fill = (Pixmap) ui_create_glyph(8, 8,
2769                                                            hatch_patterns + brush->pattern[0] * 8);
2770                            SET_FOREGROUND(fgcolour);
2771                            SET_BACKGROUND(bgcolour);
2772                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2773                            XSetStipple(g_display, g_gc, fill);
2774                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2775                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2776                            XSetFillStyle(g_display, g_gc, FillSolid);
2777                            XSetTSOrigin(g_display, g_gc, 0, 0);
2778                            ui_destroy_glyph((HGLYPH) fill);
2779                            break;
2780    
2781                    case 3: /* Pattern */
2782                            for (i = 0; i != 8; i++)
2783                                    ipattern[7 - i] = brush->pattern[i];
2784                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2785                            SET_FOREGROUND(bgcolour);
2786                            SET_BACKGROUND(fgcolour);
2787                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2788                            XSetStipple(g_display, g_gc, fill);
2789                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2790                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2791                            XSetFillStyle(g_display, g_gc, FillSolid);
2792                            XSetTSOrigin(g_display, g_gc, 0, 0);
2793                            ui_destroy_glyph((HGLYPH) fill);
2794                            break;
2795    
2796                    default:
2797                            unimpl("brush %d\n", brush->style);
2798            }
2799    
2800            RESET_FUNCTION(opcode);
2801    }
2802    
2803  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2804  void  void
2805  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 2043  ui_draw_glyph(int mixmode, Line 2855  ui_draw_glyph(int mixmode,
2855  }  }
2856    
2857  void  void
2858  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,
2859               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2860               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2861               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2862  {  {
2863            /* TODO: use brush appropriately */
2864    
2865          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2866          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
2867          DATABLOB *entry;          DATABLOB *entry;
# Line 2079  ui_draw_text(uint8 font, uint8 flags, in Line 2893  ui_draw_text(uint8 font, uint8 flags, in
2893                  switch (text[i])                  switch (text[i])
2894                  {                  {
2895                          case 0xff:                          case 0xff:
2896                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2897                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2898                                  {                                  {
2899                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2900                                          exit(1);                                          for (j = 0; j < length; j++)
2901                                                    fprintf(stderr, "%02x ", text[j]);
2902                                            fprintf(stderr, "\n");
2903                                            i = length = 0;
2904                                            break;
2905                                  }                                  }
2906                                    cache_put_text(text[i + 1], text, text[i + 2]);
2907                                    i += 3;
2908                                    length -= i;
2909                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2910                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2911                                  i = 0;                                  i = 0;
2912                                  break;                                  break;
2913    
2914                          case 0xfe:                          case 0xfe:
2915                                    /* At least one byte needs to follow */
2916                                    if (i + 2 > length)
2917                                    {
2918                                            warning("Skipping short 0xfe command:");
2919                                            for (j = 0; j < length; j++)
2920                                                    fprintf(stderr, "%02x ", text[j]);
2921                                            fprintf(stderr, "\n");
2922                                            i = length = 0;
2923                                            break;
2924                                    }
2925                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2926                                  if (entry != NULL)                                  if (entry->data != NULL)
2927                                  {                                  {
2928                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2929                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2930                                          {                                          {
2931                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2932                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2129  ui_draw_text(uint8 font, uint8 flags, in Line 2958  ui_draw_text(uint8 font, uint8 flags, in
2958          if (g_ownbackstore)          if (g_ownbackstore)
2959          {          {
2960                  if (boxcx > 1)                  if (boxcx > 1)
2961                    {
2962                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2963                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2964                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2965                                                    (g_display, g_backstore, sw->wnd, g_gc,
2966                                                     boxx, boxy,
2967                                                     boxcx, boxcy,
2968                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2969                    }
2970                  else                  else
2971                    {
2972                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2973                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2974                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2975                                                    (g_display, g_backstore, sw->wnd, g_gc,
2976                                                     clipx, clipy,
2977                                                     clipcx, clipcy, clipx - sw->xoffset,
2978                                                     clipy - sw->yoffset));
2979                    }
2980          }          }
2981  }  }
2982    
# Line 2179  ui_desktop_restore(uint32 offset, int x, Line 3022  ui_desktop_restore(uint32 offset, int x,
3022          {          {
3023                  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);
3024                  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);
3025                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3026                                            (g_display, g_backstore, sw->wnd, g_gc,
3027                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3028          }          }
3029          else          else
3030          {          {
3031                  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);
3032                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3033                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3034                                             x - sw->xoffset, y - sw->yoffset));
3035          }          }
3036    
3037          XFree(image);          XFree(image);
# Line 2198  void Line 3047  void
3047  ui_end_update(void)  ui_end_update(void)
3048  {  {
3049  }  }
3050    
3051    void
3052    ui_seamless_begin()
3053    {
3054            if (!g_seamless_rdp)
3055                    return;
3056    
3057            if (g_seamless_started)
3058                    return;
3059    
3060            g_seamless_started = True;
3061    
3062            ui_seamless_toggle();
3063    }
3064    
3065    void
3066    ui_seamless_toggle()
3067    {
3068            if (!g_seamless_rdp)
3069                    return;
3070    
3071            if (!g_seamless_started)
3072                    return;
3073    
3074            if (g_seamless_active)
3075            {
3076                    /* Deactivate */
3077                    while (g_seamless_windows)
3078                    {
3079                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3080                            seamless_remove_window(g_seamless_windows);
3081                    }
3082                    XMapWindow(g_display, g_wnd);
3083            }
3084            else
3085            {
3086                    /* Activate */
3087                    XUnmapWindow(g_display, g_wnd);
3088                    seamless_send_sync();
3089            }
3090    
3091            g_seamless_active = !g_seamless_active;
3092    }
3093    
3094    void
3095    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3096    {
3097            Window wnd;
3098            XSetWindowAttributes attribs;
3099            XClassHint *classhints;
3100            XSizeHints *sizehints;
3101            long input_mask;
3102            seamless_window *sw, *sw_parent;
3103    
3104            if (!g_seamless_active)
3105                    return;
3106    
3107            /* Ignore CREATEs for existing windows */
3108            sw = seamless_get_window_by_id(id);
3109            if (sw)
3110                    return;
3111    
3112            get_window_attribs(&attribs);
3113            attribs.override_redirect = False;
3114    
3115            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3116                                InputOutput, g_visual,
3117                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3118                                CWBorderPixel, &attribs);
3119    
3120            XStoreName(g_display, wnd, "SeamlessRDP");
3121            ewmh_set_wm_name(wnd, "SeamlessRDP");
3122    
3123            mwm_hide_decorations(wnd);
3124    
3125            classhints = XAllocClassHint();
3126            if (classhints != NULL)
3127            {
3128                    classhints->res_name = "rdesktop";
3129                    classhints->res_class = "SeamlessRDP";
3130                    XSetClassHint(g_display, wnd, classhints);
3131                    XFree(classhints);
3132            }
3133    
3134            /* WM_NORMAL_HINTS */
3135            sizehints = XAllocSizeHints();
3136            if (sizehints != NULL)
3137            {
3138                    sizehints->flags = USPosition;
3139                    XSetWMNormalHints(g_display, wnd, sizehints);
3140                    XFree(sizehints);
3141            }
3142    
3143            /* Set WM_TRANSIENT_FOR, if necessary */
3144            if ((parent != 0x00000000) && (parent != 0xFFFFFFFF))
3145            {
3146                    sw_parent = seamless_get_window_by_id(parent);
3147                    if (sw_parent)
3148                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3149                    else
3150                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3151            }
3152    
3153    
3154            /* FIXME: Support for Input Context:s */
3155    
3156            get_input_mask(&input_mask);
3157            input_mask |= PropertyChangeMask;
3158    
3159            XSelectInput(g_display, wnd, input_mask);
3160    
3161            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3162               seamless window, we could try to close the window on the
3163               serverside, instead of terminating rdesktop */
3164            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3165    
3166            sw = malloc(sizeof(seamless_window));
3167            sw->wnd = wnd;
3168            sw->id = id;
3169            sw->parent = parent;
3170            sw->xoffset = 0;
3171            sw->yoffset = 0;
3172            sw->width = 0;
3173            sw->height = 0;
3174            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3175            sw->desktop = 0;
3176            sw->next = g_seamless_windows;
3177            g_seamless_windows = sw;
3178    }
3179    
3180    
3181    void
3182    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3183    {
3184            seamless_window *sw;
3185    
3186            if (!g_seamless_active)
3187                    return;
3188    
3189            sw = seamless_get_window_by_id(id);
3190            if (!sw)
3191            {
3192                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3193                    return;
3194            }
3195    
3196            XDestroyWindow(g_display, sw->wnd);
3197            seamless_remove_window(sw);
3198    }
3199    
3200    
3201    void
3202    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3203    {
3204            seamless_window *sw;
3205    
3206            if (!g_seamless_active)
3207                    return;
3208    
3209            sw = seamless_get_window_by_id(id);
3210            if (!sw)
3211            {
3212                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3213                    return;
3214            }
3215    
3216            if (!width || !height)
3217                    /* X11 windows must be at least 1x1 */
3218                    return;
3219    
3220            /* About MAX and MIN: Windows allows moving a window outside
3221               the desktop. This happens, for example, when maximizing an
3222               application. In this case, the position is set to something
3223               like -4,-4,1288,1032. Many WMs does not allow windows
3224               outside the desktop, however. Therefore, clip the window
3225               ourselves. */
3226            sw->xoffset = MAX(0, x);
3227            sw->yoffset = MAX(0, y);
3228            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3229            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3230    
3231            /* If we move the window in a maximized state, then KDE won't
3232               accept restoration */
3233            switch (sw->state)
3234            {
3235                    case SEAMLESSRDP_MINIMIZED:
3236                    case SEAMLESSRDP_MAXIMIZED:
3237                            return;
3238            }
3239    
3240            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3241            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3242    }
3243    
3244    void
3245    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3246    {
3247            seamless_window *sw;
3248    
3249            if (!g_seamless_active)
3250                    return;
3251    
3252            sw = seamless_get_window_by_id(id);
3253            if (!sw)
3254            {
3255                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3256                    return;
3257            }
3258    
3259            if (behind)
3260            {
3261                    seamless_window *sw_behind;
3262                    Window wnds[2];
3263    
3264                    sw_behind = seamless_get_window_by_id(behind);
3265                    if (!sw_behind)
3266                    {
3267                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3268                                    behind);
3269                            return;
3270                    }
3271    
3272                    wnds[1] = sw_behind->wnd;
3273                    wnds[0] = sw->wnd;
3274    
3275                    XRestackWindows(g_display, wnds, 2);
3276            }
3277            else
3278            {
3279                    XRaiseWindow(g_display, sw->wnd);
3280            }
3281    }
3282    
3283    void
3284    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3285    {
3286            seamless_window *sw;
3287    
3288            if (!g_seamless_active)
3289                    return;
3290    
3291            sw = seamless_get_window_by_id(id);
3292            if (!sw)
3293            {
3294                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3295                    return;
3296            }
3297    
3298            /* FIXME: Might want to convert the name for non-EWMH WMs */
3299            XStoreName(g_display, sw->wnd, title);
3300            ewmh_set_wm_name(sw->wnd, title);
3301    }
3302    
3303    
3304    void
3305    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3306    {
3307            seamless_window *sw;
3308    
3309            if (!g_seamless_active)
3310                    return;
3311    
3312            sw = seamless_get_window_by_id(id);
3313            if (!sw)
3314            {
3315                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3316                    return;
3317            }
3318    
3319            switch (state)
3320            {
3321                    case SEAMLESSRDP_NORMAL:
3322                    case SEAMLESSRDP_MAXIMIZED:
3323                            ewmh_change_state(sw->wnd, state);
3324                            XMapWindow(g_display, sw->wnd);
3325                            break;
3326                    case SEAMLESSRDP_MINIMIZED:
3327                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3328                               the Window Manager should probably just ignore the request, since
3329                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3330                               such as minimization, rather than an independent state." Besides,
3331                               XIconifyWindow is easier. */
3332                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3333                            {
3334                                    XWMHints *hints;
3335                                    hints = XAllocWMHints();
3336                                    hints->flags = StateHint;
3337                                    hints->initial_state = IconicState;
3338                                    XSetWMHints(g_display, sw->wnd, hints);
3339                                    XFree(hints);
3340                                    XMapWindow(g_display, sw->wnd);
3341                            }
3342                            else
3343                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3344                            break;
3345                    default:
3346                            warning("SeamlessRDP: Invalid state %d\n", state);
3347                            break;
3348            }
3349    
3350            /* Handle popups without parents through some ewm hints */
3351            if ((sw->state == SEAMLESSRDP_NOTYETMAPPED) && (sw->parent == 0xFFFFFFFF))
3352                    ewmh_set_window_popup(sw->wnd);
3353    
3354            sw->state = state;
3355    }
3356    
3357    
3358    void
3359    ui_seamless_syncbegin(unsigned long flags)
3360    {
3361            if (!g_seamless_active)
3362                    return;
3363    
3364            /* Destroy all seamless windows */
3365            while (g_seamless_windows)
3366            {
3367                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3368                    seamless_remove_window(g_seamless_windows);
3369            }
3370    }

Legend:
Removed from v.800  
changed lines
  Added in v.1151

  ViewVC Help
Powered by ViewVC 1.1.26