/[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 822 by stargo, Mon Feb 28 22:38:24 2005 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1105 by astrand, Fri Mar 10 13:46:15 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            int xoffset, yoffset;
58            int width, height;
59            struct _seamless_window *next;
60    } seamless_window;
61    static seamless_window *g_seamless_windows = NULL;
62    extern BOOL g_seamless_rdp;
63    
64  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
65  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
66  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
67  static GC g_gc = NULL;  static GC g_gc = NULL;
68  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
69  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
70    static XRectangle g_clip_rectangle;
71  static Visual *g_visual;  static Visual *g_visual;
72    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
73       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
74       as far as we're concerned. */
75  static int g_depth;  static int g_depth;
76    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
77       This may be larger than g_depth, in which case some of the bits would
78       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
79  static int g_bpp;  static int g_bpp;
80  static XIM g_IM;  static XIM g_IM;
81  static XIC g_IC;  static XIC g_IC;
# Line 62  static HCURSOR g_null_cursor = NULL; Line 85  static HCURSOR g_null_cursor = NULL;
85  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
86  static BOOL g_focused;  static BOOL g_focused;
87  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
88  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* Indicates that:
89       1) visual has 15, 16 or 24 depth and the same color channel masks
90          as its RDP equivalent (implies X server is LE),
91       2) host is LE
92       This will trigger an optimization whose real value is questionable.
93    */
94    static BOOL g_compatible_arch;
95    /* Indicates whether RDP's bitmaps and our XImages have the same
96       binary format. If so, we can avoid an expensive translation.
97       Note that this can be true when g_compatible_arch is false,
98       e.g.:
99      
100         RDP(LE) <-> host(BE) <-> X-Server(LE)
101        
102       ('host' is the machine running rdesktop; the host simply memcpy's
103        so its endianess doesn't matter)
104     */
105    static BOOL g_no_translate_image = False;
106    
107  /* endianness */  /* endianness */
108  static BOOL g_host_be;  static BOOL g_host_be;
# Line 78  static Pixmap g_backstore = 0; Line 118  static Pixmap g_backstore = 0;
118  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
119  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
120  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
121    static BOOL g_using_full_workarea = False;
122    
123  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
124  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 90  extern BOOL g_rdpsnd; Line 131  extern BOOL g_rdpsnd;
131  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
132  typedef struct  typedef struct
133  {  {
134          uint32 flags;          unsigned long flags;
135          uint32 functions;          unsigned long functions;
136          uint32 decorations;          unsigned long decorations;
137          sint32 inputMode;          long inputMode;
138          uint32 status;          unsigned long status;
139  }  }
140  PropMotifWmHints;  PropMotifWmHints;
141    
# Line 106  typedef struct Line 147  typedef struct
147  }  }
148  PixelColour;  PixelColour;
149    
150    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
151            do { \
152                    seamless_window *sw; \
153                    XRectangle rect; \
154                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
155                        rect.x = g_clip_rectangle.x - sw->xoffset; \
156                        rect.y = g_clip_rectangle.y - sw->yoffset; \
157                        rect.width = g_clip_rectangle.width; \
158                        rect.height = g_clip_rectangle.height; \
159                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
160                        func args; \
161                    } \
162                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
163            } while (0)
164    
165    static void
166    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
167    {
168            points[0].x -= xoffset;
169            points[0].y -= yoffset;
170            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
171            points[0].x += xoffset;
172            points[0].y += yoffset;
173    }
174    
175    static void
176    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
177    {
178            points[0].x -= xoffset;
179            points[0].y -= yoffset;
180            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
181            points[0].x += xoffset;
182            points[0].y += yoffset;
183    }
184    
185  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
186  { \  { \
187          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
188            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
189          if (g_ownbackstore) \          if (g_ownbackstore) \
190                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
191  }  }
# Line 119  PixelColour; Line 195  PixelColour;
195          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); \
196  }  }
197    
198    #define FILL_POLYGON(p,np)\
199    { \
200            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
201            if (g_ownbackstore) \
202                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
203            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
204    }
205    
206    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
207    { \
208            switch (m) \
209            { \
210                    case 0: /* Outline */ \
211                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
212                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
213                            if (g_ownbackstore) \
214                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
215                            break; \
216                    case 1: /* Filled */ \
217                            XFillArc(g_display, g_wnd, g_gc, x, y, \
218                                     cx, cy, 0, 360*64); \
219                            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)); \
220                            if (g_ownbackstore) \
221                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
222                            break; \
223            } \
224    }
225    
226  /* colour maps */  /* colour maps */
227  extern BOOL g_owncolmap;  extern BOOL g_owncolmap;
228  static Colormap g_xcolmap;  static Colormap g_xcolmap;
229  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
230    
231  #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] )
232  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
233  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
234    
# Line 150  static int rop2_map[] = { Line 254  static int rop2_map[] = {
254  #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]); }
255  #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); }
256    
257    static seamless_window *
258    seamless_get_window_by_id(unsigned long id)
259    {
260            seamless_window *sw;
261            for (sw = g_seamless_windows; sw; sw = sw->next)
262            {
263                    if (sw->id == id)
264                            return sw;
265            }
266            return NULL;
267    }
268    
269    
270    static seamless_window *
271    seamless_get_window_by_wnd(Window wnd)
272    {
273            seamless_window *sw;
274            for (sw = g_seamless_windows; sw; sw = sw->next)
275            {
276                    if (sw->wnd == wnd)
277                            return sw;
278            }
279            return NULL;
280    }
281    
282    
283  static void  static void
284  mwm_hide_decorations(void)  seamless_remove_window(seamless_window * win)
285    {
286            seamless_window *sw, **prevnext = &g_seamless_windows;
287            for (sw = g_seamless_windows; sw; sw = sw->next)
288            {
289                    if (sw == win)
290                    {
291                            *prevnext = sw->next;
292                            xfree(sw);
293                            return;
294                    }
295                    prevnext = &sw->next;
296            }
297            return;
298    }
299    
300    
301    static void
302    mwm_hide_decorations(Window wnd)
303  {  {
304          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
305          Atom hintsatom;          Atom hintsatom;
# Line 168  mwm_hide_decorations(void) Line 316  mwm_hide_decorations(void)
316                  return;                  return;
317          }          }
318    
319          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
320                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
321    
322  }  }
323    
324  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 203  mwm_hide_decorations(void) Line 352  mwm_hide_decorations(void)
352  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
353                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
354    
355    /* The following macros output the same octet sequences
356       on both BE and LE hosts: */
357    
358  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
359  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
360  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
# Line 214  static uint32 Line 366  static uint32
366  translate_colour(uint32 colour)  translate_colour(uint32 colour)
367  {  {
368          PixelColour pc;          PixelColour pc;
369          switch (g_server_bpp)          switch (g_server_depth)
370          {          {
371                  case 15:                  case 15:
372                          SPLITCOLOUR15(colour, pc);                          SPLITCOLOUR15(colour, pc);
# Line 225  translate_colour(uint32 colour) Line 377  translate_colour(uint32 colour)
377                  case 24:                  case 24:
378                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
379                          break;                          break;
380                    default:
381                            /* Avoid warning */
382                            pc.red = 0;
383                            pc.green = 0;
384                            pc.blue = 0;
385                            break;
386          }          }
387          return MAKECOLOUR(pc);          return MAKECOLOUR(pc);
388  }  }
# Line 276  translate8to16(const uint8 * data, uint8 Line 434  translate8to16(const uint8 * data, uint8
434  {  {
435          uint16 value;          uint16 value;
436    
437          if (g_arch_match)          if (g_compatible_arch)
438          {          {
439                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
440                  REPEAT2                  REPEAT2
# Line 310  translate8to24(const uint8 * data, uint8 Line 468  translate8to24(const uint8 * data, uint8
468  {  {
469          uint32 value;          uint32 value;
470    
471          if (g_xserver_be)          if (g_compatible_arch)
472          {          {
473                  while (out < end)                  while (out < end)
474                  {                  {
# Line 333  translate8to32(const uint8 * data, uint8 Line 491  translate8to32(const uint8 * data, uint8
491  {  {
492          uint32 value;          uint32 value;
493    
494          if (g_arch_match)          if (g_compatible_arch)
495          {          {
496                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
497                  REPEAT4                  REPEAT4
# Line 405  translate15to24(const uint16 * data, uin Line 563  translate15to24(const uint16 * data, uin
563          uint16 pixel;          uint16 pixel;
564          PixelColour pc;          PixelColour pc;
565    
566          if (g_arch_match)          if (g_compatible_arch)
567          {          {
568                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
569                  REPEAT3                  REPEAT3
# Line 455  translate15to32(const uint16 * data, uin Line 613  translate15to32(const uint16 * data, uin
613          uint32 value;          uint32 value;
614          PixelColour pc;          PixelColour pc;
615    
616          if (g_arch_match)          if (g_compatible_arch)
617          {          {
618                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
619                  REPEAT4                  REPEAT4
# Line 563  translate16to24(const uint16 * data, uin Line 721  translate16to24(const uint16 * data, uin
721          uint16 pixel;          uint16 pixel;
722          PixelColour pc;          PixelColour pc;
723    
724          if (g_arch_match)          if (g_compatible_arch)
725          {          {
726                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
727                  REPEAT3                  REPEAT3
# Line 633  translate16to32(const uint16 * data, uin Line 791  translate16to32(const uint16 * data, uin
791          uint32 value;          uint32 value;
792          PixelColour pc;          PixelColour pc;
793    
794          if (g_arch_match)          if (g_compatible_arch)
795          {          {
796                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
797                  REPEAT4                  REPEAT4
# Line 662  translate16to32(const uint16 * data, uin Line 820  translate16to32(const uint16 * data, uin
820                  }                  }
821                  else                  else
822                  {                  {
823                            while (out < end)
824                          {                          {
825                                  pixel = *(data++);                                  pixel = *(data++);
826                                  SPLITCOLOUR16(pixel, pc);                                  SPLITCOLOUR16(pixel, pc);
# Line 761  translate24to32(const uint8 * data, uint Line 920  translate24to32(const uint8 * data, uint
920          uint32 value;          uint32 value;
921          PixelColour pc;          PixelColour pc;
922    
923          if (g_arch_match)          if (g_compatible_arch)
924          {          {
925                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
926  #ifdef NEED_ALIGN  #ifdef NEED_ALIGN
# Line 775  translate24to32(const uint8 * data, uint Line 934  translate24to32(const uint8 * data, uint
934  #else  #else
935                  REPEAT4                  REPEAT4
936                  (                  (
937                          *((uint32 *) out) = *((uint32 *) data);                   /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
938                          out += 4;                   *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
939                          data += 3;                   out += 4;
940                     data += 3;
941                  )                  )
942  #endif  #endif
943                  /* *INDENT-ON* */                  /* *INDENT-ON* */
# Line 815  translate_image(int width, int height, u Line 975  translate_image(int width, int height, u
975          uint8 *out;          uint8 *out;
976          uint8 *end;          uint8 *end;
977    
978          /* if server and xserver bpp match, */          /*
979          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
980          /* just return data */             and arch(endian) matches, no need to translate:
981          if (g_arch_match)             just return data.
982               Note: select_visual should've already ensured g_no_translate
983               is only set for compatible depths, but the RDP depth might've
984               changed during connection negotiations.
985             */
986            if (g_no_translate_image)
987          {          {
988                  if (g_depth == 15 && g_server_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
989                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
990                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
                         return data;  
                 if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)  
991                          return data;                          return data;
992          }          }
993    
# Line 832  translate_image(int width, int height, u Line 995  translate_image(int width, int height, u
995          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
996          end = out + size;          end = out + size;
997    
998          switch (g_server_bpp)          switch (g_server_depth)
999          {          {
1000                  case 24:                  case 24:
1001                          switch (g_bpp)                          switch (g_bpp)
# Line 930  calculate_shifts(uint32 mask, int *shift Line 1093  calculate_shifts(uint32 mask, int *shift
1093          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
1094  }  }
1095    
1096  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1097  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1098     */
1099    static unsigned
1100    calculate_mask_weight(uint32 mask)
1101    {
1102            unsigned weight = 0;
1103            do
1104            {
1105                    weight += (mask & 1);
1106            }
1107            while (mask >>= 1);
1108            return weight;
1109    }
1110    
1111    static BOOL
1112    select_visual()
1113  {  {
         XVisualInfo vi;  
1114          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1115          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1116          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1117          XVisualInfo template;          XVisualInfo template;
1118          Bool TrueColorVisual = False;          int i;
1119            unsigned red_weight, blue_weight, green_weight;
1120    
1121          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1122          if (g_display == NULL)  
1123            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1124            if (pfm == NULL)
1125          {          {
1126                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1127                    XCloseDisplay(g_display);
1128                  return False;                  return False;
1129          }          }
1130    
1131          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 */  
1132          template.class = TrueColor;          template.class = TrueColor;
1133          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1134            g_visual = NULL;
1135            g_no_translate_image = False;
1136            g_compatible_arch = False;
1137            if (vmatches != NULL)
1138            {
1139                    for (i = 0; i < visuals_count; ++i)
1140                    {
1141                            XVisualInfo *visual_info = &vmatches[i];
1142    
1143                            /* Try to find a no-translation visual that'll
1144                               allow us to use RDP bitmaps directly as ZPixmaps. */
1145                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1146                                                   /* R5G5B5 */
1147                                                   (visual_info->red_mask == 0x7c00) &&
1148                                                   (visual_info->green_mask == 0x3e0) &&
1149                                                   (visual_info->blue_mask == 0x1f)) ||
1150                                                  ((visual_info->depth == 16) &&
1151                                                   /* R5G6B5 */
1152                                                   (visual_info->red_mask == 0xf800) &&
1153                                                   (visual_info->green_mask == 0x7e0) &&
1154                                                   (visual_info->blue_mask == 0x1f)) ||
1155                                                  ((visual_info->depth == 24) &&
1156                                                   /* R8G8B8 */
1157                                                   (visual_info->red_mask == 0xff0000) &&
1158                                                   (visual_info->green_mask == 0xff00) &&
1159                                                   (visual_info->blue_mask == 0xff))))
1160                            {
1161                                    g_visual = visual_info->visual;
1162                                    g_depth = visual_info->depth;
1163                                    g_compatible_arch = !g_host_be;
1164                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1165                                    if (g_no_translate_image)
1166                                            /* We found the best visual */
1167                                            break;
1168                            }
1169                            else
1170                            {
1171                                    g_compatible_arch = False;
1172                            }
1173    
1174                            if (visual_info->depth > 24)
1175                            {
1176                                    /* Avoid 32-bit visuals and likes like the plague.
1177                                       They're either untested or proven to work bad
1178                                       (e.g. nvidia's Composite 32-bit visual).
1179                                       Most implementation offer a 24-bit visual anyway. */
1180                                    continue;
1181                            }
1182    
1183          nvisuals--;                          /* Only care for visuals, for whose BPPs (not depths!)
1184          while (nvisuals >= 0)                             we have a translateXtoY function. */
1185          {                          BOOL can_translate_to_bpp = False;
1186                  if ((vmatches + nvisuals)->depth > g_depth)                          int j;
1187                  {                          for (j = 0; j < pixmap_formats_count; ++j)
1188                          g_depth = (vmatches + nvisuals)->depth;                          {
1189                                    if (pfm[j].depth == visual_info->depth)
1190                                    {
1191                                            if ((pfm[j].bits_per_pixel == 16) ||
1192                                                (pfm[j].bits_per_pixel == 24) ||
1193                                                (pfm[j].bits_per_pixel == 32))
1194                                            {
1195                                                    can_translate_to_bpp = True;
1196                                            }
1197                                            break;
1198                                    }
1199                            }
1200    
1201                            /* Prefer formats which have the most colour depth.
1202                               We're being truly aristocratic here, minding each
1203                               weight on its own. */
1204                            if (can_translate_to_bpp)
1205                            {
1206                                    unsigned vis_red_weight =
1207                                            calculate_mask_weight(visual_info->red_mask);
1208                                    unsigned vis_green_weight =
1209                                            calculate_mask_weight(visual_info->green_mask);
1210                                    unsigned vis_blue_weight =
1211                                            calculate_mask_weight(visual_info->blue_mask);
1212                                    if ((vis_red_weight >= red_weight)
1213                                        && (vis_green_weight >= green_weight)
1214                                        && (vis_blue_weight >= blue_weight))
1215                                    {
1216                                            red_weight = vis_red_weight;
1217                                            green_weight = vis_green_weight;
1218                                            blue_weight = vis_blue_weight;
1219                                            g_visual = visual_info->visual;
1220                                            g_depth = visual_info->depth;
1221                                    }
1222                            }
1223                  }                  }
1224                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1225          }          }
1226    
1227          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)))  
1228          {          {
1229                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1230                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1231                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1232                    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;  
                 }  
1233          }          }
1234          else          else
1235          {          {
1236                  /* need a truecolour visual */                  template.class = PseudoColor;
1237                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1238                  {                  template.colormap_size = 256;
1239                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1240                            XGetVisualInfo(g_display,
1241                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1242                                           &template, &visuals_count);
1243                    if (vmatches == NULL)
1244                    {
1245                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1246                            XCloseDisplay(g_display);
1247                            XFree(pfm);
1248                          return False;                          return False;
1249                  }                  }
1250    
1251                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1252                  g_owncolmap = False;                  g_owncolmap = True;
1253                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1254                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
1255                  calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);          }
1256    
1257                  /* if RGB video and everything is little endian */          g_bpp = 0;
1258                  if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&          for (i = 0; i < pixmap_formats_count; ++i)
1259                      !g_xserver_be && !g_host_be)          {
1260                    XPixmapFormatValues *pf = &pfm[i];
1261                    if (pf->depth == g_depth)
1262                  {                  {
1263                          if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&                          g_bpp = pf->bits_per_pixel;
1264                                                g_blue_shift_l == 0))  
1265                            if (g_no_translate_image)
1266                          {                          {
1267                                  g_arch_match = True;                                  switch (g_server_depth)
1268                                    {
1269                                            case 15:
1270                                            case 16:
1271                                                    if (g_bpp != 16)
1272                                                            g_no_translate_image = False;
1273                                                    break;
1274                                            case 24:
1275                                                    /* Yes, this will force image translation
1276                                                       on most modern servers which use 32 bits
1277                                                       for R8G8B8. */
1278                                                    if (g_bpp != 24)
1279                                                            g_no_translate_image = False;
1280                                                    break;
1281                                            default:
1282                                                    g_no_translate_image = False;
1283                                                    break;
1284                                    }
1285                          }                          }
                 }  
1286    
1287                  if (g_arch_match)                          /* Pixmap formats list is a depth-to-bpp mapping --
1288                  {                             there's just a single entry for every depth,
1289                          DEBUG(("Architectures match, enabling little endian optimisations.\n"));                             so we can safely break here */
1290                            break;
1291                  }                  }
1292          }          }
1293            XFree(pfm);
1294            pfm = NULL;
1295            return True;
1296    }
1297    
1298    BOOL
1299    ui_init(void)
1300    {
1301            int screen_num;
1302    
1303          pfm = XListPixmapFormats(g_display, &i);          g_display = XOpenDisplay(NULL);
1304          if (pfm != NULL)          if (g_display == NULL)
1305          {          {
1306                  /* Use maximum bpp for this depth - this is generally                  error("Failed to open display: %s\n", XDisplayName(NULL));
1307                     desirable, e.g. 24 bits->32 bits. */                  return False;
                 while (i--)  
                 {  
                         if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))  
                         {  
                                 g_bpp = pfm[i].bits_per_pixel;  
                         }  
                 }  
                 XFree(pfm);  
1308          }          }
1309    
         if (g_bpp < 8)  
1310          {          {
1311                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1312                  XCloseDisplay(g_display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1313            }
1314    
1315            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1316            screen_num = DefaultScreen(g_display);
1317            g_x_socket = ConnectionNumber(g_display);
1318            g_screen = ScreenOfDisplay(g_display, screen_num);
1319            g_depth = DefaultDepthOfScreen(g_screen);
1320    
1321            if (!select_visual())
1322                  return False;                  return False;
1323    
1324            if (g_no_translate_image)
1325            {
1326                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1327          }          }
1328    
1329            if (g_server_depth > g_bpp)
1330            {
1331                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1332                            g_server_depth, g_bpp);
1333            }
1334    
1335            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1336                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1337    
1338          if (!g_owncolmap)          if (!g_owncolmap)
1339          {          {
1340                  g_xcolmap =                  g_xcolmap =
1341                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1342                                          AllocNone);                                          AllocNone);
1343                  if (g_depth <= 8)                  if (g_depth <= 8)
1344                          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);
1345          }          }
1346    
1347          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1348          {          {
1349                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1350                  g_ownbackstore = True;                  g_ownbackstore = True;
1351          }          }
1352    
# Line 1060  ui_init(void) Line 1357  ui_init(void)
1357          {          {
1358                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1359                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1360                    g_using_full_workarea = True;
1361          }          }
1362          else if (g_width < 0)          else if (g_width < 0)
1363          {          {
1364                  /* Percent of screen */                  /* Percent of screen */
1365                    if (-g_width >= 100)
1366                            g_using_full_workarea = True;
1367                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1368                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1369          }          }
# Line 1071  ui_init(void) Line 1371  ui_init(void)
1371          {          {
1372                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1373                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1374                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1375                  {                  {
1376                          g_width = cx;                          g_width = cx;
1377                          g_height = cy;                          g_height = cy;
1378                            g_using_full_workarea = True;
1379                  }                  }
1380                  else                  else
1381                  {                  {
1382                          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");
1383                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1384                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1385                  }                  }
1386          }          }
1387    
# Line 1096  ui_init(void) Line 1396  ui_init(void)
1396                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1397    
1398          xclip_init();          xclip_init();
1399            if (g_seamless_rdp)
1400                    seamless_init();
1401    
1402          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));
1403    
1404          return True;          return True;
1405  }  }
# Line 1121  ui_deinit(void) Line 1423  ui_deinit(void)
1423          g_display = NULL;          g_display = NULL;
1424  }  }
1425    
1426    
1427    static void
1428    get_window_attribs(XSetWindowAttributes * attribs)
1429    {
1430            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1431            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1432            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1433            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1434            attribs->override_redirect = g_fullscreen;
1435            attribs->colormap = g_xcolmap;
1436    }
1437    
1438    static void
1439    get_input_mask(long *input_mask)
1440    {
1441            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1442                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1443    
1444            if (g_sendmotion)
1445                    *input_mask |= PointerMotionMask;
1446            if (g_ownbackstore)
1447                    *input_mask |= ExposureMask;
1448            if (g_fullscreen || g_grab_keyboard)
1449                    *input_mask |= EnterWindowMask;
1450            if (g_grab_keyboard)
1451                    *input_mask |= LeaveWindowMask;
1452    }
1453    
1454  BOOL  BOOL
1455  ui_create_window(void)  ui_create_window(void)
1456  {  {
# Line 1137  ui_create_window(void) Line 1467  ui_create_window(void)
1467          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1468          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1469    
1470          attribs.background_pixel = BlackPixelOfScreen(g_screen);          /* Handle -x-y portion of geometry string */
1471          attribs.border_pixel = WhitePixelOfScreen(g_screen);          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1472          attribs.backing_store = g_ownbackstore ? NotUseful : Always;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1473          attribs.override_redirect = g_fullscreen;          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1474          attribs.colormap = g_xcolmap;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1475    
1476            get_window_attribs(&attribs);
1477    
1478          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1479                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1149  ui_create_window(void) Line 1481  ui_create_window(void)
1481                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1482    
1483          if (g_gc == NULL)          if (g_gc == NULL)
1484            {
1485                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1486                    ui_reset_clip();
1487            }
1488    
1489          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1490                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 1166  ui_create_window(void) Line 1501  ui_create_window(void)
1501          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1502    
1503          if (g_hide_decorations)          if (g_hide_decorations)
1504                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1505    
1506          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1507          if (classhints != NULL)          if (classhints != NULL)
# Line 1180  ui_create_window(void) Line 1515  ui_create_window(void)
1515          if (sizehints)          if (sizehints)
1516          {          {
1517                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1518                    if (g_pos)
1519                            sizehints->flags |= PPosition;
1520                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1521                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1522                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
# Line 1191  ui_create_window(void) Line 1528  ui_create_window(void)
1528                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1529          }          }
1530    
1531          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;  
1532    
1533          if (g_IM != NULL)          if (g_IM != NULL)
1534          {          {
# Line 1214  ui_create_window(void) Line 1541  ui_create_window(void)
1541          }          }
1542    
1543          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1544          XMapWindow(g_display, g_wnd);          if (!g_seamless_rdp)
   
         /* wait for VisibilityNotify */  
         do  
1545          {          {
1546                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMapWindow(g_display, g_wnd);
1547                    /* wait for VisibilityNotify */
1548                    do
1549                    {
1550                            XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1551                    }
1552                    while (xevent.type != VisibilityNotify);
1553                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1554          }          }
         while (xevent.type != VisibilityNotify);  
         g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;  
1555    
1556          g_focused = False;          g_focused = False;
1557          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1286  xwin_toggle_fullscreen(void) Line 1615  xwin_toggle_fullscreen(void)
1615  {  {
1616          Pixmap contents = 0;          Pixmap contents = 0;
1617    
1618            if (g_seamless_rdp)
1619                    /* Turn off SeamlessRDP mode */
1620                    ui_seamless_toggle();
1621    
1622          if (!g_ownbackstore)          if (!g_ownbackstore)
1623          {          {
1624                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1306  xwin_toggle_fullscreen(void) Line 1639  xwin_toggle_fullscreen(void)
1639          }          }
1640  }  }
1641    
1642  /* Process all events in Xlib queue  static void
1643    handle_button_event(XEvent xevent, BOOL down)
1644    {
1645            uint16 button, flags = 0;
1646            g_last_gesturetime = xevent.xbutton.time;
1647            button = xkeymap_translate_button(xevent.xbutton.button);
1648            if (button == 0)
1649                    return;
1650    
1651            if (down)
1652                    flags = MOUSE_FLAG_DOWN;
1653    
1654            /* Stop moving window when button is released, regardless of cursor position */
1655            if (g_moving_wnd && (xevent.type == ButtonRelease))
1656                    g_moving_wnd = False;
1657    
1658            /* If win_button_size is nonzero, enable single app mode */
1659            if (xevent.xbutton.y < g_win_button_size)
1660            {
1661                    /*  Check from right to left: */
1662                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1663                    {
1664                            /* The close button, continue */
1665                            ;
1666                    }
1667                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1668                    {
1669                            /* The maximize/restore button. Do not send to
1670                               server.  It might be a good idea to change the
1671                               cursor or give some other visible indication
1672                               that rdesktop inhibited this click */
1673                            if (xevent.type == ButtonPress)
1674                                    return;
1675                    }
1676                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1677                    {
1678                            /* The minimize button. Iconify window. */
1679                            if (xevent.type == ButtonRelease)
1680                            {
1681                                    /* Release the mouse button outside the minimize button, to prevent the
1682                                       actual minimazation to happen */
1683                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1684                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1685                                    return;
1686                            }
1687                    }
1688                    else if (xevent.xbutton.x <= g_win_button_size)
1689                    {
1690                            /* The system menu. Ignore. */
1691                            if (xevent.type == ButtonPress)
1692                                    return;
1693                    }
1694                    else
1695                    {
1696                            /* The title bar. */
1697                            if (xevent.type == ButtonPress)
1698                            {
1699                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1700                                    {
1701                                            g_moving_wnd = True;
1702                                            g_move_x_offset = xevent.xbutton.x;
1703                                            g_move_y_offset = xevent.xbutton.y;
1704                                    }
1705                                    return;
1706                            }
1707                    }
1708            }
1709    
1710            if (xevent.xmotion.window == g_wnd)
1711            {
1712                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1713                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1714            }
1715            else
1716            {
1717                    /* SeamlessRDP */
1718                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1719                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1720            }
1721    }
1722    
1723    /* Process events in Xlib queue
1724     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1725  static int  static int
1726  xwin_process_events(void)  xwin_process_events(void)
1727  {  {
1728          XEvent xevent;          XEvent xevent;
1729          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1730          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1731          char str[256];          char str[256];
1732          Status status;          Status status;
1733            int events = 0;
1734            seamless_window *sw;
1735    
1736          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1737          {          {
1738                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1739    
# Line 1329  xwin_process_events(void) Line 1743  xwin_process_events(void)
1743                          continue;                          continue;
1744                  }                  }
1745    
                 flags = 0;  
   
1746                  switch (xevent.type)                  switch (xevent.type)
1747                  {                  {
1748                          case VisibilityNotify:                          case VisibilityNotify:
1749                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1750                                            g_Unobscured =
1751                                                    xevent.xvisibility.state == VisibilityUnobscured;
1752    
1753                                  break;                                  break;
1754                          case ClientMessage:                          case ClientMessage:
1755                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1367  xwin_process_events(void) Line 1782  xwin_process_events(void)
1782                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1783                                  }                                  }
1784    
1785                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1786                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1787    
1788                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1789                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1790                                          break;                                          break;
1791    
1792                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1793                                                             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);  
   
1794                                  break;                                  break;
1795    
1796                          case KeyRelease:                          case KeyRelease:
# Line 1392  xwin_process_events(void) Line 1798  xwin_process_events(void)
1798                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1799                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1800    
1801                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1802                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1803    
1804                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1805                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1806                                          break;                                          break;
1807    
1808                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1809                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1810                                  break;                                  break;
1811    
1812                          case ButtonPress:                          case ButtonPress:
1813                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1814                                  /* fall through */                                  break;
1815    
1816                          case ButtonRelease:                          case ButtonRelease:
1817                                  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);  
1818                                  break;                                  break;
1819    
1820                          case MotionNotify:                          case MotionNotify:
# Line 1485  xwin_process_events(void) Line 1829  xwin_process_events(void)
1829                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1830                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1831                                                         CurrentTime);                                                         CurrentTime);
1832                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1833                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1834                                    {
1835                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1836                                                           xevent.xmotion.x, xevent.xmotion.y);
1837                                    }
1838                                    else
1839                                    {
1840                                            /* SeamlessRDP */
1841                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1842                                                           xevent.xmotion.x_root,
1843                                                           xevent.xmotion.y_root);
1844                                    }
1845                                  break;                                  break;
1846    
1847                          case FocusIn:                          case FocusIn:
# Line 1529  xwin_process_events(void) Line 1884  xwin_process_events(void)
1884                                  break;                                  break;
1885    
1886                          case Expose:                          case Expose:
1887                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
1888                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1889                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1890                                            xevent.xexpose.height,                                                    g_gc,
1891                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1892                                                      xevent.xexpose.width, xevent.xexpose.height,
1893                                                      xevent.xexpose.x, xevent.xexpose.y);
1894                                    }
1895                                    else
1896                                    {
1897                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1898                                            if (sw)
1899                                                    XCopyArea(g_display, g_backstore,
1900                                                              xevent.xexpose.window, g_gc,
1901                                                              xevent.xexpose.x + sw->xoffset,
1902                                                              xevent.xexpose.y + sw->yoffset,
1903                                                              xevent.xexpose.width,
1904                                                              xevent.xexpose.height, xevent.xexpose.x,
1905                                                              xevent.xexpose.y);
1906                                    }
1907    
1908                                  break;                                  break;
1909    
1910                          case MappingNotify:                          case MappingNotify:
# Line 1563  xwin_process_events(void) Line 1934  xwin_process_events(void)
1934                          case PropertyNotify:                          case PropertyNotify:
1935                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1936                                  break;                                  break;
1937                            case MapNotify:
1938                                    if (!g_seamless_rdp)
1939                                            rdp_send_client_window_status(1);
1940                                    break;
1941                            case UnmapNotify:
1942                                    if (!g_seamless_rdp)
1943                                            rdp_send_client_window_status(0);
1944                                    break;
1945                  }                  }
1946          }          }
1947          /* Keep going */          /* Keep going */
# Line 1646  ui_create_bitmap(int width, int height, Line 2025  ui_create_bitmap(int width, int height,
2025          uint8 *tdata;          uint8 *tdata;
2026          int bitmap_pad;          int bitmap_pad;
2027    
2028          if (g_server_bpp == 8)          if (g_server_depth == 8)
2029          {          {
2030                  bitmap_pad = 8;                  bitmap_pad = 8;
2031          }          }
# Line 1678  ui_paint_bitmap(int x, int y, int cx, in Line 2057  ui_paint_bitmap(int x, int y, int cx, in
2057          uint8 *tdata;          uint8 *tdata;
2058          int bitmap_pad;          int bitmap_pad;
2059    
2060          if (g_server_bpp == 8)          if (g_server_depth == 8)
2061          {          {
2062                  bitmap_pad = 8;                  bitmap_pad = 8;
2063          }          }
# Line 1698  ui_paint_bitmap(int x, int y, int cx, in Line 2077  ui_paint_bitmap(int x, int y, int cx, in
2077          {          {
2078                  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);
2079                  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);
2080                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2081                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2082                                             x - sw->xoffset, y - sw->yoffset));
2083          }          }
2084          else          else
2085          {          {
2086                  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);
2087                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2088                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2089                                             x - sw->xoffset, y - sw->yoffset));
2090          }          }
2091    
2092          XFree(image);          XFree(image);
# Line 1822  ui_set_cursor(HCURSOR cursor) Line 2207  ui_set_cursor(HCURSOR cursor)
2207  {  {
2208          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2209          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2210            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2211  }  }
2212    
2213  void  void
# Line 1963  ui_set_colourmap(HCOLOURMAP map) Line 2349  ui_set_colourmap(HCOLOURMAP map)
2349                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2350          }          }
2351          else          else
2352            {
2353                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2354                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2355            }
2356  }  }
2357    
2358  void  void
2359  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2360  {  {
2361          XRectangle rect;          g_clip_rectangle.x = x;
2362            g_clip_rectangle.y = y;
2363          rect.x = x;          g_clip_rectangle.width = cx;
2364          rect.y = y;          g_clip_rectangle.height = cy;
2365          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);  
2366  }  }
2367    
2368  void  void
2369  ui_reset_clip(void)  ui_reset_clip(void)
2370  {  {
2371          XRectangle rect;          g_clip_rectangle.x = 0;
2372            g_clip_rectangle.y = 0;
2373          rect.x = 0;          g_clip_rectangle.width = g_width;
2374          rect.y = 0;          g_clip_rectangle.height = g_height;
2375          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);  
2376  }  }
2377    
2378  void  void
# Line 2068  ui_patblt(uint8 opcode, Line 2453  ui_patblt(uint8 opcode,
2453    
2454          if (g_ownbackstore)          if (g_ownbackstore)
2455                  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);
2456            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2457                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2458                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2459  }  }
2460    
2461  void  void
# Line 2078  ui_screenblt(uint8 opcode, Line 2466  ui_screenblt(uint8 opcode,
2466          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2467          if (g_ownbackstore)          if (g_ownbackstore)
2468          {          {
2469                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2470                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2471                          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);  
                 }  
