/[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 709 by jsorg71, Fri Jun 11 22:37:05 2004 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1157 by astrand, Fri Mar 17 12:39:09 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 30  Line 30 
30    
31  extern int g_width;  extern int g_width;
32  extern int g_height;  extern int g_height;
33    extern int g_xpos;
34    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 43  Time g_last_gesturetime; Line 48  Time g_last_gesturetime;
48  static int g_x_socket;  static int g_x_socket;
49  static Screen *g_screen;  static Screen *g_screen;
50  Window g_wnd;  Window g_wnd;
51    
52    /* SeamlessRDP support */
53    typedef struct _seamless_window
54    {
55            Window wnd;
56            unsigned long id;
57            unsigned long parent;
58            unsigned long behind;
59            int xoffset, yoffset;
60            int width, height;
61            int state;              /* normal/minimized/maximized. */
62            unsigned int desktop;
63            struct timeval *position_timer;
64            struct _seamless_window *next;
65    } seamless_window;
66    static seamless_window *g_seamless_windows = NULL;
67    static unsigned long g_seamless_focused = 0;
68    static BOOL g_seamless_started = False; /* Server end is up and running */
69    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
70    extern BOOL g_seamless_rdp;
71    
72  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
73  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
74  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
75  static GC g_gc = NULL;  static GC g_gc = NULL;
76    static GC g_create_bitmap_gc = NULL;
77    static GC g_create_glyph_gc = NULL;
78    static XRectangle g_clip_rectangle;
79  static Visual *g_visual;  static Visual *g_visual;
80    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
81       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
82       as far as we're concerned. */
83  static int g_depth;  static int g_depth;
84    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
85       This may be larger than g_depth, in which case some of the bits would
86       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
87  static int g_bpp;  static int g_bpp;
88  static XIM g_IM;  static XIM g_IM;
89  static XIC g_IC;  static XIC g_IC;
# Line 56  static XModifierKeymap *g_mod_map; Line 91  static XModifierKeymap *g_mod_map;
91  static Cursor g_current_cursor;  static Cursor g_current_cursor;
92  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
93  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
94    extern Atom g_net_wm_state_atom;
95    extern Atom g_net_wm_desktop_atom;
96  static BOOL g_focused;  static BOOL g_focused;
97  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
98  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* Indicates that:
99       1) visual has 15, 16 or 24 depth and the same color channel masks
100          as its RDP equivalent (implies X server is LE),
101       2) host is LE
102       This will trigger an optimization whose real value is questionable.
103    */
104    static BOOL g_compatible_arch;
105    /* Indicates whether RDP's bitmaps and our XImages have the same
106       binary format. If so, we can avoid an expensive translation.
107       Note that this can be true when g_compatible_arch is false,
108       e.g.:
109      
110         RDP(LE) <-> host(BE) <-> X-Server(LE)
111        
112       ('host' is the machine running rdesktop; the host simply memcpy's
113        so its endianess doesn't matter)
114     */
115    static BOOL g_no_translate_image = False;
116    
117  /* endianness */  /* endianness */
118  static BOOL g_host_be;  static BOOL g_host_be;
# Line 74  static Pixmap g_backstore = 0; Line 128  static Pixmap g_backstore = 0;
128  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
129  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
130  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
131    static BOOL g_using_full_workarea = False;
132    
133  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
134  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 86  extern BOOL g_rdpsnd; Line 141  extern BOOL g_rdpsnd;
141  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
142  typedef struct  typedef struct
143  {  {
144          uint32 flags;          unsigned long flags;
145          uint32 functions;          unsigned long functions;
146          uint32 decorations;          unsigned long decorations;
147          sint32 inputMode;          long inputMode;
148          uint32 status;          unsigned long status;
149  }  }
150  PropMotifWmHints;  PropMotifWmHints;
151    
# Line 102  typedef struct Line 157  typedef struct
157  }  }
158  PixelColour;  PixelColour;
159    
160    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
161            do { \
162                    seamless_window *sw; \
163                    XRectangle rect; \
164                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
165                        rect.x = g_clip_rectangle.x - sw->xoffset; \
166                        rect.y = g_clip_rectangle.y - sw->yoffset; \
167                        rect.width = g_clip_rectangle.width; \
168                        rect.height = g_clip_rectangle.height; \
169                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
170                        func args; \
171                    } \
172                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
173            } while (0)
174    
175    static void
176    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
177    {
178            points[0].x -= xoffset;
179            points[0].y -= yoffset;
180            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
181            points[0].x += xoffset;
182            points[0].y += yoffset;
183    }
184    
185    static void
186    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
187    {
188            points[0].x -= xoffset;
189            points[0].y -= yoffset;
190            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
191            points[0].x += xoffset;
192            points[0].y += yoffset;
193    }
194    
195  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
196  { \  { \
197          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
198            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
199          if (g_ownbackstore) \          if (g_ownbackstore) \
200                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
201  }  }
# Line 115  PixelColour; Line 205  PixelColour;
205          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); \
206  }  }
207    
208    #define FILL_POLYGON(p,np)\
209    { \
210            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
211            if (g_ownbackstore) \
212                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
213            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
214    }
215    
216    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
217    { \
218            switch (m) \
219            { \
220                    case 0: /* Outline */ \
221                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
222                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
223                            if (g_ownbackstore) \
224                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
225                            break; \
226                    case 1: /* Filled */ \
227                            XFillArc(g_display, g_wnd, g_gc, x, y, \
228                                     cx, cy, 0, 360*64); \
229                            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)); \
230                            if (g_ownbackstore) \
231                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
232                            break; \
233            } \
234    }
235    
236  /* colour maps */  /* colour maps */
237  extern BOOL g_owncolmap;  extern BOOL g_owncolmap;
238  static Colormap g_xcolmap;  static Colormap g_xcolmap;
239  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
240    
241  #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] )
242  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
243  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
244    
# Line 146  static int rop2_map[] = { Line 264  static int rop2_map[] = {
264  #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]); }
265  #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); }
266    
267    static seamless_window *
268    seamless_get_window_by_id(unsigned long id)
269    {
270            seamless_window *sw;
271            for (sw = g_seamless_windows; sw; sw = sw->next)
272            {
273                    if (sw->id == id)
274                            return sw;
275            }
276            return NULL;
277    }
278    
279    
280    static seamless_window *
281    seamless_get_window_by_wnd(Window wnd)
282    {
283            seamless_window *sw;
284            for (sw = g_seamless_windows; sw; sw = sw->next)
285            {
286                    if (sw->wnd == wnd)
287                            return sw;
288            }
289            return NULL;
290    }
291    
292    
293    static void
294    seamless_remove_window(seamless_window * win)
295    {
296            seamless_window *sw, **prevnext = &g_seamless_windows;
297            for (sw = g_seamless_windows; sw; sw = sw->next)
298            {
299                    if (sw == win)
300                    {
301                            *prevnext = sw->next;
302                            xfree(sw);
303                            return;
304                    }
305                    prevnext = &sw->next;
306            }
307            return;
308    }
309    
310    
311    /* Move all windows except wnd to new desktop */
312    static void
313    seamless_all_to_desktop(Window wnd, unsigned int desktop)
314    {
315            seamless_window *sw;
316            for (sw = g_seamless_windows; sw; sw = sw->next)
317            {
318                    if (sw->wnd == wnd)
319                            continue;
320                    if (sw->desktop != desktop)
321                    {
322                            ewmh_move_to_desktop(sw->wnd, desktop);
323                            sw->desktop = desktop;
324                    }
325            }
326    }
327    
328    
329    /* Send our position */
330    static void
331    seamless_update_position(seamless_window * sw)
332    {
333            XWindowAttributes wa;
334            int x, y;
335            Window child_return;
336    
337            XGetWindowAttributes(g_display, sw->wnd, &wa);
338            XTranslateCoordinates(g_display, sw->wnd, wa.root,
339                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
340    
341            seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
342            sw->xoffset = x;
343            sw->yoffset = y;
344            sw->width = wa.width;
345            sw->height = wa.height;
346    }
347    
348    
349    /* Check if it's time to send our position */
350    static void
351    seamless_check_timers()
352    {
353            seamless_window *sw;
354            struct timeval now;
355    
356            gettimeofday(&now, NULL);
357            for (sw = g_seamless_windows; sw; sw = sw->next)
358            {
359                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
360                    {
361                            timerclear(sw->position_timer);
362                            seamless_update_position(sw);
363                    }
364            }
365    }
366    
367    
368  static void  static void
369  mwm_hide_decorations(void)  seamless_restack_window(seamless_window * sw, unsigned long behind)
370    {
371            seamless_window *sw_above;
372    
373            /* Remove window from stack */
374            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
375            {
376                    if (sw_above->behind == sw->id)
377                            break;
378            }
379    
380            if (sw_above)
381                    sw_above->behind = sw->behind;
382    
383            /* And then add it at the new position */
384    
385            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
386            {
387                    if (sw_above->behind == behind)
388                            break;
389            }
390    
391            if (sw_above)
392                    sw_above->behind = sw->id;
393    
394            sw->behind = behind;
395    }
396    
397    
398    static void
399    mwm_hide_decorations(Window wnd)
400  {  {
401          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
402          Atom hintsatom;          Atom hintsatom;
# Line 164  mwm_hide_decorations(void) Line 413  mwm_hide_decorations(void)
413                  return;                  return;
414          }          }
415    
416          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
417                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
418    
419  }  }
420    
421  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
422  split_colour15(uint32 colour)  { \
423  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
424          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
425          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7);          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
         rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7);  
         rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);  
         return rv;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7);  
         rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3);  
         rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);  
         return rv;  
 }  
   
 static PixelColour  
 split_colour24(uint32 colour)  
 {  
         PixelColour rv;  
         rv.blue = (colour & 0xff0000) >> 16;  
         rv.green = (colour & 0x00ff00) >> 8;  
         rv.red = (colour & 0x0000ff);  
         return rv;  
426  }  }
427    
428  static uint32  #define SPLITCOLOUR16(colour, rv) \
429  make_colour(PixelColour pc)  { \
430  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
431          return (((pc.red >> g_red_shift_r) << g_red_shift_l)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
432                  | ((pc.green >> g_green_shift_r) << g_green_shift_l)          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
433                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));  } \
434    
435    #define SPLITCOLOUR24(colour, rv) \
436    { \
437            rv.blue = (colour & 0xff0000) >> 16; \
438            rv.green = (colour & 0x00ff00) >> 8; \
439            rv.red = (colour & 0x0000ff); \
440  }  }
441    
442    #define MAKECOLOUR(pc) \
443            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
444                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
445                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
446    
447  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
448  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
449  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
450                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
451    
452    /* The following macros output the same octet sequences
453       on both BE and LE hosts: */
454    
455    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
456    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
457    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
458    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
459    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
460    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
461    
462  static uint32  static uint32
463  translate_colour(uint32 colour)  translate_colour(uint32 colour)
464  {  {
465          PixelColour pc;          PixelColour pc;
466          switch (g_server_bpp)          switch (g_server_depth)
467          {          {
468                  case 15:                  case 15:
469                          pc = split_colour15(colour);                          SPLITCOLOUR15(colour, pc);
470                          break;                          break;
471                  case 16:                  case 16:
472                          pc = split_colour16(colour);                          SPLITCOLOUR16(colour, pc);
473                          break;                          break;
474                  case 24:                  case 24:
475                          pc = split_colour24(colour);                          SPLITCOLOUR24(colour, pc);
476                            break;
477                    default:
478                            /* Avoid warning */
479                            pc.red = 0;
480                            pc.green = 0;
481                            pc.blue = 0;
482                          break;                          break;
483          }          }
484          return make_colour(pc);          return MAKECOLOUR(pc);
485  }  }
486    
487  /* indent is confused by UNROLL8 */  /* indent is confused by UNROLL8 */
# Line 247  translate_colour(uint32 colour) Line 501  translate_colour(uint32 colour)
501          while (out < end) \          while (out < end) \
502                  { stm } \                  { stm } \
503  }  }
504    /* 3 byte output repeat */
505    #define REPEAT3(stm) \
506    { \
507            while (out <= end - 8 * 3) \
508                    UNROLL8(stm) \
509            while (out < end) \
510                    { stm } \
511    }
512  /* 4 byte output repeat */  /* 4 byte output repeat */
513  #define REPEAT4(stm) \  #define REPEAT4(stm) \
514  { \  { \
# Line 255  translate_colour(uint32 colour) Line 517  translate_colour(uint32 colour)
517          while (out < end) \          while (out < end) \
518                  { stm } \                  { stm } \
519  }  }
520    /* *INDENT-ON* */
521    
522  static void  static void
523  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
524  {  {
525          while (out < end)          while (out < end)
526                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
527  }  }
528    
529  static void  static void
530  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
531  {  {
532          uint16 value;          uint16 value;
533    
534          if (g_arch_match)          if (g_compatible_arch)
535          {          {
536                    /* *INDENT-OFF* */
537                  REPEAT2                  REPEAT2
538                  (                  (
539                          *((uint16 *) out) = g_colmap[*(data++)];                          *((uint16 *) out) = g_colmap[*(data++)];
540                          out += 2;                          out += 2;
541                  )                  )
542                    /* *INDENT-ON* */
543          }          }
544          else if (g_xserver_be)          else if (g_xserver_be)
545          {          {
546                  while (out < end)                  while (out < end)
547                  {                  {
548                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
549                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
550                  }                  }
551          }          }
552          else          else
# Line 290  translate8to16(uint8 * data, uint8 * out Line 554  translate8to16(uint8 * data, uint8 * out
554                  while (out < end)                  while (out < end)
555                  {                  {
556                          value = (uint16) g_colmap[*(data++)];                          value = (uint16) g_colmap[*(data++)];
557                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
558                  }                  }
559          }          }
560  }  }
561    
562  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
563  static void  static void
564  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
565  {  {
566          uint32 value;          uint32 value;
567    
568          if (g_xserver_be)          if (g_compatible_arch)
569          {          {
570                  while (out < end)                  while (out < end)
571                  {                  {
572                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
573                          *(out++) = value >> 16;                          BOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
574                  }                  }
575          }          }
576          else          else
# Line 317  translate8to24(uint8 * data, uint8 * out Line 578  translate8to24(uint8 * data, uint8 * out
578                  while (out < end)                  while (out < end)
579                  {                  {
580                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
581                          *(out++) = value;                          LOUT24(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
582                  }                  }
583          }          }
584  }  }
585    
586  static void  static void
587  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
588  {  {
589          uint32 value;          uint32 value;
590    
591          if (g_arch_match)          if (g_compatible_arch)
592          {          {
593                    /* *INDENT-OFF* */
594                  REPEAT4                  REPEAT4
595                  (                  (
596                          *((uint32 *) out) = g_colmap[*(data++)];                          *((uint32 *) out) = g_colmap[*(data++)];
597                          out += 4;                          out += 4;
598                  )                  )
599                    /* *INDENT-ON* */
600          }          }
601          else if (g_xserver_be)          else if (g_xserver_be)
602          {          {
603                  while (out < end)                  while (out < end)
604                  {                  {
605                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
606                          *(out++) = value >> 24;                          BOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 8;  
                         *(out++) = value;  
607                  }                  }
608          }          }
609          else          else
# Line 353  translate8to32(uint8 * data, uint8 * out Line 611  translate8to32(uint8 * data, uint8 * out
611                  while (out < end)                  while (out < end)
612                  {                  {
613                          value = g_colmap[*(data++)];                          value = g_colmap[*(data++)];
614                          *(out++) = value;                          LOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
615                  }                  }
616          }          }
617  }  }
618    
 /* *INDENT-ON* */  
   
619  static void  static void
620  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
621  {  {
622          uint16 pixel;          uint16 pixel;
623          uint16 value;          uint16 value;
624            PixelColour pc;
625    
626          while (out < end)          if (g_xserver_be)
627          {          {
628                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel);  
                 }  
   
                 value = make_colour(split_colour15(pixel));  
   
                 if (g_xserver_be)  
629                  {                  {
630                          *(out++) = value >> 8;                          pixel = *(data++);
631                          *(out++) = value;                          if (g_host_be)
632                            {
633                                    BSWAP16(pixel);
634                            }
635                            SPLITCOLOUR15(pixel, pc);
636                            value = MAKECOLOUR(pc);
637                            BOUT16(out, value);
638                  }                  }
639                  else          }
640            else
641            {
642                    while (out < end)
643                  {                  {
644                          *(out++) = value;                          pixel = *(data++);
645                          *(out++) = value >> 8;                          if (g_host_be)
646                            {
647                                    BSWAP16(pixel);
648                            }
649                            SPLITCOLOUR15(pixel, pc);
650                            value = MAKECOLOUR(pc);
651                            LOUT16(out, value);
652                  }                  }
653          }          }
654  }  }
655    
656  static void  static void
657  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
658  {  {
659          uint32 value;          uint32 value;
660          uint16 pixel;          uint16 pixel;
661            PixelColour pc;
662    
663          while (out < end)          if (g_compatible_arch)
664          {          {
665                  pixel = *(data++);                  /* *INDENT-OFF* */
666                    REPEAT3
667                  if (g_host_be)                  (
668                  {                          pixel = *(data++);
669                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
670                  }                          *(out++) = pc.blue;
671                            *(out++) = pc.green;
672                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
673                  if (g_xserver_be)                  )
674                    /* *INDENT-ON* */
675            }
676            else if (g_xserver_be)
677            {
678                    while (out < end)
679                  {                  {
680                          *(out++) = value >> 16;                          pixel = *(data++);
681                          *(out++) = value >> 8;                          if (g_host_be)
682                          *(out++) = value;                          {
683                                    BSWAP16(pixel);
684                            }
685                            SPLITCOLOUR15(pixel, pc);
686                            value = MAKECOLOUR(pc);
687                            BOUT24(out, value);
688                  }                  }
689                  else          }
690            else
691            {
692                    while (out < end)
693                  {                  {
694                          *(out++) = value;                          pixel = *(data++);
695                          *(out++) = value >> 8;                          if (g_host_be)
696                          *(out++) = value >> 16;                          {
697                                    BSWAP16(pixel);
698                            }
699                            SPLITCOLOUR15(pixel, pc);
700                            value = MAKECOLOUR(pc);
701                            LOUT24(out, value);
702                  }                  }
703          }          }
704  }  }
705    
706  static void  static void
707  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
708  {  {
709          uint16 pixel;          uint16 pixel;
710          uint32 value;          uint32 value;
711            PixelColour pc;
712    
713          while (out < end)          if (g_compatible_arch)
714          {          {
715                  pixel = *(data++);                  /* *INDENT-OFF* */
716                    REPEAT4
717                  if (g_host_be)                  (
718                  {                          pixel = *(data++);
719                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
720                  }                          *(out++) = pc.blue;
721                            *(out++) = pc.green;
722                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
723                            *(out++) = 0;
724                  if (g_xserver_be)                  )
725                    /* *INDENT-ON* */
726            }
727            else if (g_xserver_be)
728            {
729                    while (out < end)
730                  {                  {
731                          *(out++) = value >> 24;                          pixel = *(data++);
732                          *(out++) = value >> 16;                          if (g_host_be)
733                          *(out++) = value >> 8;                          {
734                          *(out++) = value;                                  BSWAP16(pixel);
735                            }
736                            SPLITCOLOUR15(pixel, pc);
737                            value = MAKECOLOUR(pc);
738                            BOUT32(out, value);
739                  }                  }
740                  else          }
741            else
742            {
743                    while (out < end)
744                  {                  {
745                          *(out++) = value;                          pixel = *(data++);
746                          *(out++) = value >> 8;                          if (g_host_be)
747                          *(out++) = value >> 16;                          {
748                          *(out++) = value >> 24;                                  BSWAP16(pixel);
749                            }
750                            SPLITCOLOUR15(pixel, pc);
751                            value = MAKECOLOUR(pc);
752                            LOUT32(out, value);
753                  }                  }
754          }          }
755  }  }
756    
757  static void  static void
758  translate16to16(uint16 * data, uint8 * out, uint8 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
759  {  {
760          uint16 pixel;          uint16 pixel;
761          uint16 value;          uint16 value;
762            PixelColour pc;
763    
764          while (out < end)          if (g_xserver_be)
765          {          {
                 pixel = *(data++);  
   
766                  if (g_host_be)                  if (g_host_be)
767                  {                  {
768                          BSWAP16(pixel);                          while (out < end)
769                            {
770                                    pixel = *(data++);
771                                    BSWAP16(pixel);
772                                    SPLITCOLOUR16(pixel, pc);
773                                    value = MAKECOLOUR(pc);
774                                    BOUT16(out, value);
775                            }
776                  }                  }
777                    else
778                  value = make_colour(split_colour16(pixel));                  {
779                            while (out < end)
780                  if (g_xserver_be)                          {
781                                    pixel = *(data++);
782                                    SPLITCOLOUR16(pixel, pc);
783                                    value = MAKECOLOUR(pc);
784                                    BOUT16(out, value);
785                            }
786                    }
787            }
788            else
789            {
790                    if (g_host_be)
791                  {                  {
792                          *(out++) = value >> 8;                          while (out < end)
793                          *(out++) = value;                          {
794                                    pixel = *(data++);
795                                    BSWAP16(pixel);
796                                    SPLITCOLOUR16(pixel, pc);
797                                    value = MAKECOLOUR(pc);
798                                    LOUT16(out, value);
799                            }
800                  }                  }
801                  else                  else
802                  {                  {
803                          *(out++) = value;                          while (out < end)
804                          *(out++) = value >> 8;                          {
805                                    pixel = *(data++);
806                                    SPLITCOLOUR16(pixel, pc);
807                                    value = MAKECOLOUR(pc);
808                                    LOUT16(out, value);
809                            }
810                  }                  }
811          }          }
812  }  }
813    
814  static void  static void
815  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
816  {  {
817          uint32 value;          uint32 value;
818          uint16 pixel;          uint16 pixel;
819            PixelColour pc;
820    
821          while (out < end)          if (g_compatible_arch)
822            {
823                    /* *INDENT-OFF* */
824                    REPEAT3
825                    (
826                            pixel = *(data++);
827                            SPLITCOLOUR16(pixel, pc);
828                            *(out++) = pc.blue;
829                            *(out++) = pc.green;
830                            *(out++) = pc.red;
831                    )
832                    /* *INDENT-ON* */
833            }
834            else if (g_xserver_be)
835          {          {
                 pixel = *(data++);  
   
836                  if (g_host_be)                  if (g_host_be)
837                  {                  {
838                          BSWAP16(pixel);                          while (out < end)
839                            {
840                                    pixel = *(data++);
841                                    BSWAP16(pixel);
842                                    SPLITCOLOUR16(pixel, pc);
843                                    value = MAKECOLOUR(pc);
844                                    BOUT24(out, value);
845                            }
846                  }                  }
847                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
848                  {                  {
849                          *(out++) = value >> 16;                          while (out < end)
850                          *(out++) = value >> 8;                          {
851                          *(out++) = value;                                  pixel = *(data++);
852                                    SPLITCOLOUR16(pixel, pc);
853                                    value = MAKECOLOUR(pc);
854                                    BOUT24(out, value);
855                            }
856                    }
857            }
858            else
859            {
860                    if (g_host_be)
861                    {
862                            while (out < end)
863                            {
864                                    pixel = *(data++);
865                                    BSWAP16(pixel);
866                                    SPLITCOLOUR16(pixel, pc);
867                                    value = MAKECOLOUR(pc);
868                                    LOUT24(out, value);
869                            }
870                  }                  }
871                  else                  else
872                  {                  {
873                          *(out++) = value;                          while (out < end)
874                          *(out++) = value >> 8;                          {
875                          *(out++) = value >> 16;                                  pixel = *(data++);
876                                    SPLITCOLOUR16(pixel, pc);
877                                    value = MAKECOLOUR(pc);
878                                    LOUT24(out, value);
879                            }
880                  }                  }
881          }          }
882  }  }
883    
884  static void  static void
885  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
886  {  {
887          uint16 pixel;          uint16 pixel;
888          uint32 value;          uint32 value;
889            PixelColour pc;
890    
891          while (out < end)          if (g_compatible_arch)
892            {
893                    /* *INDENT-OFF* */
894                    REPEAT4
895                    (
896                            pixel = *(data++);
897                            SPLITCOLOUR16(pixel, pc);
898                            *(out++) = pc.blue;
899                            *(out++) = pc.green;
900                            *(out++) = pc.red;
901                            *(out++) = 0;
902                    )
903                    /* *INDENT-ON* */
904            }
905            else if (g_xserver_be)
906          {          {
                 pixel = *(data++);  
   
907                  if (g_host_be)                  if (g_host_be)
908                  {                  {
909                          BSWAP16(pixel);                          while (out < end)
910                            {
911                                    pixel = *(data++);
912                                    BSWAP16(pixel);
913                                    SPLITCOLOUR16(pixel, pc);
914                                    value = MAKECOLOUR(pc);
915                                    BOUT32(out, value);
916                            }
917                  }                  }
918                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
919                  {                  {
920                          *(out++) = value >> 24;                          while (out < end)
921                          *(out++) = value >> 16;                          {
922                          *(out++) = value >> 8;                                  pixel = *(data++);
923                          *(out++) = value;                                  SPLITCOLOUR16(pixel, pc);
924                                    value = MAKECOLOUR(pc);
925                                    BOUT32(out, value);
926                            }
927                    }
928            }
929            else
930            {
931                    if (g_host_be)
932                    {
933                            while (out < end)
934                            {
935                                    pixel = *(data++);
936                                    BSWAP16(pixel);
937                                    SPLITCOLOUR16(pixel, pc);
938                                    value = MAKECOLOUR(pc);
939                                    LOUT32(out, value);
940                            }
941                  }                  }
942                  else                  else
943                  {                  {
944                          *(out++) = value;                          while (out < end)
945                          *(out++) = value >> 8;                          {
946                          *(out++) = value >> 16;                                  pixel = *(data++);
947                          *(out++) = value >> 24;                                  SPLITCOLOUR16(pixel, pc);
948                                    value = MAKECOLOUR(pc);
949                                    LOUT32(out, value);
950                            }
951                  }                  }
952          }          }
953  }  }
954    
955  static void  static void
956  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
957  {  {
958          uint32 pixel = 0;          uint32 pixel = 0;
959          uint16 value;          uint16 value;
960            PixelColour pc;
961    
962          while (out < end)          while (out < end)
963          {          {
964                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
965                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
966                  pixel |= *(data++);                  pixel |= *(data++);
967                    SPLITCOLOUR24(pixel, pc);
968                  value = (uint16) make_colour(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
969                  if (g_xserver_be)                  if (g_xserver_be)
970                  {                  {
971                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
972                  }                  }
973                  else                  else
974                  {                  {
975                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
976                  }                  }
977          }          }
978  }  }
979    
980  static void  static void
981  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
982  {  {
983          uint32 pixel;          uint32 pixel;
984          uint32 value;          uint32 value;
985            PixelColour pc;
986    
987          while (out < end)          if (g_xserver_be)
988          {          {
989                  pixel = *(data++) << 16;                  while (out < end)
                 pixel |= *(data++) << 8;  
                 pixel |= *(data++);  
   
                 value = make_colour(split_colour24(pixel));  
   
                 if (g_xserver_be)  
990                  {                  {
991                          *(out++) = value >> 16;                          pixel = *(data++) << 16;
992                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
993                          *(out++) = value;                          pixel |= *(data++);
994                            SPLITCOLOUR24(pixel, pc);
995                            value = MAKECOLOUR(pc);
996                            BOUT24(out, value);
997                  }                  }
998                  else          }
999            else
1000            {
1001                    while (out < end)
1002                  {                  {
1003                          *(out++) = value;                          pixel = *(data++) << 16;
1004                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
1005                          *(out++) = value >> 16;                          pixel |= *(data++);
1006                            SPLITCOLOUR24(pixel, pc);
1007                            value = MAKECOLOUR(pc);
1008                            LOUT24(out, value);
1009                  }                  }
1010          }          }
1011  }  }
1012    
1013  static void  static void
1014  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
1015  {  {
1016          uint32 pixel;          uint32 pixel;
1017          uint32 value;          uint32 value;
1018            PixelColour pc;
1019    
1020          while (out < end)          if (g_compatible_arch)
1021          {          {
1022                  pixel = *(data++) << 16;                  /* *INDENT-OFF* */
1023                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
1024                  pixel |= *(data++);                  REPEAT4
1025                    (
1026                  value = make_colour(split_colour24(pixel));                          *(out++) = *(data++);
1027                            *(out++) = *(data++);
1028                  if (g_xserver_be)                          *(out++) = *(data++);
1029                            *(out++) = 0;
1030                    )
1031    #else
1032                    REPEAT4
1033                    (
1034                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
1035                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
1036                     out += 4;
1037                     data += 3;
1038                    )
1039    #endif
1040                    /* *INDENT-ON* */
1041            }
1042            else if (g_xserver_be)
1043            {
1044                    while (out < end)
1045                  {                  {
1046                          *(out++) = value >> 24;                          pixel = *(data++) << 16;
1047                          *(out++) = value >> 16;                          pixel |= *(data++) << 8;
1048                          *(out++) = value >> 8;                          pixel |= *(data++);
1049                          *(out++) = value;                          SPLITCOLOUR24(pixel, pc);
1050                            value = MAKECOLOUR(pc);
1051                            BOUT32(out, value);
1052                  }                  }
1053                  else          }
1054            else
1055            {
1056                    while (out < end)
1057                  {                  {
1058                          *(out++) = value;                          pixel = *(data++) << 16;
1059                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
1060                          *(out++) = value >> 16;                          pixel |= *(data++);
1061                          *(out++) = value >> 24;                          SPLITCOLOUR24(pixel, pc);
1062                            value = MAKECOLOUR(pc);
1063                            LOUT32(out, value);
1064                  }                  }
1065          }          }
1066  }  }
# Line 647  translate_image(int width, int height, u Line 1072  translate_image(int width, int height, u
1072          uint8 *out;          uint8 *out;
1073          uint8 *end;          uint8 *end;
1074    
1075          /* if server and xserver bpp match, */          /*
1076          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
1077          /* just return data */             and arch(endian) matches, no need to translate:
1078          if (g_arch_match)             just return data.
1079               Note: select_visual should've already ensured g_no_translate
1080               is only set for compatible depths, but the RDP depth might've
1081               changed during connection negotiations.
1082             */
1083            if (g_no_translate_image)
1084          {          {
1085                  if (g_depth == 15 && g_server_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
1086                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
1087                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
1088                          return data;                          return data;
1089          }          }
1090    
# Line 662  translate_image(int width, int height, u Line 1092  translate_image(int width, int height, u
1092          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
1093          end = out + size;          end = out + size;
1094    
1095          switch (g_server_bpp)          switch (g_server_depth)
1096          {          {
1097                  case 24:                  case 24:
1098                          switch (g_bpp)                          switch (g_bpp)
# Line 760  calculate_shifts(uint32 mask, int *shift Line 1190  calculate_shifts(uint32 mask, int *shift
1190          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
1191  }  }
1192    
1193  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1194  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1195     */
1196    static unsigned
1197    calculate_mask_weight(uint32 mask)
1198    {
1199            unsigned weight = 0;
1200            do
1201            {
1202                    weight += (mask & 1);
1203            }
1204            while (mask >>= 1);
1205            return weight;
1206    }
1207    
1208    static BOOL
1209    select_visual()
1210  {  {
         XVisualInfo vi;  
1211          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1212          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1213          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1214          XVisualInfo template;          XVisualInfo template;
1215          Bool TrueColorVisual = False;          int i;
1216            unsigned red_weight, blue_weight, green_weight;
1217    
1218          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1219          if (g_display == NULL)  
1220            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1221            if (pfm == NULL)
1222          {          {
1223                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1224                    XCloseDisplay(g_display);
1225                  return False;                  return False;
1226          }          }
1227    
1228          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 */  
1229          template.class = TrueColor;          template.class = TrueColor;
1230          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1231            g_visual = NULL;
1232            g_no_translate_image = False;
1233            g_compatible_arch = False;
1234            if (vmatches != NULL)
1235            {
1236                    for (i = 0; i < visuals_count; ++i)
1237                    {
1238                            XVisualInfo *visual_info = &vmatches[i];
1239    
1240                            /* Try to find a no-translation visual that'll
1241                               allow us to use RDP bitmaps directly as ZPixmaps. */
1242                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1243                                                   /* R5G5B5 */
1244                                                   (visual_info->red_mask == 0x7c00) &&
1245                                                   (visual_info->green_mask == 0x3e0) &&
1246                                                   (visual_info->blue_mask == 0x1f)) ||
1247                                                  ((visual_info->depth == 16) &&
1248                                                   /* R5G6B5 */
1249                                                   (visual_info->red_mask == 0xf800) &&
1250                                                   (visual_info->green_mask == 0x7e0) &&
1251                                                   (visual_info->blue_mask == 0x1f)) ||
1252                                                  ((visual_info->depth == 24) &&
1253                                                   /* R8G8B8 */
1254                                                   (visual_info->red_mask == 0xff0000) &&
1255                                                   (visual_info->green_mask == 0xff00) &&
1256                                                   (visual_info->blue_mask == 0xff))))
1257                            {
1258                                    g_visual = visual_info->visual;
1259                                    g_depth = visual_info->depth;
1260                                    g_compatible_arch = !g_host_be;
1261                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1262                                    if (g_no_translate_image)
1263                                            /* We found the best visual */
1264                                            break;
1265                            }
1266                            else
1267                            {
1268                                    g_compatible_arch = False;
1269                            }
1270    
1271          nvisuals--;                          if (visual_info->depth > 24)
1272          while (nvisuals >= 0)                          {
1273          {                                  /* Avoid 32-bit visuals and likes like the plague.
1274                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1275                  {                                     (e.g. nvidia's Composite 32-bit visual).
1276                          g_depth = (vmatches + nvisuals)->depth;                                     Most implementation offer a 24-bit visual anyway. */
1277                                    continue;
1278                            }
1279    
1280                            /* Only care for visuals, for whose BPPs (not depths!)
1281                               we have a translateXtoY function. */
1282                            BOOL can_translate_to_bpp = False;
1283                            int j;
1284                            for (j = 0; j < pixmap_formats_count; ++j)
1285                            {
1286                                    if (pfm[j].depth == visual_info->depth)
1287                                    {
1288                                            if ((pfm[j].bits_per_pixel == 16) ||
1289                                                (pfm[j].bits_per_pixel == 24) ||
1290                                                (pfm[j].bits_per_pixel == 32))
1291                                            {
1292                                                    can_translate_to_bpp = True;
1293                                            }
1294                                            break;
1295                                    }
1296                            }
1297    
1298                            /* Prefer formats which have the most colour depth.
1299                               We're being truly aristocratic here, minding each
1300                               weight on its own. */
1301                            if (can_translate_to_bpp)
1302                            {
1303                                    unsigned vis_red_weight =
1304                                            calculate_mask_weight(visual_info->red_mask);
1305                                    unsigned vis_green_weight =
1306                                            calculate_mask_weight(visual_info->green_mask);
1307                                    unsigned vis_blue_weight =
1308                                            calculate_mask_weight(visual_info->blue_mask);
1309                                    if ((vis_red_weight >= red_weight)
1310                                        && (vis_green_weight >= green_weight)
1311                                        && (vis_blue_weight >= blue_weight))
1312                                    {
1313                                            red_weight = vis_red_weight;
1314                                            green_weight = vis_green_weight;
1315                                            blue_weight = vis_blue_weight;
1316                                            g_visual = visual_info->visual;
1317                                            g_depth = visual_info->depth;
1318                                    }
1319                            }
1320                  }                  }
1321                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1322          }          }
1323    
1324          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)))  
1325          {          {
1326                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1327                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1328                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1329                    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;  
                 }  
1330          }          }
1331          else          else
1332          {          {
1333                  /* need a truecolour visual */                  template.class = PseudoColor;
1334                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1335                  {                  template.colormap_size = 256;
1336                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1337                            XGetVisualInfo(g_display,
1338                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1339                                           &template, &visuals_count);
1340                    if (vmatches == NULL)
1341                    {
1342                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1343                            XCloseDisplay(g_display);
1344                            XFree(pfm);
1345                          return False;                          return False;
1346                  }                  }
1347    
1348                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1349                  g_owncolmap = False;                  g_owncolmap = True;
1350                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1351                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
                 calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);  
   
                 /* if RGB video and averything is little endian */  
                 if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask)  
                         if (!g_xserver_be && !g_host_be)  
                                 g_arch_match = True;  