2472          }          }
2473          else          else
2474          {          {
2475                  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);
2476          }          }
2477    
2478            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2479                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2480                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2481    
2482          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2483  }  }
2484    
# Line 2105  ui_memblt(uint8 opcode, Line 2489  ui_memblt(uint8 opcode,
2489  {  {
2490          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2491          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);
2492            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2493                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2494                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2495          if (g_ownbackstore)          if (g_ownbackstore)
2496                  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);
2497          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2151  ui_line(uint8 opcode, Line 2538  ui_line(uint8 opcode,
2538          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2539          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2540          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2541            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2542                                                startx - sw->xoffset, starty - sw->yoffset,
2543                                                endx - sw->xoffset, endy - sw->yoffset));
2544          if (g_ownbackstore)          if (g_ownbackstore)
2545                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2546          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2165  ui_rect( Line 2555  ui_rect(
2555          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2556  }  }
2557    
2558    void
2559    ui_polygon(uint8 opcode,
2560               /* mode */ uint8 fillmode,
2561               /* dest */ POINT * point, int npoints,
2562               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2563    {
2564            uint8 style, i, ipattern[8];
2565            Pixmap fill;
2566    
2567            SET_FUNCTION(opcode);
2568    
2569            switch (fillmode)
2570            {
2571                    case ALTERNATE:
2572                            XSetFillRule(g_display, g_gc, EvenOddRule);
2573                            break;
2574                    case WINDING:
2575                            XSetFillRule(g_display, g_gc, WindingRule);
2576                            break;
2577                    default:
2578                            unimpl("fill mode %d\n", fillmode);
2579            }
2580    
2581            if (brush)
2582                    style = brush->style;
2583            else
2584                    style = 0;
2585    
2586            switch (style)
2587            {
2588                    case 0: /* Solid */
2589                            SET_FOREGROUND(fgcolour);
2590                            FILL_POLYGON((XPoint *) point, npoints);
2591                            break;
2592    
2593                    case 2: /* Hatch */
2594                            fill = (Pixmap) ui_create_glyph(8, 8,
2595                                                            hatch_patterns + brush->pattern[0] * 8);
2596                            SET_FOREGROUND(fgcolour);
2597                            SET_BACKGROUND(bgcolour);
2598                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2599                            XSetStipple(g_display, g_gc, fill);
2600                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2601                            FILL_POLYGON((XPoint *) point, npoints);
2602                            XSetFillStyle(g_display, g_gc, FillSolid);
2603                            XSetTSOrigin(g_display, g_gc, 0, 0);
2604                            ui_destroy_glyph((HGLYPH) fill);
2605                            break;
2606    
2607                    case 3: /* Pattern */
2608                            for (i = 0; i != 8; i++)
2609                                    ipattern[7 - i] = brush->pattern[i];
2610                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2611                            SET_FOREGROUND(bgcolour);
2612                            SET_BACKGROUND(fgcolour);
2613                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2614                            XSetStipple(g_display, g_gc, fill);
2615                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2616                            FILL_POLYGON((XPoint *) point, npoints);
2617                            XSetFillStyle(g_display, g_gc, FillSolid);
2618                            XSetTSOrigin(g_display, g_gc, 0, 0);
2619                            ui_destroy_glyph((HGLYPH) fill);
2620                            break;
2621    
2622                    default:
2623                            unimpl("brush %d\n", brush->style);
2624            }
2625    
2626            RESET_FUNCTION(opcode);
2627    }
2628    
2629    void
2630    ui_polyline(uint8 opcode,
2631                /* dest */ POINT * points, int npoints,
2632                /* pen */ PEN * pen)
2633    {
2634            /* TODO: set join style */
2635            SET_FUNCTION(opcode);
2636            SET_FOREGROUND(pen->colour);
2637            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2638            if (g_ownbackstore)
2639                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2640                               CoordModePrevious);
2641    
2642            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2643                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2644    
2645            RESET_FUNCTION(opcode);
2646    }
2647    
2648    void
2649    ui_ellipse(uint8 opcode,
2650               /* mode */ uint8 fillmode,
2651               /* dest */ int x, int y, int cx, int cy,
2652               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2653    {
2654            uint8 style, i, ipattern[8];
2655            Pixmap fill;
2656    
2657            SET_FUNCTION(opcode);
2658    
2659            if (brush)
2660                    style = brush->style;
2661            else
2662                    style = 0;
2663    
2664            switch (style)
2665            {
2666                    case 0: /* Solid */
2667                            SET_FOREGROUND(fgcolour);
2668                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2669                            break;
2670    
2671                    case 2: /* Hatch */
2672                            fill = (Pixmap) ui_create_glyph(8, 8,
2673                                                            hatch_patterns + brush->pattern[0] * 8);
2674                            SET_FOREGROUND(fgcolour);
2675                            SET_BACKGROUND(bgcolour);
2676                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2677                            XSetStipple(g_display, g_gc, fill);
2678                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2679                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2680                            XSetFillStyle(g_display, g_gc, FillSolid);
2681                            XSetTSOrigin(g_display, g_gc, 0, 0);
2682                            ui_destroy_glyph((HGLYPH) fill);
2683                            break;
2684    
2685                    case 3: /* Pattern */
2686                            for (i = 0; i != 8; i++)
2687                                    ipattern[7 - i] = brush->pattern[i];
2688                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2689                            SET_FOREGROUND(bgcolour);
2690                            SET_BACKGROUND(fgcolour);
2691                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2692                            XSetStipple(g_display, g_gc, fill);
2693                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2694                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2695                            XSetFillStyle(g_display, g_gc, FillSolid);
2696                            XSetTSOrigin(g_display, g_gc, 0, 0);
2697                            ui_destroy_glyph((HGLYPH) fill);
2698                            break;
2699    
2700                    default:
2701                            unimpl("brush %d\n", brush->style);
2702            }
2703    
2704            RESET_FUNCTION(opcode);
2705    }
2706    
2707  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2708  void  void
2709  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 2220  ui_draw_glyph(int mixmode, Line 2759  ui_draw_glyph(int mixmode,
2759  }  }
2760    
2761  void  void
2762  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,
2763               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2764               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2765               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2766  {  {
2767            /* TODO: use brush appropriately */
2768    
2769          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2770          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
2771          DATABLOB *entry;          DATABLOB *entry;
# Line 2256  ui_draw_text(uint8 font, uint8 flags, in Line 2797  ui_draw_text(uint8 font, uint8 flags, in
2797                  switch (text[i])                  switch (text[i])
2798                  {                  {
2799                          case 0xff:                          case 0xff:
2800                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2801                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2802                                  {                                  {
2803                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2804                                          exit(1);                                          for (j = 0; j < length; j++)
2805                                                    fprintf(stderr, "%02x ", text[j]);
2806                                            fprintf(stderr, "\n");
2807                                            i = length = 0;
2808                                            break;
2809                                  }                                  }
2810                                    cache_put_text(text[i + 1], text, text[i + 2]);
2811                                    i += 3;
2812                                    length -= i;
2813                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2814                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2815                                  i = 0;                                  i = 0;
2816                                  break;                                  break;
2817    
2818                          case 0xfe:                          case 0xfe:
2819                                    /* At least one byte needs to follow */
2820                                    if (i + 2 > length)
2821                                    {
2822                                            warning("Skipping short 0xfe command:");
2823                                            for (j = 0; j < length; j++)
2824                                                    fprintf(stderr, "%02x ", text[j]);
2825                                            fprintf(stderr, "\n");
2826                                            i = length = 0;
2827                                            break;
2828                                    }
2829                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2830                                  if (entry != NULL)                                  if (entry->data != NULL)
2831                                  {                                  {
2832                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2833                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2834                                          {                                          {
2835                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2836                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2306  ui_draw_text(uint8 font, uint8 flags, in Line 2862  ui_draw_text(uint8 font, uint8 flags, in
2862          if (g_ownbackstore)          if (g_ownbackstore)
2863          {          {
2864                  if (boxcx > 1)                  if (boxcx > 1)
2865                    {
2866                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2867                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2868                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2869                                                    (g_display, g_backstore, sw->wnd, g_gc,
2870                                                     boxx, boxy,
2871                                                     boxcx, boxcy,
2872                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2873                    }
2874                  else                  else
2875                    {
2876                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2877                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2878                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2879                                                    (g_display, g_backstore, sw->wnd, g_gc,
2880                                                     clipx, clipy,
2881                                                     clipcx, clipcy, clipx - sw->xoffset,
2882                                                     clipy - sw->yoffset));
2883                    }
2884          }          }
2885  }  }
2886    
# Line 2356  ui_desktop_restore(uint32 offset, int x, Line 2926  ui_desktop_restore(uint32 offset, int x,
2926          {          {
2927                  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);
2928                  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);
2929                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2930                                            (g_display, g_backstore, sw->wnd, g_gc,
2931                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2932          }          }
2933          else          else
2934          {          {
2935                  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);
2936                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2937                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2938                                             x - sw->xoffset, y - sw->yoffset));
2939          }          }
2940    
2941          XFree(image);          XFree(image);
# Line 2375  void Line 2951  void
2951  ui_end_update(void)  ui_end_update(void)
2952  {  {
2953  }  }
2954    
2955    void
2956    ui_seamless_toggle()
2957    {
2958            if (g_seamless_rdp)
2959            {
2960                    /* Deactivate */
2961                    while (g_seamless_windows)
2962                    {
2963                            XDestroyWindow(g_display, g_seamless_windows->wnd);
2964                            seamless_remove_window(g_seamless_windows);
2965                    }
2966                    XMapWindow(g_display, g_wnd);
2967            }
2968            else
2969            {
2970                    /* Activate */
2971                    if (g_win_button_size)
2972                    {
2973                            error("SeamlessRDP mode cannot be activated when using single application mode\n");
2974                            return;
2975                    }
2976                    if (!g_using_full_workarea)
2977                    {
2978                            error("SeamlessRDP mode requires a session that covers the whole screen");
2979                            return;
2980                    }
2981    
2982                    XUnmapWindow(g_display, g_wnd);
2983                    seamless_send_sync();
2984            }
2985    
2986            g_seamless_rdp = !g_seamless_rdp;
2987    }
2988    
2989    void
2990    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
2991    {
2992            Window wnd;
2993            XSetWindowAttributes attribs;
2994            XClassHint *classhints;
2995            long input_mask;
2996            seamless_window *sw, *sw_parent;
2997    
2998            get_window_attribs(&attribs);
2999    
3000            attribs.override_redirect = False;
3001    
3002            /* FIXME: Do not assume that -1, -1 is outside screen Consider
3003               wait with showing the window until STATE and others have
3004               been recieved. */
3005            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, 0,
3006                                InputOutput, g_visual,
3007                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3008                                CWBorderPixel, &attribs);
3009    
3010            XStoreName(g_display, wnd, "rdesktop-seamless");
3011    
3012            mwm_hide_decorations(wnd);
3013    
3014            classhints = XAllocClassHint();
3015            if (classhints != NULL)
3016            {
3017                    classhints->res_name = classhints->res_class = "rdesktop";
3018                    XSetClassHint(g_display, wnd, classhints);
3019                    XFree(classhints);
3020            }
3021    
3022            /* Set WM_TRANSIENT_FOR, if necessary */
3023            if (parent)
3024            {
3025                    sw_parent = seamless_get_window_by_id(parent);
3026                    if (sw_parent)
3027                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3028                    else
3029                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3030            }
3031    
3032            /* FIXME: Support for Input Context:s */
3033    
3034            get_input_mask(&input_mask);
3035    
3036            XSelectInput(g_display, wnd, input_mask);
3037    
3038            XMapWindow(g_display, wnd);
3039    
3040            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3041               seamless window, we could try to close the window on the
3042               serverside, instead of terminating rdesktop */
3043            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3044    
3045            sw = malloc(sizeof(seamless_window));
3046            sw->wnd = wnd;
3047            sw->id = id;
3048            sw->xoffset = 0;
3049            sw->yoffset = 0;
3050            sw->width = 0;
3051            sw->height = 0;
3052            sw->next = g_seamless_windows;
3053            g_seamless_windows = sw;
3054    }
3055    
3056    
3057    void
3058    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3059    {
3060            seamless_window *sw;
3061            sw = seamless_get_window_by_id(id);
3062    
3063            if (!sw)
3064            {
3065                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3066                    return;
3067            }
3068    
3069            XDestroyWindow(g_display, sw->wnd);
3070            seamless_remove_window(sw);
3071    }
3072    
3073    
3074    void
3075    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3076    {
3077            seamless_window *sw;
3078    
3079            sw = seamless_get_window_by_id(id);
3080    
3081            if (!sw)
3082            {
3083                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3084                    return;
3085            }
3086    
3087            if (!width || !height)
3088                    /* X11 windows must be at least 1x1 */
3089                    return;
3090    
3091            /* About MAX and MIN: Windows allows moving a window outside
3092               the desktop. This happens, for example, when maximizing an
3093               application. In this case, the position is set to something
3094               like -4,-4,1288,1032. Many WMs does not allow windows
3095               outside the desktop, however. Therefore, clip the window
3096               ourselves. */
3097            sw->xoffset = MAX(0, x);
3098            sw->yoffset = MAX(0, y);
3099            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3100            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3101    
3102            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3103            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3104    }
3105    
3106    
3107    void
3108    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3109    {
3110            seamless_window *sw;
3111    
3112            sw = seamless_get_window_by_id(id);
3113    
3114            XStoreName(g_display, sw->wnd, title);
3115    }
3116    
3117    
3118    void
3119    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3120    {
3121            seamless_window *sw;
3122    
3123            sw = seamless_get_window_by_id(id);
3124    
3125            switch (state)
3126            {
3127                    case SEAMLESSRDP_NORMAL:
3128                    case SEAMLESSRDP_MAXIMIZED:
3129                            XMapWindow(g_display, sw->wnd);
3130                            break;
3131                    case SEAMLESSRDP_MINIMIZED:
3132                            XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3133                            break;
3134                    default:
3135                            warning("SeamlessRDP: Invalid state %d\n", state);
3136                            break;
3137            }
3138    }

Legend:
Removed from v.822  
changed lines
  Added in v.1105

  ViewVC Help
Powered by ViewVC 1.1.26