1352          }          }
1353    
1354          pfm = XListPixmapFormats(g_display, &i);          g_bpp = 0;
1355          if (pfm != NULL)          for (i = 0; i < pixmap_formats_count; ++i)
1356          {          {
1357                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1358                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1359                  {                  {
1360                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1361    
1362                            if (g_no_translate_image)
1363                          {                          {
1364                                  g_bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1365                                    {
1366                                            case 15:
1367                                            case 16:
1368                                                    if (g_bpp != 16)
1369                                                            g_no_translate_image = False;
1370                                                    break;
1371                                            case 24:
1372                                                    /* Yes, this will force image translation
1373                                                       on most modern servers which use 32 bits
1374                                                       for R8G8B8. */
1375                                                    if (g_bpp != 24)
1376                                                            g_no_translate_image = False;
1377                                                    break;
1378                                            default:
1379                                                    g_no_translate_image = False;
1380                                                    break;
1381                                    }
1382                          }                          }
1383    
1384                            /* Pixmap formats list is a depth-to-bpp mapping --
1385                               there's just a single entry for every depth,
1386                               so we can safely break here */
1387                            break;
1388                  }                  }
                 XFree(pfm);  
1389          }          }
1390            XFree(pfm);
1391            pfm = NULL;
1392            return True;
1393    }
1394    
1395          if (g_bpp < 8)  BOOL
1396    ui_init(void)
1397    {
1398            int screen_num;
1399    
1400            g_display = XOpenDisplay(NULL);
1401            if (g_display == NULL)
1402          {          {
1403                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
                 XCloseDisplay(g_display);  
1404                  return False;                  return False;
1405          }          }
1406    
1407            {
1408                    uint16 endianess_test = 1;
1409                    g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1410            }
1411    
1412            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1413            screen_num = DefaultScreen(g_display);
1414            g_x_socket = ConnectionNumber(g_display);
1415            g_screen = ScreenOfDisplay(g_display, screen_num);
1416            g_depth = DefaultDepthOfScreen(g_screen);
1417    
1418            if (!select_visual())
1419                    return False;
1420    
1421            if (g_no_translate_image)
1422            {
1423                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1424            }
1425    
1426            if (g_server_depth > g_bpp)
1427            {
1428                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1429                            g_server_depth, g_bpp);
1430            }
1431    
1432            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1433                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1434    
1435          if (!g_owncolmap)          if (!g_owncolmap)
1436          {          {
1437                  g_xcolmap =                  g_xcolmap =
1438                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1439                                          AllocNone);                                          AllocNone);
1440                  if (g_depth <= 8)                  if (g_depth <= 8)
1441                          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);
1442          }          }
1443    
1444          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1445          {          {
1446                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1447                  g_ownbackstore = True;                  g_ownbackstore = True;
1448          }          }
1449    
# Line 879  ui_init(void) Line 1454  ui_init(void)
1454          {          {
1455                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1456                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1457                    g_using_full_workarea = True;
1458          }          }
1459          else if (g_width < 0)          else if (g_width < 0)
1460          {          {
1461                  /* Percent of screen */                  /* Percent of screen */
1462                    if (-g_width >= 100)
1463                            g_using_full_workarea = True;
1464                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1465                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1466          }          }
# Line 890  ui_init(void) Line 1468  ui_init(void)
1468          {          {
1469                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1470                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1471                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1472                  {                  {
1473                          g_width = cx;                          g_width = cx;
1474                          g_height = cy;                          g_height = cy;
1475                            g_using_full_workarea = True;
1476                  }                  }
1477                  else                  else
1478                  {                  {
1479                          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");
1480                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1481                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1482                  }                  }
1483          }          }
1484    
# Line 915  ui_init(void) Line 1493  ui_init(void)
1493                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1494    
1495          xclip_init();          xclip_init();
1496            ewmh_init();
1497            if (g_seamless_rdp)
1498                    seamless_init();
1499    
1500          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));
1501    
1502          return True;          return True;
1503  }  }
# Line 940  ui_deinit(void) Line 1521  ui_deinit(void)
1521          g_display = NULL;          g_display = NULL;
1522  }  }
1523    
1524    
1525    static void
1526    get_window_attribs(XSetWindowAttributes * attribs)
1527    {
1528            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1529            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1530            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1531            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1532            attribs->override_redirect = g_fullscreen;
1533            attribs->colormap = g_xcolmap;
1534    }
1535    
1536    static void
1537    get_input_mask(long *input_mask)
1538    {
1539            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1540                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1541    
1542            if (g_sendmotion)
1543                    *input_mask |= PointerMotionMask;
1544            if (g_ownbackstore)
1545                    *input_mask |= ExposureMask;
1546            if (g_fullscreen || g_grab_keyboard)
1547                    *input_mask |= EnterWindowMask;
1548            if (g_grab_keyboard)
1549                    *input_mask |= LeaveWindowMask;
1550    }
1551    
1552  BOOL  BOOL
1553  ui_create_window(void)  ui_create_window(void)
1554  {  {
1555          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
1556          uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };          uint8 null_pointer_data[24] = { 0x00 };
1557    
1558          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1559          XClassHint *classhints;          XClassHint *classhints;
1560          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 955  ui_create_window(void) Line 1565  ui_create_window(void)
1565          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1566          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1567    
1568          attribs.background_pixel = BlackPixelOfScreen(g_screen);          /* Handle -x-y portion of geometry string */
1569          attribs.border_pixel = WhitePixelOfScreen(g_screen);          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1570          attribs.backing_store = g_ownbackstore ? NotUseful : Always;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1571          attribs.override_redirect = g_fullscreen;          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1572          attribs.colormap = g_xcolmap;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1573    
1574          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,          get_window_attribs(&attribs);
1575                                0, g_depth, InputOutput, g_visual,  
1576                                CWBackPixel | CWBackingStore | CWOverrideRedirect |          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1577                                CWColormap | CWBorderPixel, &attribs);                                wndheight, 0, g_depth, InputOutput, g_visual,
1578                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1579                                  CWBorderPixel, &attribs);
1580    
1581          if (g_gc == NULL)          if (g_gc == NULL)
1582            {
1583                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1584                    ui_reset_clip();
1585            }
1586    
1587            if (g_create_bitmap_gc == NULL)
1588                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1589    
1590          if ((g_ownbackstore) && (g_backstore == 0))          if ((g_ownbackstore) && (g_backstore == 0))
1591          {          {
# Line 981  ui_create_window(void) Line 1599  ui_create_window(void)
1599          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1600    
1601          if (g_hide_decorations)          if (g_hide_decorations)
1602                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1603    
1604          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1605          if (classhints != NULL)          if (classhints != NULL)
# Line 995  ui_create_window(void) Line 1613  ui_create_window(void)
1613          if (sizehints)          if (sizehints)
1614          {          {
1615                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1616                    if (g_pos)
1617                            sizehints->flags |= PPosition;
1618                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1619                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1620                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
# Line 1006  ui_create_window(void) Line 1626  ui_create_window(void)
1626                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1627          }          }
1628    
1629          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;  
1630    
1631          if (g_IM != NULL)          if (g_IM != NULL)
1632          {          {
# Line 1029  ui_create_window(void) Line 1639  ui_create_window(void)
1639          }          }
1640    
1641          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
         XMapWindow(g_display, g_wnd);  
1642    
1643            XMapWindow(g_display, g_wnd);
1644          /* wait for VisibilityNotify */          /* wait for VisibilityNotify */
1645          do          do
1646          {          {
# Line 1101  xwin_toggle_fullscreen(void) Line 1711  xwin_toggle_fullscreen(void)
1711  {  {
1712          Pixmap contents = 0;          Pixmap contents = 0;
1713    
1714            if (g_seamless_active)
1715                    /* Turn off SeamlessRDP mode */
1716                    ui_seamless_toggle();
1717    
1718          if (!g_ownbackstore)          if (!g_ownbackstore)
1719          {          {
1720                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1121  xwin_toggle_fullscreen(void) Line 1735  xwin_toggle_fullscreen(void)
1735          }          }
1736  }  }
1737    
1738  /* Process all events in Xlib queue  static void
1739    handle_button_event(XEvent xevent, BOOL down)
1740    {
1741            uint16 button, flags = 0;
1742            g_last_gesturetime = xevent.xbutton.time;
1743            button = xkeymap_translate_button(xevent.xbutton.button);
1744            if (button == 0)
1745                    return;
1746    
1747            if (down)
1748                    flags = MOUSE_FLAG_DOWN;
1749    
1750            /* Stop moving window when button is released, regardless of cursor position */
1751            if (g_moving_wnd && (xevent.type == ButtonRelease))
1752                    g_moving_wnd = False;
1753    
1754            /* If win_button_size is nonzero, enable single app mode */
1755            if (xevent.xbutton.y < g_win_button_size)
1756            {
1757                    /*  Check from right to left: */
1758                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1759                    {
1760                            /* The close button, continue */
1761                            ;
1762                    }
1763                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1764                    {
1765                            /* The maximize/restore button. Do not send to
1766                               server.  It might be a good idea to change the
1767                               cursor or give some other visible indication
1768                               that rdesktop inhibited this click */
1769                            if (xevent.type == ButtonPress)
1770                                    return;
1771                    }
1772                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1773                    {
1774                            /* The minimize button. Iconify window. */
1775                            if (xevent.type == ButtonRelease)
1776                            {
1777                                    /* Release the mouse button outside the minimize button, to prevent the
1778                                       actual minimazation to happen */
1779                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1780                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1781                                    return;
1782                            }
1783                    }
1784                    else if (xevent.xbutton.x <= g_win_button_size)
1785                    {
1786                            /* The system menu. Ignore. */
1787                            if (xevent.type == ButtonPress)
1788                                    return;
1789                    }
1790                    else
1791                    {
1792                            /* The title bar. */
1793                            if (xevent.type == ButtonPress)
1794                            {
1795                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1796                                    {
1797                                            g_moving_wnd = True;
1798                                            g_move_x_offset = xevent.xbutton.x;
1799                                            g_move_y_offset = xevent.xbutton.y;
1800                                    }
1801                                    return;
1802                            }
1803                    }
1804            }
1805    
1806            if (xevent.xmotion.window == g_wnd)
1807            {
1808                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1809                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1810            }
1811            else
1812            {
1813                    /* SeamlessRDP */
1814                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1815                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1816            }
1817    }
1818    
1819    static void
1820    ui_seamless_handle_restack(seamless_window * sw)
1821    {
1822            Status status;
1823            Window root, parent, *children;
1824            unsigned int nchildren, i;
1825            seamless_window *sw_below;
1826    
1827            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
1828                                &root, &parent, &children, &nchildren);
1829            if (!status || !nchildren)
1830                    return;
1831    
1832            sw_below = NULL;
1833    
1834            i = 0;
1835            while (children[i] != sw->wnd)
1836            {
1837                    i++;
1838                    if (i >= nchildren)
1839                            return;
1840            }
1841    
1842            for (i++; i < nchildren; i++)
1843            {
1844                    sw_below = seamless_get_window_by_wnd(children[i]);
1845                    if (sw_below)
1846                            break;
1847            }
1848    
1849            if (!sw_below && !sw->behind)
1850                    return;
1851            if (sw_below && (sw_below->id == sw->behind))
1852                    return;
1853    
1854            if (sw_below)
1855            {
1856                    seamless_send_zchange(sw->id, sw_below->id, 0);
1857                    seamless_restack_window(sw, sw_below->id);
1858            }
1859            else
1860            {
1861                    seamless_send_zchange(sw->id, 0, 0);
1862                    seamless_restack_window(sw, 0);
1863            }
1864    }
1865    
1866    /* Process events in Xlib queue
1867     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1868  static int  static int
1869  xwin_process_events(void)  xwin_process_events(void)
1870  {  {
1871          XEvent xevent;          XEvent xevent;
1872          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1873          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1874          char str[256];          char str[256];
1875          Status status;          Status status;
1876            int events = 0;
1877            seamless_window *sw;
1878    
1879          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1880          {          {
1881                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1882    
# Line 1144  xwin_process_events(void) Line 1886  xwin_process_events(void)
1886                          continue;                          continue;
1887                  }                  }
1888    
                 flags = 0;  
   
1889                  switch (xevent.type)                  switch (xevent.type)
1890                  {                  {
1891                          case VisibilityNotify:                          case VisibilityNotify:
1892                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1893                                            g_Unobscured =
1894                                                    xevent.xvisibility.state == VisibilityUnobscured;
1895    
1896                                  break;                                  break;
1897                          case ClientMessage:                          case ClientMessage:
1898                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1182  xwin_process_events(void) Line 1925  xwin_process_events(void)
1925                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1926                                  }                                  }
1927    
1928                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1929                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1930    
1931                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1932                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1933                                          break;                                          break;
1934    
1935                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1936                                                             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);  
   
1937                                  break;                                  break;
1938    
1939                          case KeyRelease:                          case KeyRelease:
# Line 1207  xwin_process_events(void) Line 1941  xwin_process_events(void)
1941                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1942                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1943    
1944                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1945                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1946    
1947                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1948                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1949                                          break;                                          break;
1950    
1951                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1952                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1953                                  break;                                  break;
1954    
1955                          case ButtonPress:                          case ButtonPress:
1956                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1957                                  /* fall through */                                  break;
1958    
1959                          case ButtonRelease:                          case ButtonRelease:
1960                                  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);  
1961                                  break;                                  break;
1962    
1963                          case MotionNotify:                          case MotionNotify:
# Line 1300  xwin_process_events(void) Line 1972  xwin_process_events(void)
1972                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1973                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1974                                                         CurrentTime);                                                         CurrentTime);
1975                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1976                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1977                                    {
1978                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1979                                                           xevent.xmotion.x, xevent.xmotion.y);
1980                                    }
1981                                    else
1982                                    {
1983                                            /* SeamlessRDP */
1984                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1985                                                           xevent.xmotion.x_root,
1986                                                           xevent.xmotion.y_root);
1987                                    }
1988                                  break;                                  break;
1989    
1990                          case FocusIn:                          case FocusIn:
# Line 1312  xwin_process_events(void) Line 1995  xwin_process_events(void)
1995                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
1996                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
1997                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1998    
1999                                    sw = seamless_get_window_by_wnd(xevent.xfocus.window);
2000                                    if (!sw)
2001                                            break;
2002    
2003                                    if (sw->id != g_seamless_focused)
2004                                    {
2005                                            seamless_send_focus(sw->id, 0);
2006                                            g_seamless_focused = sw->id;
2007                                    }
2008                                  break;                                  break;
2009    
2010                          case FocusOut:                          case FocusOut:
# Line 1344  xwin_process_events(void) Line 2037  xwin_process_events(void)
2037                                  break;                                  break;
2038    
2039                          case Expose:                          case Expose:
2040                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2041                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2042                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2043                                            xevent.xexpose.height,                                                    g_gc,
2044                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2045                                                      xevent.xexpose.width, xevent.xexpose.height,
2046                                                      xevent.xexpose.x, xevent.xexpose.y);
2047                                    }
2048                                    else
2049                                    {
2050                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
2051                                            if (sw)
2052                                                    XCopyArea(g_display, g_backstore,
2053                                                              xevent.xexpose.window, g_gc,
2054                                                              xevent.xexpose.x + sw->xoffset,
2055                                                              xevent.xexpose.y + sw->yoffset,
2056                                                              xevent.xexpose.width,
2057                                                              xevent.xexpose.height, xevent.xexpose.x,
2058                                                              xevent.xexpose.y);
2059                                            else
2060                                            {
2061                                                    error("Expose for unknown window 0x%lx\n",
2062                                                          xevent.xexpose.window);
2063                                            }
2064                                    }
2065    
2066                                  break;                                  break;
2067    
2068                          case MappingNotify:                          case MappingNotify:
# Line 1377  xwin_process_events(void) Line 2091  xwin_process_events(void)
2091                                  break;                                  break;
2092                          case PropertyNotify:                          case PropertyNotify:
2093                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2094                                    if (xevent.xproperty.window == g_wnd)
2095                                            break;
2096                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2097                                            break;
2098    
2099                                    /* seamless */
2100                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
2101                                    if (!sw)
2102                                            break;
2103    
2104                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2105                                        && (xevent.xproperty.state == PropertyNewValue))
2106                                    {
2107                                            sw->state = ewmh_get_window_state(sw->wnd);
2108                                            seamless_send_state(sw->id, sw->state, 0);
2109                                    }
2110    
2111                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2112                                        && (xevent.xproperty.state == PropertyNewValue))
2113                                    {
2114                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2115                                            seamless_all_to_desktop(sw->wnd, sw->desktop);
2116                                    }
2117    
2118                                    break;
2119                            case MapNotify:
2120                                    if (!g_seamless_active)
2121                                            rdp_send_client_window_status(1);
2122                                    break;
2123                            case UnmapNotify:
2124                                    if (!g_seamless_active)
2125                                            rdp_send_client_window_status(0);
2126                                    break;
2127                            case ConfigureNotify:
2128                                    if (!g_seamless_active)
2129                                            break;
2130    
2131                                    sw = seamless_get_window_by_wnd(xevent.xconfigure.window);
2132                                    if (!sw)
2133                                    {
2134                                            error("ConfigureNotify for unknown window 0x%lx\n",
2135                                                  xevent.xconfigure.window);
2136                                    }
2137    
2138                                    gettimeofday(sw->position_timer, NULL);
2139                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2140                                        1000000)
2141                                    {
2142                                            sw->position_timer->tv_usec +=
2143                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2144                                            sw->position_timer->tv_sec += 1;
2145                                    }
2146                                    else
2147                                    {
2148                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2149                                    }
2150    
2151                                    ui_seamless_handle_restack(sw);
2152                                  break;                                  break;
2153                  }                  }
2154          }          }
# Line 1401  ui_select(int rdp_socket) Line 2173  ui_select(int rdp_socket)
2173                          /* User quit */                          /* User quit */
2174                          return 0;                          return 0;
2175    
2176                    if (g_seamless_active)
2177                            seamless_check_timers();
2178    
2179                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2180                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2181                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
# Line 1420  ui_select(int rdp_socket) Line 2195  ui_select(int rdp_socket)
2195    
2196                  /* add redirection handles */                  /* add redirection handles */
2197                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2198                    seamless_select_timeout(&tv);
2199    
2200                  n++;                  n++;
2201    
# Line 1429  ui_select(int rdp_socket) Line 2205  ui_select(int rdp_socket)
2205                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2206    
2207                          case 0:                          case 0:
2208                                  /* TODO: if tv.tv_sec just times out                                  /* Abort serial read calls */
2209                                   * we will segfault.                                  if (s_timeout)
2210                                   * FIXME:                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
                                  */  
                                 //s_timeout = True;  
                                 //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);  
2211                                  continue;                                  continue;
2212                  }                  }
2213    
# Line 1464  ui_create_bitmap(int width, int height, Line 2237  ui_create_bitmap(int width, int height,
2237          uint8 *tdata;          uint8 *tdata;
2238          int bitmap_pad;          int bitmap_pad;
2239    
2240          if (g_server_bpp == 8)          if (g_server_depth == 8)
2241          {          {
2242                  bitmap_pad = 8;                  bitmap_pad = 8;
2243          }          }
# Line 1481  ui_create_bitmap(int width, int height, Line 2254  ui_create_bitmap(int width, int height,
2254          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2255                               (char *) tdata, width, height, bitmap_pad, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
2256    
2257          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
2258    
2259          XFree(image);          XFree(image);
2260          if (tdata != data)          if (tdata != data)
# Line 1496  ui_paint_bitmap(int x, int y, int cx, in Line 2269  ui_paint_bitmap(int x, int y, int cx, in
2269          uint8 *tdata;          uint8 *tdata;
2270          int bitmap_pad;          int bitmap_pad;
2271    
2272          if (g_server_bpp == 8)          if (g_server_depth == 8)
2273          {          {
2274                  bitmap_pad = 8;                  bitmap_pad = 8;
2275          }          }
# Line 1516  ui_paint_bitmap(int x, int y, int cx, in Line 2289  ui_paint_bitmap(int x, int y, int cx, in
2289          {          {
2290                  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);
2291                  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);
2292                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2293                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2294                                             x - sw->xoffset, y - sw->yoffset));
2295          }          }
2296          else          else
2297          {          {
2298                  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);
2299                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2300                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2301                                             x - sw->xoffset, y - sw->yoffset));
2302          }          }
2303    
2304          XFree(image);          XFree(image);
# Line 1539  ui_create_glyph(int width, int height, u Line 2318  ui_create_glyph(int width, int height, u
2318          XImage *image;          XImage *image;
2319          Pixmap bitmap;          Pixmap bitmap;
2320          int scanline;          int scanline;
         GC gc;  
2321    
2322          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
2323    
2324          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
2325          gc = XCreateGC(g_display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
2326                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
2327    
2328          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
2329                               width, height, 8, scanline);                               width, height, 8, scanline);
# Line 1552  ui_create_glyph(int width, int height, u Line 2331  ui_create_glyph(int width, int height, u
2331          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
2332          XInitImage(image);          XInitImage(image);
2333    
2334          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
2335    
2336          XFree(image);          XFree(image);
         XFreeGC(g_display, gc);  
2337          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
2338  }  }
2339    
# Line 1641  ui_set_cursor(HCURSOR cursor) Line 2419  ui_set_cursor(HCURSOR cursor)
2419  {  {
2420          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2421          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2422            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2423  }  }
2424    
2425  void  void
# Line 1782  ui_set_colourmap(HCOLOURMAP map) Line 2561  ui_set_colourmap(HCOLOURMAP map)
2561                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2562          }          }
2563          else          else
2564            {
2565                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2566                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2567            }
2568  }  }
2569    
2570  void  void
2571  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2572  {  {
2573          XRectangle rect;          g_clip_rectangle.x = x;
2574            g_clip_rectangle.y = y;
2575          rect.x = x;          g_clip_rectangle.width = cx;
2576          rect.y = y;          g_clip_rectangle.height = cy;
2577          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);  
2578  }  }
2579    
2580  void  void
2581  ui_reset_clip(void)  ui_reset_clip(void)
2582  {  {
2583          XRectangle rect;          g_clip_rectangle.x = 0;
2584            g_clip_rectangle.y = 0;
2585          rect.x = 0;          g_clip_rectangle.width = g_width;
2586          rect.y = 0;          g_clip_rectangle.height = g_height;
2587          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);  
2588  }  }
2589    
2590  void  void
# Line 1887  ui_patblt(uint8 opcode, Line 2665  ui_patblt(uint8 opcode,
2665    
2666          if (g_ownbackstore)          if (g_ownbackstore)
2667                  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);
2668            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2669                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2670                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2671  }  }
2672    
2673  void  void
# Line 1897  ui_screenblt(uint8 opcode, Line 2678  ui_screenblt(uint8 opcode,
2678          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2679          if (g_ownbackstore)          if (g_ownbackstore)
2680          {          {
2681                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2682                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2683                          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);  
                 }  
2684          }          }
2685          else          else
2686          {          {
2687                  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);
2688          }          }
2689    
2690            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2691                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2692                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2693    
2694          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2695  }  }
2696    
# Line 1924  ui_memblt(uint8 opcode, Line 2701  ui_memblt(uint8 opcode,
2701  {  {
2702          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2703          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);
2704            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2705                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2706                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2707          if (g_ownbackstore)          if (g_ownbackstore)
2708                  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);
2709          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1970  ui_line(uint8 opcode, Line 2750  ui_line(uint8 opcode,
2750          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2751          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2752          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2753            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2754                                                startx - sw->xoffset, starty - sw->yoffset,
2755                                                endx - sw->xoffset, endy - sw->yoffset));
2756          if (g_ownbackstore)          if (g_ownbackstore)
2757                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2758          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1984  ui_rect( Line 2767  ui_rect(
2767          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2768  }  }
2769    
2770    void
2771    ui_polygon(uint8 opcode,
2772               /* mode */ uint8 fillmode,
2773               /* dest */ POINT * point, int npoints,
2774               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2775    {
2776            uint8 style, i, ipattern[8];
2777            Pixmap fill;
2778    
2779            SET_FUNCTION(opcode);
2780    
2781            switch (fillmode)
2782            {
2783                    case ALTERNATE:
2784                            XSetFillRule(g_display, g_gc, EvenOddRule);
2785                            break;
2786                    case WINDING:
2787                            XSetFillRule(g_display, g_gc, WindingRule);
2788                            break;
2789                    default:
2790                            unimpl("fill mode %d\n", fillmode);
2791            }
2792    
2793            if (brush)
2794                    style = brush->style;
2795            else
2796                    style = 0;
2797    
2798            switch (style)
2799            {
2800                    case 0: /* Solid */
2801                            SET_FOREGROUND(fgcolour);
2802                            FILL_POLYGON((XPoint *) point, npoints);
2803                            break;
2804    
2805                    case 2: /* Hatch */
2806                            fill = (Pixmap) ui_create_glyph(8, 8,
2807                                                            hatch_patterns + brush->pattern[0] * 8);
2808                            SET_FOREGROUND(fgcolour);
2809                            SET_BACKGROUND(bgcolour);
2810                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2811                            XSetStipple(g_display, g_gc, fill);
2812                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2813                            FILL_POLYGON((XPoint *) point, npoints);
2814                            XSetFillStyle(g_display, g_gc, FillSolid);
2815                            XSetTSOrigin(g_display, g_gc, 0, 0);
2816                            ui_destroy_glyph((HGLYPH) fill);
2817                            break;
2818    
2819                    case 3: /* Pattern */
2820                            for (i = 0; i != 8; i++)
2821                                    ipattern[7 - i] = brush->pattern[i];
2822                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2823                            SET_FOREGROUND(bgcolour);
2824                            SET_BACKGROUND(fgcolour);
2825                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2826                            XSetStipple(g_display, g_gc, fill);
2827                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2828                            FILL_POLYGON((XPoint *) point, npoints);
2829                            XSetFillStyle(g_display, g_gc, FillSolid);
2830                            XSetTSOrigin(g_display, g_gc, 0, 0);
2831                            ui_destroy_glyph((HGLYPH) fill);
2832                            break;
2833    
2834                    default:
2835                            unimpl("brush %d\n", brush->style);
2836            }
2837    
2838            RESET_FUNCTION(opcode);
2839    }
2840    
2841    void
2842    ui_polyline(uint8 opcode,
2843                /* dest */ POINT * points, int npoints,
2844                /* pen */ PEN * pen)
2845    {
2846            /* TODO: set join style */
2847            SET_FUNCTION(opcode);
2848            SET_FOREGROUND(pen->colour);
2849            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2850            if (g_ownbackstore)
2851                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2852                               CoordModePrevious);
2853    
2854            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2855                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2856    
2857            RESET_FUNCTION(opcode);
2858    }
2859    
2860    void
2861    ui_ellipse(uint8 opcode,
2862               /* mode */ uint8 fillmode,
2863               /* dest */ int x, int y, int cx, int cy,
2864               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2865    {
2866            uint8 style, i, ipattern[8];
2867            Pixmap fill;
2868    
2869            SET_FUNCTION(opcode);
2870    
2871            if (brush)
2872                    style = brush->style;
2873            else
2874                    style = 0;
2875    
2876            switch (style)
2877            {
2878                    case 0: /* Solid */
2879                            SET_FOREGROUND(fgcolour);
2880                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2881                            break;
2882    
2883                    case 2: /* Hatch */
2884                            fill = (Pixmap) ui_create_glyph(8, 8,
2885                                                            hatch_patterns + brush->pattern[0] * 8);
2886                            SET_FOREGROUND(fgcolour);
2887                            SET_BACKGROUND(bgcolour);
2888                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2889                            XSetStipple(g_display, g_gc, fill);
2890                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2891                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2892                            XSetFillStyle(g_display, g_gc, FillSolid);
2893                            XSetTSOrigin(g_display, g_gc, 0, 0);
2894                            ui_destroy_glyph((HGLYPH) fill);
2895                            break;
2896    
2897                    case 3: /* Pattern */
2898                            for (i = 0; i != 8; i++)
2899                                    ipattern[7 - i] = brush->pattern[i];
2900                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2901                            SET_FOREGROUND(bgcolour);
2902                            SET_BACKGROUND(fgcolour);
2903                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2904                            XSetStipple(g_display, g_gc, fill);
2905                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2906                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2907                            XSetFillStyle(g_display, g_gc, FillSolid);
2908                            XSetTSOrigin(g_display, g_gc, 0, 0);
2909                            ui_destroy_glyph((HGLYPH) fill);
2910                            break;
2911    
2912                    default:
2913                            unimpl("brush %d\n", brush->style);
2914            }
2915    
2916            RESET_FUNCTION(opcode);
2917    }
2918    
2919  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2920  void  void
2921  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 2039  ui_draw_glyph(int mixmode, Line 2971  ui_draw_glyph(int mixmode,
2971  }  }
2972    
2973  void  void
2974  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,
2975               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2976               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2977               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2978  {  {
2979            /* TODO: use brush appropriately */
2980    
2981          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2982          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
2983          DATABLOB *entry;          DATABLOB *entry;
# Line 2075  ui_draw_text(uint8 font, uint8 flags, in Line 3009  ui_draw_text(uint8 font, uint8 flags, in
3009                  switch (text[i])                  switch (text[i])
3010                  {                  {
3011                          case 0xff:                          case 0xff:
3012                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
3013                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
3014                                  {                                  {
3015                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
3016                                          exit(1);                                          for (j = 0; j < length; j++)
3017                                                    fprintf(stderr, "%02x ", text[j]);
3018                                            fprintf(stderr, "\n");
3019                                            i = length = 0;
3020                                            break;
3021                                  }                                  }
3022                                    cache_put_text(text[i + 1], text, text[i + 2]);
3023                                    i += 3;
3024                                    length -= i;
3025                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
3026                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
3027                                  i = 0;                                  i = 0;
3028                                  break;                                  break;
3029    
3030                          case 0xfe:                          case 0xfe:
3031                                    /* At least one byte needs to follow */
3032                                    if (i + 2 > length)
3033                                    {
3034                                            warning("Skipping short 0xfe command:");
3035                                            for (j = 0; j < length; j++)
3036                                                    fprintf(stderr, "%02x ", text[j]);
3037                                            fprintf(stderr, "\n");
3038                                            i = length = 0;
3039                                            break;
3040                                    }
3041                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
3042                                  if (entry != NULL)                                  if (entry->data != NULL)
3043                                  {                                  {
3044                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
3045                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
3046                                          {                                          {
3047                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
3048                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2125  ui_draw_text(uint8 font, uint8 flags, in Line 3074  ui_draw_text(uint8 font, uint8 flags, in
3074          if (g_ownbackstore)          if (g_ownbackstore)
3075          {          {
3076                  if (boxcx > 1)                  if (boxcx > 1)
3077                    {
3078                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3079                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3080                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3081                                                    (g_display, g_backstore, sw->wnd, g_gc,
3082                                                     boxx, boxy,
3083                                                     boxcx, boxcy,
3084                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3085                    }
3086                  else                  else
3087                    {
3088                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3089                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3090                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3091                                                    (g_display, g_backstore, sw->wnd, g_gc,
3092                                                     clipx, clipy,
3093                                                     clipcx, clipcy, clipx - sw->xoffset,
3094                                                     clipy - sw->yoffset));
3095                    }
3096          }          }
3097  }  }
3098    
# Line 2175  ui_desktop_restore(uint32 offset, int x, Line 3138  ui_desktop_restore(uint32 offset, int x,
3138          {          {
3139                  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);
3140                  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);
3141                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3142                                            (g_display, g_backstore, sw->wnd, g_gc,
3143                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3144          }          }
3145          else          else
3146          {          {
3147                  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);
3148                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3149                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3150                                             x - sw->xoffset, y - sw->yoffset));
3151          }          }
3152    
3153          XFree(image);          XFree(image);
3154  }  }
3155    
3156    /* these do nothing here but are used in uiports */
3157    void
3158    ui_begin_update(void)
3159    {
3160    }
3161    
3162    void
3163    ui_end_update(void)
3164    {
3165    }
3166    
3167    void
3168    ui_seamless_begin()
3169    {
3170            if (!g_seamless_rdp)
3171                    return;
3172    
3173            if (g_seamless_started)
3174                    return;
3175    
3176            g_seamless_started = True;
3177    
3178            ui_seamless_toggle();
3179    }
3180    
3181    void
3182    ui_seamless_toggle()
3183    {
3184            if (!g_seamless_rdp)
3185                    return;
3186    
3187            if (!g_seamless_started)
3188                    return;
3189    
3190            if (g_seamless_active)
3191            {
3192                    /* Deactivate */
3193                    while (g_seamless_windows)
3194                    {
3195                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3196                            seamless_remove_window(g_seamless_windows);
3197                    }
3198                    XMapWindow(g_display, g_wnd);
3199            }
3200            else
3201            {
3202                    /* Activate */
3203                    XUnmapWindow(g_display, g_wnd);
3204                    seamless_send_sync();
3205            }
3206    
3207            g_seamless_active = !g_seamless_active;
3208    }
3209    
3210    void
3211    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3212    {
3213            Window wnd;
3214            XSetWindowAttributes attribs;
3215            XClassHint *classhints;
3216            XSizeHints *sizehints;
3217            long input_mask;
3218            seamless_window *sw, *sw_parent;
3219    
3220            if (!g_seamless_active)
3221                    return;
3222    
3223            /* Ignore CREATEs for existing windows */
3224            sw = seamless_get_window_by_id(id);
3225            if (sw)
3226                    return;
3227    
3228            get_window_attribs(&attribs);
3229            attribs.override_redirect = False;
3230    
3231            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3232                                InputOutput, g_visual,
3233                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3234                                CWBorderPixel, &attribs);
3235    
3236            XStoreName(g_display, wnd, "SeamlessRDP");
3237            ewmh_set_wm_name(wnd, "SeamlessRDP");
3238    
3239            mwm_hide_decorations(wnd);
3240    
3241            classhints = XAllocClassHint();
3242            if (classhints != NULL)
3243            {
3244                    classhints->res_name = "rdesktop";
3245                    classhints->res_class = "SeamlessRDP";
3246                    XSetClassHint(g_display, wnd, classhints);
3247                    XFree(classhints);
3248            }
3249    
3250            /* WM_NORMAL_HINTS */
3251            sizehints = XAllocSizeHints();
3252            if (sizehints != NULL)
3253            {
3254                    sizehints->flags = USPosition;
3255                    XSetWMNormalHints(g_display, wnd, sizehints);
3256                    XFree(sizehints);
3257            }
3258    
3259            /* Set WM_TRANSIENT_FOR, if necessary */
3260            if ((parent != 0x00000000) && (parent != 0xFFFFFFFF))
3261            {
3262                    sw_parent = seamless_get_window_by_id(parent);
3263                    if (sw_parent)
3264                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3265                    else
3266                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3267            }
3268    
3269    
3270            /* FIXME: Support for Input Context:s */
3271    
3272            get_input_mask(&input_mask);
3273            input_mask |= PropertyChangeMask;
3274    
3275            XSelectInput(g_display, wnd, input_mask);
3276    
3277            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3278               seamless window, we could try to close the window on the
3279               serverside, instead of terminating rdesktop */
3280            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3281    
3282            sw = xmalloc(sizeof(seamless_window));
3283            sw->wnd = wnd;
3284            sw->id = id;
3285            sw->parent = parent;
3286            sw->behind = 0;
3287            sw->xoffset = 0;
3288            sw->yoffset = 0;
3289            sw->width = 0;
3290            sw->height = 0;
3291            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3292            sw->desktop = 0;
3293            sw->position_timer = xmalloc(sizeof(struct timeval));
3294            timerclear(sw->position_timer);
3295            sw->next = g_seamless_windows;
3296            g_seamless_windows = sw;
3297    }
3298    
3299    
3300    void
3301    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3302    {
3303            seamless_window *sw;
3304    
3305            if (!g_seamless_active)
3306                    return;
3307    
3308            sw = seamless_get_window_by_id(id);
3309            if (!sw)
3310            {
3311                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3312                    return;
3313            }
3314    
3315            XDestroyWindow(g_display, sw->wnd);
3316            seamless_remove_window(sw);
3317    }
3318    
3319    
3320    void
3321    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3322    {
3323            seamless_window *sw;
3324    
3325            if (!g_seamless_active)
3326                    return;
3327    
3328            sw = seamless_get_window_by_id(id);
3329            if (!sw)
3330            {
3331                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3332                    return;
3333            }
3334    
3335            if (!width || !height)
3336                    /* X11 windows must be at least 1x1 */
3337                    return;
3338    
3339            sw->xoffset = x;
3340            sw->yoffset = y;
3341            sw->width = width;
3342            sw->height = height;
3343    
3344            /* If we move the window in a maximized state, then KDE won't
3345               accept restoration */
3346            switch (sw->state)
3347            {
3348                    case SEAMLESSRDP_MINIMIZED:
3349                    case SEAMLESSRDP_MAXIMIZED:
3350                            return;
3351            }
3352    
3353            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3354            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3355    }
3356    
3357    void
3358    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3359    {
3360            seamless_window *sw;
3361    
3362            if (!g_seamless_active)
3363                    return;
3364    
3365            sw = seamless_get_window_by_id(id);
3366            if (!sw)
3367            {
3368                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3369                    return;
3370            }
3371    
3372            if (behind)
3373            {
3374                    seamless_window *sw_behind;
3375                    Window wnds[2];
3376    
3377                    sw_behind = seamless_get_window_by_id(behind);
3378                    if (!sw_behind)
3379                    {
3380                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3381                                    behind);
3382                            return;
3383                    }
3384    
3385                    wnds[1] = sw_behind->wnd;
3386                    wnds[0] = sw->wnd;
3387    
3388                    XRestackWindows(g_display, wnds, 2);
3389            }
3390            else
3391            {
3392                    XRaiseWindow(g_display, sw->wnd);
3393            }
3394    
3395            seamless_restack_window(sw, behind);
3396    }
3397    
3398    void
3399    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3400    {
3401            seamless_window *sw;
3402    
3403            if (!g_seamless_active)
3404                    return;
3405    
3406            sw = seamless_get_window_by_id(id);
3407            if (!sw)
3408            {
3409                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3410                    return;
3411            }
3412    
3413            /* FIXME: Might want to convert the name for non-EWMH WMs */
3414            XStoreName(g_display, sw->wnd, title);
3415            ewmh_set_wm_name(sw->wnd, title);
3416    }
3417    
3418    
3419    void
3420    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3421    {
3422            seamless_window *sw;
3423    
3424            if (!g_seamless_active)
3425                    return;
3426    
3427            sw = seamless_get_window_by_id(id);
3428            if (!sw)
3429            {
3430                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3431                    return;
3432            }
3433    
3434            switch (state)
3435            {
3436                    case SEAMLESSRDP_NORMAL:
3437                    case SEAMLESSRDP_MAXIMIZED:
3438                            ewmh_change_state(sw->wnd, state);
3439                            XMapWindow(g_display, sw->wnd);
3440                            break;
3441                    case SEAMLESSRDP_MINIMIZED:
3442                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3443                               the Window Manager should probably just ignore the request, since
3444                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3445                               such as minimization, rather than an independent state." Besides,
3446                               XIconifyWindow is easier. */
3447                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3448                            {
3449                                    XWMHints *hints;
3450                                    hints = XAllocWMHints();
3451                                    hints->flags = StateHint;
3452                                    hints->initial_state = IconicState;
3453                                    XSetWMHints(g_display, sw->wnd, hints);
3454                                    XFree(hints);
3455                                    XMapWindow(g_display, sw->wnd);
3456                            }
3457                            else
3458                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3459                            break;
3460                    default:
3461                            warning("SeamlessRDP: Invalid state %d\n", state);
3462                            break;
3463            }
3464    
3465            /* Handle popups without parents through some ewm hints */
3466            if ((sw->state == SEAMLESSRDP_NOTYETMAPPED) && (sw->parent == 0xFFFFFFFF))
3467                    ewmh_set_window_popup(sw->wnd);
3468    
3469            sw->state = state;
3470    }
3471    
3472    
3473    void
3474    ui_seamless_syncbegin(unsigned long flags)
3475    {
3476            if (!g_seamless_active)
3477                    return;
3478    
3479            /* Destroy all seamless windows */
3480            while (g_seamless_windows)
3481            {
3482                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3483                    seamless_remove_window(g_seamless_windows);
3484            }
3485    }

Legend:
Removed from v.709  
changed lines
  Added in v.1157

  ViewVC Help
Powered by ViewVC 1.1.26