/[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 487 by astrand, Mon Oct 13 12:34:15 2003 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1142 by ossman_, Thu Mar 16 08:11:29 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2002     Copyright (C) Matthew Chapman 1999-2005
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26  #include <errno.h>  #include <errno.h>
27    #include <strings.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29  #include "xproto.h"  #include "xproto.h"
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 40  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            XWMHints *hints;
58            int xoffset, yoffset;
59            int width, height;
60            int state;              /* normal/minimized/maximized. */
61            unsigned int desktop;
62            struct _seamless_window *next;
63    } seamless_window;
64    static seamless_window *g_seamless_windows = NULL;
65    extern BOOL g_seamless_rdp;
66    
67    extern uint32 g_embed_wnd;
68  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
69  static GC g_gc;  BOOL g_Unobscured;              /* used for screenblt */
70    static GC g_gc = NULL;
71    static GC g_create_bitmap_gc = NULL;
72    static GC g_create_glyph_gc = NULL;
73    static XRectangle g_clip_rectangle;
74  static Visual *g_visual;  static Visual *g_visual;
75    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
76       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
77       as far as we're concerned. */
78  static int g_depth;  static int g_depth;
79    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
80       This may be larger than g_depth, in which case some of the bits would
81       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
82  static int g_bpp;  static int g_bpp;
83  static XIM g_IM;  static XIM g_IM;
84  static XIC g_IC;  static XIC g_IC;
85  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
86  static Cursor g_current_cursor;  static Cursor g_current_cursor;
87    static HCURSOR g_null_cursor = NULL;
88  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
89    extern Atom g_net_wm_state_atom;
90    extern Atom g_net_wm_desktop_atom;
91  static BOOL g_focused;  static BOOL g_focused;
92  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
93    /* Indicates that:
94       1) visual has 15, 16 or 24 depth and the same color channel masks
95          as its RDP equivalent (implies X server is LE),
96       2) host is LE
97       This will trigger an optimization whose real value is questionable.
98    */
99    static BOOL g_compatible_arch;
100    /* Indicates whether RDP's bitmaps and our XImages have the same
101       binary format. If so, we can avoid an expensive translation.
102       Note that this can be true when g_compatible_arch is false,
103       e.g.:
104      
105         RDP(LE) <-> host(BE) <-> X-Server(LE)
106        
107       ('host' is the machine running rdesktop; the host simply memcpy's
108        so its endianess doesn't matter)
109     */
110    static BOOL g_no_translate_image = False;
111    
112  /* endianness */  /* endianness */
113  static BOOL g_host_be;  static BOOL g_host_be;
114  static BOOL g_xserver_be;  static BOOL g_xserver_be;
115    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
116    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
117    
118  /* software backing store */  /* software backing store */
119  static BOOL g_ownbackstore;  extern BOOL g_ownbackstore;
120  static Pixmap g_backstore;  static Pixmap g_backstore = 0;
121    
122  /* Moving in single app mode */  /* Moving in single app mode */
123  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
124  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
125  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
126    static BOOL g_using_full_workarea = False;
127    
128  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
129  extern int g_dsp_fd;  extern int g_dsp_fd;
130  extern BOOL g_dsp_busy;  extern BOOL g_dsp_busy;
131    extern BOOL g_rdpsnd;
132  #endif  #endif
133    
134  /* MWM decorations */  /* MWM decorations */
# Line 76  extern BOOL g_dsp_busy; Line 136  extern BOOL g_dsp_busy;
136  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
137  typedef struct  typedef struct
138  {  {
139          uint32 flags;          unsigned long flags;
140          uint32 functions;          unsigned long functions;
141          uint32 decorations;          unsigned long decorations;
142          sint32 inputMode;          long inputMode;
143          uint32 status;          unsigned long status;
144  }  }
145  PropMotifWmHints;  PropMotifWmHints;
146    
# Line 92  typedef struct Line 152  typedef struct
152  }  }
153  PixelColour;  PixelColour;
154    
155    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
156            do { \
157                    seamless_window *sw; \
158                    XRectangle rect; \
159                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
160                        rect.x = g_clip_rectangle.x - sw->xoffset; \
161                        rect.y = g_clip_rectangle.y - sw->yoffset; \
162                        rect.width = g_clip_rectangle.width; \
163                        rect.height = g_clip_rectangle.height; \
164                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
165                        func args; \
166                    } \
167                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
168            } while (0)
169    
170    static void
171    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
172    {
173            points[0].x -= xoffset;
174            points[0].y -= yoffset;
175            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
176            points[0].x += xoffset;
177            points[0].y += yoffset;
178    }
179    
180    static void
181    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
182    {
183            points[0].x -= xoffset;
184            points[0].y -= yoffset;
185            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
186            points[0].x += xoffset;
187            points[0].y += yoffset;
188    }
189    
190  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
191  { \  { \
192          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
193            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
194          if (g_ownbackstore) \          if (g_ownbackstore) \
195                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
196  }  }
# Line 105  PixelColour; Line 200  PixelColour;
200          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); \
201  }  }
202    
203    #define FILL_POLYGON(p,np)\
204    { \
205            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
206            if (g_ownbackstore) \
207                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
208            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
209    }
210    
211    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
212    { \
213            switch (m) \
214            { \
215                    case 0: /* Outline */ \
216                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
217                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
218                            if (g_ownbackstore) \
219                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
220                            break; \
221                    case 1: /* Filled */ \
222                            XFillArc(g_display, g_wnd, g_gc, x, y, \
223                                     cx, cy, 0, 360*64); \
224                            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)); \
225                            if (g_ownbackstore) \
226                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
227                            break; \
228            } \
229    }
230    
231  /* colour maps */  /* colour maps */
232  BOOL g_owncolmap = False;  extern BOOL g_owncolmap;
233  static Colormap g_xcolmap;  static Colormap g_xcolmap;
234  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
235    
236  #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : translate_colour(g_colmap[col]) )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
237  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
238  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
239    
# Line 136  static int rop2_map[] = { Line 259  static int rop2_map[] = {
259  #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]); }
260  #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); }
261    
262    static seamless_window *
263    seamless_get_window_by_id(unsigned long id)
264    {
265            seamless_window *sw;
266            for (sw = g_seamless_windows; sw; sw = sw->next)
267            {
268                    if (sw->id == id)
269                            return sw;
270            }
271            return NULL;
272    }
273    
274    
275    static seamless_window *
276    seamless_get_window_by_wnd(Window wnd)
277    {
278            seamless_window *sw;
279            for (sw = g_seamless_windows; sw; sw = sw->next)
280            {
281                    if (sw->wnd == wnd)
282                            return sw;
283            }
284            return NULL;
285    }
286    
287    
288    static void
289    seamless_remove_window(seamless_window * win)
290    {
291            seamless_window *sw, **prevnext = &g_seamless_windows;
292            for (sw = g_seamless_windows; sw; sw = sw->next)
293            {
294                    if (sw == win)
295                    {
296                            *prevnext = sw->next;
297                            XFree(sw->hints);
298                            xfree(sw);
299                            return;
300                    }
301                    prevnext = &sw->next;
302            }
303            return;
304    }
305    
306    
307    /* Move all windows except wnd to new desktop */
308    static void
309    seamless_all_to_desktop(Window wnd, unsigned int desktop)
310    {
311            seamless_window *sw;
312            for (sw = g_seamless_windows; sw; sw = sw->next)
313            {
314                    if (sw->wnd == wnd)
315                            continue;
316                    if (sw->desktop != desktop)
317                    {
318                            ewmh_move_to_desktop(sw->wnd, desktop);
319                            sw->desktop = desktop;
320                    }
321            }
322    }
323    
324    
325  static void  static void
326  mwm_hide_decorations(void)  mwm_hide_decorations(Window wnd)
327  {  {
328          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
329          Atom hintsatom;          Atom hintsatom;
# Line 154  mwm_hide_decorations(void) Line 340  mwm_hide_decorations(void)
340                  return;                  return;
341          }          }
342    
343          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
344                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
 }  
345    
 static PixelColour  
 split_colour15(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = (colour & 0x7c00) >> 10;  
         rv.red = (rv.red * 0xff) / 0x1f;  
         rv.green = (colour & 0x03e0) >> 5;  
         rv.green = (rv.green * 0xff) / 0x1f;  
         rv.blue = (colour & 0x1f);  
         rv.blue = (rv.blue * 0xff) / 0x1f;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = (colour & 0xf800) >> 11;  
         rv.red = (rv.red * 0xff) / 0x1f;  
         rv.green = (colour & 0x07e0) >> 5;  
         rv.green = (rv.green * 0xff) / 0x3f;  
         rv.blue = (colour & 0x001f);  
         rv.blue = (rv.blue * 0xff) / 0x1f;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour24(uint32 colour)  
 {  
         PixelColour rv;  
         rv.blue = (colour & 0xff0000) >> 16;  
         rv.green = (colour & 0xff00) >> 8;  
         rv.red = (colour & 0xff);  
         return rv;  
346  }  }
347    
348  static uint32  #define SPLITCOLOUR15(colour, rv) \
349  make_colour16(PixelColour pc)  { \
350  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
351          pc.red = (pc.red * 0x1f) / 0xff;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
352          pc.green = (pc.green * 0x3f) / 0xff;          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
         pc.blue = (pc.blue * 0x1f) / 0xff;  
         return (pc.red << 11) | (pc.green << 5) | pc.blue;  
353  }  }
354    
355  static uint32  #define SPLITCOLOUR16(colour, rv) \
356  make_colour24(PixelColour pc)  { \
357  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
358          if (g_xserver_be)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
359          {          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
360                  return pc.red | (pc.green << 8) | (pc.blue << 16);  } \
         }  
         else  
         {  
                 return (pc.red << 16) | (pc.green << 8) | pc.blue;  
         }  
 }  
361    
362  static uint32  #define SPLITCOLOUR24(colour, rv) \
363  make_colour32(PixelColour pc)  { \
364  {          rv.blue = (colour & 0xff0000) >> 16; \
365          if (g_xserver_be)          rv.green = (colour & 0x00ff00) >> 8; \
366          {          rv.red = (colour & 0x0000ff); \
                 return pc.red | (pc.green << 8) | (pc.blue << 16);  
         }  
         else  
         {  
                 return (pc.red << 16) | (pc.green << 8) | pc.blue;  
         }  
367  }  }
368    
369    #define MAKECOLOUR(pc) \
370            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
371                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
372                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
373    
374  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
375  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
376  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
377                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
378    
379    /* The following macros output the same octet sequences
380       on both BE and LE hosts: */
381    
382    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
383    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
384    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
385    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
386    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
387    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
388    
389  static uint32  static uint32
390  translate_colour(uint32 colour)  translate_colour(uint32 colour)
391  {  {
392          switch (g_server_bpp)          PixelColour pc;
393            switch (g_server_depth)
394          {          {
395                  case 15:                  case 15:
396                          switch (g_bpp)                          SPLITCOLOUR15(colour, pc);
                         {  
                                 case 16:  
                                         colour = make_colour16(split_colour15(colour));  
                                         break;  
                                 case 24:  
                                         colour = make_colour24(split_colour15(colour));  
                                         break;  
                                 case 32:  
                                         colour = make_colour32(split_colour15(colour));  
                                         break;  
                         }  
397                          break;                          break;
398                  case 16:                  case 16:
399                          switch (g_bpp)                          SPLITCOLOUR16(colour, pc);
                         {  
                                 case 16:  
                                         break;  
                                 case 24:  
                                         colour = make_colour24(split_colour16(colour));  
                                         break;  
                                 case 32:  
                                         colour = make_colour32(split_colour16(colour));  
                                         break;  
                         }  
400                          break;                          break;
401                  case 24:                  case 24:
402                          switch (g_bpp)                          SPLITCOLOUR24(colour, pc);
403                          {                          break;
404                                  case 16:                  default:
405                                          colour = make_colour16(split_colour24(colour));                          /* Avoid warning */
406                                          break;                          pc.red = 0;
407                                  case 24:                          pc.green = 0;
408                                          break;                          pc.blue = 0;
                                 case 32:  
                                         colour = make_colour32(split_colour24(colour));  
                                         break;  
                         }  
409                          break;                          break;
410          }          }
411          return colour;          return MAKECOLOUR(pc);
412  }  }
413    
414    /* indent is confused by UNROLL8 */
415    /* *INDENT-OFF* */
416    
417    /* repeat and unroll, similar to bitmap.c */
418    /* potentialy any of the following translate */
419    /* functions can use repeat but just doing */
420    /* the most common ones */
421    
422    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
423    /* 2 byte output repeat */
424    #define REPEAT2(stm) \
425    { \
426            while (out <= end - 8 * 2) \
427                    UNROLL8(stm) \
428            while (out < end) \
429                    { stm } \
430    }
431    /* 3 byte output repeat */
432    #define REPEAT3(stm) \
433    { \
434            while (out <= end - 8 * 3) \
435                    UNROLL8(stm) \
436            while (out < end) \
437                    { stm } \
438    }
439    /* 4 byte output repeat */
440    #define REPEAT4(stm) \
441    { \
442            while (out <= end - 8 * 4) \
443                    UNROLL8(stm) \
444            while (out < end) \
445                    { stm } \
446    }
447    /* *INDENT-ON* */
448    
449  static void  static void
450  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
451  {  {
452          while (out < end)          while (out < end)
453                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
454  }  }
455    
456  static void  static void
457  translate8to16(uint8 * data, uint16 * out, uint16 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
458  {  {
459          while (out < end)          uint16 value;
460                  *(out++) = (uint16) g_colmap[*(data++)];  
461            if (g_compatible_arch)
462            {
463                    /* *INDENT-OFF* */
464                    REPEAT2
465                    (
466                            *((uint16 *) out) = g_colmap[*(data++)];
467                            out += 2;
468                    )
469                    /* *INDENT-ON* */
470            }
471            else if (g_xserver_be)
472            {
473                    while (out < end)
474                    {
475                            value = (uint16) g_colmap[*(data++)];
476                            BOUT16(out, value);
477                    }
478            }
479            else
480            {
481                    while (out < end)
482                    {
483                            value = (uint16) g_colmap[*(data++)];
484                            LOUT16(out, value);
485                    }
486            }
487  }  }
488    
489  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
490  static void  static void
491  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
492  {  {
493          uint32 value;          uint32 value;
494    
495          while (out < end)          if (g_compatible_arch)
496            {
497                    while (out < end)
498                    {
499                            value = g_colmap[*(data++)];
500                            BOUT24(out, value);
501                    }
502            }
503            else
504          {          {
505                  value = g_colmap[*(data++)];                  while (out < end)
506                  *(out++) = value;                  {
507                  *(out++) = value >> 8;                          value = g_colmap[*(data++)];
508                  *(out++) = value >> 16;                          LOUT24(out, value);
509                    }
510          }          }
511  }  }
512    
513  static void  static void
514  translate8to32(uint8 * data, uint32 * out, uint32 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
515  {  {
516          while (out < end)          uint32 value;
                 *(out++) = g_colmap[*(data++)];  
 }  
517    
518  /* todo the remaining translate function might need some big endian check ?? */          if (g_compatible_arch)
519            {
520                    /* *INDENT-OFF* */
521                    REPEAT4
522                    (
523                            *((uint32 *) out) = g_colmap[*(data++)];
524                            out += 4;
525                    )
526                    /* *INDENT-ON* */
527            }
528            else if (g_xserver_be)
529            {
530                    while (out < end)
531                    {
532                            value = g_colmap[*(data++)];
533                            BOUT32(out, value);
534                    }
535            }
536            else
537            {
538                    while (out < end)
539                    {
540                            value = g_colmap[*(data++)];
541                            LOUT32(out, value);
542                    }
543            }
544    }
545    
546  static void  static void
547  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
548  {  {
549          uint16 pixel;          uint16 pixel;
550          uint16 value;          uint16 value;
551            PixelColour pc;
552    
553          while (out < end)          if (g_xserver_be)
554          {          {
555                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel)  
                 }  
   
                 value = make_colour16(split_colour15(pixel));  
   
                 if (g_xserver_be)  
556                  {                  {
557                          *(out++) = value >> 8;                          pixel = *(data++);
558                          *(out++) = value;                          if (g_host_be)
559                            {
560                                    BSWAP16(pixel);
561                            }
562                            SPLITCOLOUR15(pixel, pc);
563                            value = MAKECOLOUR(pc);
564                            BOUT16(out, value);
565                  }                  }
566                  else          }
567            else
568            {
569                    while (out < end)
570                  {                  {
571                          *(out++) = value;                          pixel = *(data++);
572                          *(out++) = value >> 8;                          if (g_host_be)
573                            {
574                                    BSWAP16(pixel);
575                            }
576                            SPLITCOLOUR15(pixel, pc);
577                            value = MAKECOLOUR(pc);
578                            LOUT16(out, value);
579                  }                  }
580          }          }
581  }  }
582    
583  static void  static void
584  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
585  {  {
586          uint32 value;          uint32 value;
587          uint16 pixel;          uint16 pixel;
588            PixelColour pc;
589    
590          while (out < end)          if (g_compatible_arch)
591          {          {
592                  pixel = *(data++);                  /* *INDENT-OFF* */
593                    REPEAT3
594                  if (g_host_be)                  (
595                  {                          pixel = *(data++);
596                          BSWAP16(pixel)                          SPLITCOLOUR15(pixel, pc);
597                  }                          *(out++) = pc.blue;
598                            *(out++) = pc.green;
599                  value = make_colour24(split_colour15(pixel));                          *(out++) = pc.red;
600                  if (g_xserver_be)                  )
601                    /* *INDENT-ON* */
602            }
603            else if (g_xserver_be)
604            {
605                    while (out < end)
606                  {                  {
607                          *(out++) = value >> 16;                          pixel = *(data++);
608                          *(out++) = value >> 8;                          if (g_host_be)
609                          *(out++) = value;                          {
610                                    BSWAP16(pixel);
611                            }
612                            SPLITCOLOUR15(pixel, pc);
613                            value = MAKECOLOUR(pc);
614                            BOUT24(out, value);
615                  }                  }
616                  else          }
617            else
618            {
619                    while (out < end)
620                  {                  {
621                          *(out++) = value;                          pixel = *(data++);
622                          *(out++) = value >> 8;                          if (g_host_be)
623                          *(out++) = value >> 16;                          {
624                                    BSWAP16(pixel);
625                            }
626                            SPLITCOLOUR15(pixel, pc);
627                            value = MAKECOLOUR(pc);
628                            LOUT24(out, value);
629                  }                  }
630          }          }
631  }  }
632    
633  static void  static void
634  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
635  {  {
636          uint16 pixel;          uint16 pixel;
637          uint32 value;          uint32 value;
638            PixelColour pc;
639    
640          while (out < end)          if (g_compatible_arch)
641          {          {
642                  pixel = *(data++);                  /* *INDENT-OFF* */
643                    REPEAT4
644                  if (g_host_be)                  (
645                  {                          pixel = *(data++);
646                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
647                  }                          *(out++) = pc.blue;
648                            *(out++) = pc.green;
649                  value = make_colour32(split_colour15(pixel));                          *(out++) = pc.red;
650                            *(out++) = 0;
651                  if (g_xserver_be)                  )
652                    /* *INDENT-ON* */
653            }
654            else if (g_xserver_be)
655            {
656                    while (out < end)
657                  {                  {
658                          *(out++) = value >> 24;                          pixel = *(data++);
659                          *(out++) = value >> 16;                          if (g_host_be)
660                          *(out++) = value >> 8;                          {
661                          *(out++) = value;                                  BSWAP16(pixel);
662                            }
663                            SPLITCOLOUR15(pixel, pc);
664                            value = MAKECOLOUR(pc);
665                            BOUT32(out, value);
666                  }                  }
667                  else          }
668            else
669            {
670                    while (out < end)
671                  {                  {
672                          *(out++) = value;                          pixel = *(data++);
673                          *(out++) = value >> 8;                          if (g_host_be)
674                          *(out++) = value >> 16;                          {
675                          *(out++) = value >> 24;                                  BSWAP16(pixel);
676                            }
677                            SPLITCOLOUR15(pixel, pc);
678                            value = MAKECOLOUR(pc);
679                            LOUT32(out, value);
680                  }                  }
681          }          }
682  }  }
683    
684  static void  static void
685  translate16to16(uint16 * data, uint16 * out, uint16 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
686  {  {
687            uint16 pixel;
688          uint16 value;          uint16 value;
689            PixelColour pc;
690    
691          if (g_xserver_be)          if (g_xserver_be)
692          {          {
693                  while (out < end)                  if (g_host_be)
694                  {                  {
695                          value = *data;                          while (out < end)
696                          BSWAP16(value);                          {
697                          *out = value;                                  pixel = *(data++);
698                          data++;                                  BSWAP16(pixel);
699                          out++;                                  SPLITCOLOUR16(pixel, pc);
700                                    value = MAKECOLOUR(pc);
701                                    BOUT16(out, value);
702                            }
703                    }
704                    else
705                    {
706                            while (out < end)
707                            {
708                                    pixel = *(data++);
709                                    SPLITCOLOUR16(pixel, pc);
710                                    value = MAKECOLOUR(pc);
711                                    BOUT16(out, value);
712                            }
713                  }                  }
   
714          }          }
715          else          else
716          {          {
717                  while (out < end)                  if (g_host_be)
718                    {
719                            while (out < end)
720                            {
721                                    pixel = *(data++);
722                                    BSWAP16(pixel);
723                                    SPLITCOLOUR16(pixel, pc);
724                                    value = MAKECOLOUR(pc);
725                                    LOUT16(out, value);
726                            }
727                    }
728                    else
729                  {                  {
730                          *out = *data;                          while (out < end)
731                          out++;                          {
732                          data++;                                  pixel = *(data++);
733                                    SPLITCOLOUR16(pixel, pc);
734                                    value = MAKECOLOUR(pc);
735                                    LOUT16(out, value);
736                            }
737                  }                  }
738          }          }
739  }  }
740    
   
741  static void  static void
742  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
743  {  {
744          uint32 value;          uint32 value;
745          uint16 pixel;          uint16 pixel;
746            PixelColour pc;
747    
748          while (out < end)          if (g_compatible_arch)
749            {
750                    /* *INDENT-OFF* */
751                    REPEAT3
752                    (
753                            pixel = *(data++);
754                            SPLITCOLOUR16(pixel, pc);
755                            *(out++) = pc.blue;
756                            *(out++) = pc.green;
757                            *(out++) = pc.red;
758                    )
759                    /* *INDENT-ON* */
760            }
761            else if (g_xserver_be)
762          {          {
                 pixel = *(data++);  
   
763                  if (g_host_be)                  if (g_host_be)
764                  {                  {
765                          BSWAP16(pixel)                          while (out < end)
766                            {
767                                    pixel = *(data++);
768                                    BSWAP16(pixel);
769                                    SPLITCOLOUR16(pixel, pc);
770                                    value = MAKECOLOUR(pc);
771                                    BOUT24(out, value);
772                            }
773                  }                  }
774                    else
775                  value = make_colour24(split_colour16(pixel));                  {
776                            while (out < end)
777                  if (g_xserver_be)                          {
778                                    pixel = *(data++);
779                                    SPLITCOLOUR16(pixel, pc);
780                                    value = MAKECOLOUR(pc);
781                                    BOUT24(out, value);
782                            }
783                    }
784            }
785            else
786            {
787                    if (g_host_be)
788                  {                  {
789                          *(out++) = value >> 16;                          while (out < end)
790                          *(out++) = value >> 8;                          {
791                          *(out++) = value;                                  pixel = *(data++);
792                                    BSWAP16(pixel);
793                                    SPLITCOLOUR16(pixel, pc);
794                                    value = MAKECOLOUR(pc);
795                                    LOUT24(out, value);
796                            }
797                  }                  }
798                  else                  else
799                  {                  {
800                          *(out++) = value;                          while (out < end)
801                          *(out++) = value >> 8;                          {
802                          *(out++) = value >> 16;                                  pixel = *(data++);
803                                    SPLITCOLOUR16(pixel, pc);
804                                    value = MAKECOLOUR(pc);
805                                    LOUT24(out, value);
806                            }
807                  }                  }
808          }          }
809  }  }
810    
811  static void  static void
812  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
813  {  {
814          uint16 pixel;          uint16 pixel;
815          uint32 value;          uint32 value;
816            PixelColour pc;
817    
818          while (out < end)          if (g_compatible_arch)
819            {
820                    /* *INDENT-OFF* */
821                    REPEAT4
822                    (
823                            pixel = *(data++);
824                            SPLITCOLOUR16(pixel, pc);
825                            *(out++) = pc.blue;
826                            *(out++) = pc.green;
827                            *(out++) = pc.red;
828                            *(out++) = 0;
829                    )
830                    /* *INDENT-ON* */
831            }
832            else if (g_xserver_be)
833          {          {
                 pixel = *(data++);  
   
834                  if (g_host_be)                  if (g_host_be)
835                  {                  {
836                          BSWAP16(pixel)                          while (out < end)
837                            {
838                                    pixel = *(data++);
839                                    BSWAP16(pixel);
840                                    SPLITCOLOUR16(pixel, pc);
841                                    value = MAKECOLOUR(pc);
842                                    BOUT32(out, value);
843                            }
844                    }
845                    else
846                    {
847                            while (out < end)
848                            {
849                                    pixel = *(data++);
850                                    SPLITCOLOUR16(pixel, pc);
851                                    value = MAKECOLOUR(pc);
852                                    BOUT32(out, value);
853                            }
854                  }                  }
855            }
856                  value = make_colour32(split_colour16(pixel));          else
857            {
858                  if (g_xserver_be)                  if (g_host_be)
859                    {
860                            while (out < end)
861                            {
862                                    pixel = *(data++);
863                                    BSWAP16(pixel);
864                                    SPLITCOLOUR16(pixel, pc);
865                                    value = MAKECOLOUR(pc);
866                                    LOUT32(out, value);
867                            }
868                    }
869                    else
870                  {                  {
871                          *(out++) = value >> 24;                          while (out < end)
872                          *(out++) = value >> 16;                          {
873                          *(out++) = value >> 8;                                  pixel = *(data++);
874                          *(out++) = value;                                  SPLITCOLOUR16(pixel, pc);
875                  }                                  value = MAKECOLOUR(pc);
876                  else                                  LOUT32(out, value);
877                  {                          }
878                          *(out++) = value;                  }
879                          *(out++) = value >> 8;          }
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
                 }  
         }  
880  }  }
881    
882  static void  static void
883  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
884  {  {
885          uint32 pixel = 0;          uint32 pixel = 0;
886          uint16 value;          uint16 value;
887            PixelColour pc;
888    
889          while (out < end)          while (out < end)
890          {          {
891                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
892                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
893                  pixel |= *(data++);                  pixel |= *(data++);
894                    SPLITCOLOUR24(pixel, pc);
895                  value = (uint16) make_colour16(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
896                  if (g_xserver_be)                  if (g_xserver_be)
897                  {                  {
898                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
899                  }                  }
900                  else                  else
901                  {                  {
902                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
903                  }                  }
904          }          }
905  }  }
906    
907  static void  static void
908  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
909  {  {
910          while (out < end)          uint32 pixel;
911            uint32 value;
912            PixelColour pc;
913    
914            if (g_xserver_be)
915          {          {
916                  *(out++) = (*(data++));                  while (out < end)
917                    {
918                            pixel = *(data++) << 16;
919                            pixel |= *(data++) << 8;
920                            pixel |= *(data++);
921                            SPLITCOLOUR24(pixel, pc);
922                            value = MAKECOLOUR(pc);
923                            BOUT24(out, value);
924                    }
925            }
926            else
927            {
928                    while (out < end)
929                    {
930                            pixel = *(data++) << 16;
931                            pixel |= *(data++) << 8;
932                            pixel |= *(data++);
933                            SPLITCOLOUR24(pixel, pc);
934                            value = MAKECOLOUR(pc);
935                            LOUT24(out, value);
936                    }
937          }          }
938  }  }
939    
940  static void  static void
941  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
942  {  {
943          while (out < end)          uint32 pixel;
944            uint32 value;
945            PixelColour pc;
946    
947            if (g_compatible_arch)
948          {          {
949                  if (g_xserver_be)                  /* *INDENT-OFF* */
950                  {  #ifdef NEED_ALIGN
951                          *(out++) = 0x00;                  REPEAT4
952                    (
953                          *(out++) = *(data++);                          *(out++) = *(data++);
954                          *(out++) = *(data++);                          *(out++) = *(data++);
955                          *(out++) = *(data++);                          *(out++) = *(data++);
956                            *(out++) = 0;
957                    )
958    #else
959                    REPEAT4
960                    (
961                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
962                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
963                     out += 4;
964                     data += 3;
965                    )
966    #endif
967                    /* *INDENT-ON* */
968            }
969            else if (g_xserver_be)
970            {
971                    while (out < end)
972                    {
973                            pixel = *(data++) << 16;
974                            pixel |= *(data++) << 8;
975                            pixel |= *(data++);
976                            SPLITCOLOUR24(pixel, pc);
977                            value = MAKECOLOUR(pc);
978                            BOUT32(out, value);
979                  }                  }
980                  else          }
981            else
982            {
983                    while (out < end)
984                  {                  {
985                          *(out++) = *(data++);                          pixel = *(data++) << 16;
986                          *(out++) = *(data++);                          pixel |= *(data++) << 8;
987                          *(out++) = *(data++);                          pixel |= *(data++);
988                          *(out++) = 0x00;                          SPLITCOLOUR24(pixel, pc);
989                            value = MAKECOLOUR(pc);
990                            LOUT32(out, value);
991                  }                  }
992          }          }
993  }  }
# Line 571  translate24to32(uint8 * data, uint8 * ou Line 995  translate24to32(uint8 * data, uint8 * ou
995  static uint8 *  static uint8 *
996  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
997  {  {
998          int size = width * height * g_bpp / 8;          int size;
999          uint8 *out = (uint8 *) xmalloc(size);          uint8 *out;
1000          uint8 *end = out + size;          uint8 *end;
1001    
1002            /*
1003               If RDP depth and X Visual depths match,
1004               and arch(endian) matches, no need to translate:
1005               just return data.
1006               Note: select_visual should've already ensured g_no_translate
1007               is only set for compatible depths, but the RDP depth might've
1008               changed during connection negotiations.
1009             */
1010            if (g_no_translate_image)
1011            {
1012                    if ((g_depth == 15 && g_server_depth == 15) ||
1013                        (g_depth == 16 && g_server_depth == 16) ||
1014                        (g_depth == 24 && g_server_depth == 24))
1015                            return data;
1016            }
1017    
1018            size = width * height * (g_bpp / 8);
1019            out = (uint8 *) xmalloc(size);
1020            end = out + size;
1021    
1022          switch (g_server_bpp)          switch (g_server_depth)
1023          {          {
1024                  case 24:                  case 24:
1025                          switch (g_bpp)                          switch (g_bpp)
# Line 601  translate_image(int width, int height, u Line 1045  translate_image(int width, int height, u
1045                                          translate16to24((uint16 *) data, out, end);                                          translate16to24((uint16 *) data, out, end);
1046                                          break;                                          break;
1047                                  case 16:                                  case 16:
1048                                          translate16to16((uint16 *) data, (uint16 *) out,                                          translate16to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
1049                                          break;                                          break;
1050                          }                          }
1051                          break;                          break;
# Line 627  translate_image(int width, int height, u Line 1070  translate_image(int width, int height, u
1070                                          translate8to8(data, out, end);                                          translate8to8(data, out, end);
1071                                          break;                                          break;
1072                                  case 16:                                  case 16:
1073                                          translate8to16(data, (uint16 *) out, (uint16 *) end);                                          translate8to16(data, out, end);
1074                                          break;                                          break;
1075                                  case 24:                                  case 24:
1076                                          translate8to24(data, out, end);                                          translate8to24(data, out, end);
1077                                          break;                                          break;
1078                                  case 32:                                  case 32:
1079                                          translate8to32(data, (uint32 *) out, (uint32 *) end);                                          translate8to32(data, out, end);
1080                                          break;                                          break;
1081                          }                          }
1082                          break;                          break;
# Line 666  get_key_state(unsigned int state, uint32 Line 1109  get_key_state(unsigned int state, uint32
1109          return (state & keysymMask) ? True : False;          return (state & keysymMask) ? True : False;
1110  }  }
1111    
1112  BOOL  static void
1113  ui_init(void)  calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
1114    {
1115            *shift_l = ffs(mask) - 1;
1116            mask >>= *shift_l;
1117            *shift_r = 8 - ffs(mask & ~(mask >> 1));
1118    }
1119    
1120    /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1121       calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1122     */
1123    static unsigned
1124    calculate_mask_weight(uint32 mask)
1125    {
1126            unsigned weight = 0;
1127            do
1128            {
1129                    weight += (mask & 1);
1130            }
1131            while (mask >>= 1);
1132            return weight;
1133    }
1134    
1135    static BOOL
1136    select_visual()
1137  {  {
1138          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1139          uint16 test;          int pixmap_formats_count, visuals_count;
1140            XVisualInfo *vmatches = NULL;
1141            XVisualInfo template;
1142          int i;          int i;
1143            unsigned red_weight, blue_weight, green_weight;
1144    
1145          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1146          if (g_display == NULL)  
1147            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1148            if (pfm == NULL)
1149          {          {
1150                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1151                    XCloseDisplay(g_display);
1152                  return False;                  return False;
1153          }          }
1154    
1155          g_x_socket = ConnectionNumber(g_display);          /* Search for best TrueColor visual */
1156          g_screen = DefaultScreenOfDisplay(g_display);          template.class = TrueColor;
1157          g_visual = DefaultVisualOfScreen(g_screen);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1158          g_depth = DefaultDepthOfScreen(g_screen);          g_visual = NULL;
1159            g_no_translate_image = False;
1160            g_compatible_arch = False;
1161            if (vmatches != NULL)
1162            {
1163                    for (i = 0; i < visuals_count; ++i)
1164                    {
1165                            XVisualInfo *visual_info = &vmatches[i];
1166    
1167                            /* Try to find a no-translation visual that'll
1168                               allow us to use RDP bitmaps directly as ZPixmaps. */
1169                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1170                                                   /* R5G5B5 */
1171                                                   (visual_info->red_mask == 0x7c00) &&
1172                                                   (visual_info->green_mask == 0x3e0) &&
1173                                                   (visual_info->blue_mask == 0x1f)) ||
1174                                                  ((visual_info->depth == 16) &&
1175                                                   /* R5G6B5 */
1176                                                   (visual_info->red_mask == 0xf800) &&
1177                                                   (visual_info->green_mask == 0x7e0) &&
1178                                                   (visual_info->blue_mask == 0x1f)) ||
1179                                                  ((visual_info->depth == 24) &&
1180                                                   /* R8G8B8 */
1181                                                   (visual_info->red_mask == 0xff0000) &&
1182                                                   (visual_info->green_mask == 0xff00) &&
1183                                                   (visual_info->blue_mask == 0xff))))
1184                            {
1185                                    g_visual = visual_info->visual;
1186                                    g_depth = visual_info->depth;
1187                                    g_compatible_arch = !g_host_be;
1188                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1189                                    if (g_no_translate_image)
1190                                            /* We found the best visual */
1191                                            break;
1192                            }
1193                            else
1194                            {
1195                                    g_compatible_arch = False;
1196                            }
1197    
1198                            if (visual_info->depth > 24)
1199                            {
1200                                    /* Avoid 32-bit visuals and likes like the plague.
1201                                       They're either untested or proven to work bad
1202                                       (e.g. nvidia's Composite 32-bit visual).
1203                                       Most implementation offer a 24-bit visual anyway. */
1204                                    continue;
1205                            }
1206    
1207                            /* Only care for visuals, for whose BPPs (not depths!)
1208                               we have a translateXtoY function. */
1209                            BOOL can_translate_to_bpp = False;
1210                            int j;
1211                            for (j = 0; j < pixmap_formats_count; ++j)
1212                            {
1213                                    if (pfm[j].depth == visual_info->depth)
1214                                    {
1215                                            if ((pfm[j].bits_per_pixel == 16) ||
1216                                                (pfm[j].bits_per_pixel == 24) ||
1217                                                (pfm[j].bits_per_pixel == 32))
1218                                            {
1219                                                    can_translate_to_bpp = True;
1220                                            }
1221                                            break;
1222                                    }
1223                            }
1224    
1225                            /* Prefer formats which have the most colour depth.
1226                               We're being truly aristocratic here, minding each
1227                               weight on its own. */
1228                            if (can_translate_to_bpp)
1229                            {
1230                                    unsigned vis_red_weight =
1231                                            calculate_mask_weight(visual_info->red_mask);
1232                                    unsigned vis_green_weight =
1233                                            calculate_mask_weight(visual_info->green_mask);
1234                                    unsigned vis_blue_weight =
1235                                            calculate_mask_weight(visual_info->blue_mask);
1236                                    if ((vis_red_weight >= red_weight)
1237                                        && (vis_green_weight >= green_weight)
1238                                        && (vis_blue_weight >= blue_weight))
1239                                    {
1240                                            red_weight = vis_red_weight;
1241                                            green_weight = vis_green_weight;
1242                                            blue_weight = vis_blue_weight;
1243                                            g_visual = visual_info->visual;
1244                                            g_depth = visual_info->depth;
1245                                    }
1246                            }
1247                    }
1248                    XFree(vmatches);
1249            }
1250    
1251          pfm = XListPixmapFormats(g_display, &i);          if (g_visual != NULL)
         if (pfm != NULL)  
1252          {          {
1253                  /* Use maximum bpp for this depth - this is generally                  g_owncolmap = False;
1254                     desirable, e.g. 24 bits->32 bits. */                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1255                  while (i--)                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1256                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1257            }
1258            else
1259            {
1260                    template.class = PseudoColor;
1261                    template.depth = 8;
1262                    template.colormap_size = 256;
1263                    vmatches =
1264                            XGetVisualInfo(g_display,
1265                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1266                                           &template, &visuals_count);
1267                    if (vmatches == NULL)
1268                    {
1269                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1270                            XCloseDisplay(g_display);
1271                            XFree(pfm);
1272                            return False;
1273                    }
1274    
1275                    /* we use a colourmap, so the default visual should do */
1276                    g_owncolmap = True;
1277                    g_visual = vmatches[0].visual;
1278                    g_depth = vmatches[0].depth;
1279            }
1280    
1281            g_bpp = 0;
1282            for (i = 0; i < pixmap_formats_count; ++i)
1283            {
1284                    XPixmapFormatValues *pf = &pfm[i];
1285                    if (pf->depth == g_depth)
1286                  {                  {
1287                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1288    
1289                            if (g_no_translate_image)
1290                          {                          {
1291                                  g_bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1292                                    {
1293                                            case 15:
1294                                            case 16:
1295                                                    if (g_bpp != 16)
1296                                                            g_no_translate_image = False;
1297                                                    break;
1298                                            case 24:
1299                                                    /* Yes, this will force image translation
1300                                                       on most modern servers which use 32 bits
1301                                                       for R8G8B8. */
1302                                                    if (g_bpp != 24)
1303                                                            g_no_translate_image = False;
1304                                                    break;
1305                                            default:
1306                                                    g_no_translate_image = False;
1307                                                    break;
1308                                    }
1309                          }                          }
1310    
1311                            /* Pixmap formats list is a depth-to-bpp mapping --
1312                               there's just a single entry for every depth,
1313                               so we can safely break here */
1314                            break;
1315                  }                  }
                 XFree(pfm);  
1316          }          }
1317            XFree(pfm);
1318            pfm = NULL;
1319            return True;
1320    }
1321    
1322    BOOL
1323    ui_init(void)
1324    {
1325            int screen_num;
1326    
1327          if (g_bpp < 8)          g_display = XOpenDisplay(NULL);
1328            if (g_display == NULL)
1329          {          {
1330                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
                 XCloseDisplay(g_display);  
1331                  return False;                  return False;
1332          }          }
1333    
         if (g_owncolmap != True)  
1334          {          {
1335                  g_xcolmap = DefaultColormapOfScreen(g_screen);                  uint16 endianess_test = 1;
1336                  if (g_depth <= 8)                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
                         warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");  
1337          }          }
1338    
1339          g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1340            screen_num = DefaultScreen(g_display);
1341            g_x_socket = ConnectionNumber(g_display);
1342            g_screen = ScreenOfDisplay(g_display, screen_num);
1343            g_depth = DefaultDepthOfScreen(g_screen);
1344    
1345          if (DoesBackingStore(g_screen) != Always)          if (!select_visual())
1346                  g_ownbackstore = True;                  return False;
1347    
1348          test = 1;          if (g_no_translate_image)
1349          g_host_be = !(BOOL) (*(uint8 *) (&test));          {
1350          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);                  DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1351            }
1352    
1353            if (g_server_depth > g_bpp)
1354            {
1355                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1356                            g_server_depth, g_bpp);
1357            }
1358    
1359            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1360                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1361    
1362            if (!g_owncolmap)
1363            {
1364                    g_xcolmap =
1365                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1366                                            AllocNone);
1367                    if (g_depth <= 8)
1368                            warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1369            }
1370    
1371            if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1372            {
1373                    warning("External BackingStore not available. Using internal.\n");
1374                    g_ownbackstore = True;
1375            }
1376    
1377          if ((g_width == 0) || (g_height == 0))          /*
1378             * Determine desktop size
1379             */
1380            if (g_fullscreen)
1381            {
1382                    g_width = WidthOfScreen(g_screen);
1383                    g_height = HeightOfScreen(g_screen);
1384                    g_using_full_workarea = True;
1385            }
1386            else if (g_width < 0)
1387            {
1388                    /* Percent of screen */
1389                    if (-g_width >= 100)
1390                            g_using_full_workarea = True;
1391                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1392                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1393            }
1394            else if (g_width == 0)
1395          {          {
1396                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1397                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1398                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1399                  {                  {
1400                          g_width = cx;                          g_width = cx;
1401                          g_height = cy;                          g_height = cy;
1402                            g_using_full_workarea = True;
1403                  }                  }
1404                  else                  else
1405                  {                  {
1406                          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");
1407                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1408                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1409                  }                  }
1410          }          }
1411    
         if (g_fullscreen)  
         {  
                 g_width = WidthOfScreen(g_screen);  
                 g_height = HeightOfScreen(g_screen);  
         }  
   
1412          /* make sure width is a multiple of 4 */          /* make sure width is a multiple of 4 */
1413          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1414    
         if (g_ownbackstore)  
         {  
                 g_backstore =  
                         XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,  
                                       g_depth);  
   
                 /* clear to prevent rubbish being exposed at startup */  
                 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));  
                 XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);  
         }  
   
1415          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1416    
1417            xkeymap_init();
1418    
1419          if (g_enable_compose)          if (g_enable_compose)
1420                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1421    
         xkeymap_init();  
1422          xclip_init();          xclip_init();
1423            ewmh_init();
1424            if (g_seamless_rdp)
1425                    seamless_init();
1426    
1427          /* todo take this out when high colour is done */          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
         printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth);  
1428    
1429          return True;          return True;
1430  }  }
# Line 781  ui_deinit(void) Line 1435  ui_deinit(void)
1435          if (g_IM != NULL)          if (g_IM != NULL)
1436                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1437    
1438            if (g_null_cursor != NULL)
1439                    ui_destroy_cursor(g_null_cursor);
1440    
1441          XFreeModifiermap(g_mod_map);          XFreeModifiermap(g_mod_map);
1442    
1443          if (g_ownbackstore)          if (g_ownbackstore)
# Line 791  ui_deinit(void) Line 1448  ui_deinit(void)
1448          g_display = NULL;          g_display = NULL;
1449  }  }
1450    
1451    
1452    static void
1453    get_window_attribs(XSetWindowAttributes * attribs)
1454    {
1455            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1456            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1457            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1458            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1459            attribs->override_redirect = g_fullscreen;
1460            attribs->colormap = g_xcolmap;
1461    }
1462    
1463    static void
1464    get_input_mask(long *input_mask)
1465    {
1466            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1467                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1468    
1469            if (g_sendmotion)
1470                    *input_mask |= PointerMotionMask;
1471            if (g_ownbackstore)
1472                    *input_mask |= ExposureMask;
1473            if (g_fullscreen || g_grab_keyboard)
1474                    *input_mask |= EnterWindowMask;
1475            if (g_grab_keyboard)
1476                    *input_mask |= LeaveWindowMask;
1477    }
1478    
1479  BOOL  BOOL
1480  ui_create_window(void)  ui_create_window(void)
1481  {  {
1482            uint8 null_pointer_mask[1] = { 0x80 };
1483            uint8 null_pointer_data[24] = { 0x00 };
1484    
1485          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1486          XClassHint *classhints;          XClassHint *classhints;
1487          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 804  ui_create_window(void) Line 1492  ui_create_window(void)
1492          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1493          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1494    
1495          attribs.background_pixel = BlackPixelOfScreen(g_screen);          /* Handle -x-y portion of geometry string */
1496          attribs.backing_store = g_ownbackstore ? NotUseful : Always;          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1497          attribs.override_redirect = g_fullscreen;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1498            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1499          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1500                                0, CopyFromParent, InputOutput, CopyFromParent,  
1501                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);          get_window_attribs(&attribs);
1502    
1503            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1504                                  wndheight, 0, g_depth, InputOutput, g_visual,
1505                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1506                                  CWBorderPixel, &attribs);
1507    
1508            if (g_gc == NULL)
1509            {
1510                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1511                    ui_reset_clip();
1512            }
1513    
1514            if (g_create_bitmap_gc == NULL)
1515                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1516    
1517            if ((g_ownbackstore) && (g_backstore == 0))
1518            {
1519                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1520    
1521                    /* clear to prevent rubbish being exposed at startup */
1522                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1523                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1524            }
1525    
1526          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1527    
1528          if (g_hide_decorations)          if (g_hide_decorations)
1529                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1530    
1531          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1532          if (classhints != NULL)          if (classhints != NULL)
# Line 829  ui_create_window(void) Line 1540  ui_create_window(void)
1540          if (sizehints)          if (sizehints)
1541          {          {
1542                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1543                    if (g_pos)
1544                            sizehints->flags |= PPosition;
1545                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1546                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1547                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1548                  XFree(sizehints);                  XFree(sizehints);
1549          }          }
1550    
1551          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          if (g_embed_wnd)
1552                  VisibilityChangeMask | FocusChangeMask;          {
1553                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1554            }
1555    
1556          if (g_sendmotion)          get_input_mask(&input_mask);
                 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;  
1557    
1558          if (g_IM != NULL)          if (g_IM != NULL)
1559          {          {
# Line 858  ui_create_window(void) Line 1566  ui_create_window(void)
1566          }          }
1567    
1568          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1569          XMapWindow(g_display, g_wnd);          if (!g_seamless_rdp)
   
         /* wait for VisibilityNotify */  
         do  
1570          {          {
1571                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMapWindow(g_display, g_wnd);
1572                    /* wait for VisibilityNotify */
1573                    do
1574                    {
1575                            XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1576                    }
1577                    while (xevent.type != VisibilityNotify);
1578                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1579          }          }
         while (xevent.type != VisibilityNotify);  
1580    
1581          g_focused = False;          g_focused = False;
1582          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 875  ui_create_window(void) Line 1586  ui_create_window(void)
1586          g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);          g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1587          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1588    
1589            /* create invisible 1x1 cursor to be used as null cursor */
1590            if (g_null_cursor == NULL)
1591                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1592    
1593          return True;          return True;
1594  }  }
1595    
1596  void  void
1597    ui_resize_window()
1598    {
1599            XSizeHints *sizehints;
1600            Pixmap bs;
1601    
1602            sizehints = XAllocSizeHints();
1603            if (sizehints)
1604            {
1605                    sizehints->flags = PMinSize | PMaxSize;
1606                    sizehints->min_width = sizehints->max_width = g_width;
1607                    sizehints->min_height = sizehints->max_height = g_height;
1608                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1609                    XFree(sizehints);
1610            }
1611    
1612            if (!(g_fullscreen || g_embed_wnd))
1613            {
1614                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1615            }
1616    
1617            /* create new backstore pixmap */
1618            if (g_backstore != 0)
1619            {
1620                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1621                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1622                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1623                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1624                    XFreePixmap(g_display, g_backstore);
1625                    g_backstore = bs;
1626            }
1627    }
1628    
1629    void
1630  ui_destroy_window(void)  ui_destroy_window(void)
1631  {  {
1632          if (g_IC != NULL)          if (g_IC != NULL)
# Line 892  xwin_toggle_fullscreen(void) Line 1640  xwin_toggle_fullscreen(void)
1640  {  {
1641          Pixmap contents = 0;          Pixmap contents = 0;
1642    
1643            if (g_seamless_rdp)
1644                    /* Turn off SeamlessRDP mode */
1645                    ui_seamless_toggle();
1646    
1647          if (!g_ownbackstore)          if (!g_ownbackstore)
1648          {          {
1649                  /* need to save contents of window */                  /* need to save contents of window */
# Line 912  xwin_toggle_fullscreen(void) Line 1664  xwin_toggle_fullscreen(void)
1664          }          }
1665  }  }
1666    
1667  /* Process all events in Xlib queue  static void
1668    handle_button_event(XEvent xevent, BOOL down)
1669    {
1670            uint16 button, flags = 0;
1671            g_last_gesturetime = xevent.xbutton.time;
1672            button = xkeymap_translate_button(xevent.xbutton.button);
1673            if (button == 0)
1674                    return;
1675    
1676            if (down)
1677                    flags = MOUSE_FLAG_DOWN;
1678    
1679            /* Stop moving window when button is released, regardless of cursor position */
1680            if (g_moving_wnd && (xevent.type == ButtonRelease))
1681                    g_moving_wnd = False;
1682    
1683            /* If win_button_size is nonzero, enable single app mode */
1684            if (xevent.xbutton.y < g_win_button_size)
1685            {
1686                    /*  Check from right to left: */
1687                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1688                    {
1689                            /* The close button, continue */
1690                            ;
1691                    }
1692                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1693                    {
1694                            /* The maximize/restore button. Do not send to
1695                               server.  It might be a good idea to change the
1696                               cursor or give some other visible indication
1697                               that rdesktop inhibited this click */
1698                            if (xevent.type == ButtonPress)
1699                                    return;
1700                    }
1701                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1702                    {
1703                            /* The minimize button. Iconify window. */
1704                            if (xevent.type == ButtonRelease)
1705                            {
1706                                    /* Release the mouse button outside the minimize button, to prevent the
1707                                       actual minimazation to happen */
1708                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1709                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1710                                    return;
1711                            }
1712                    }
1713                    else if (xevent.xbutton.x <= g_win_button_size)
1714                    {
1715                            /* The system menu. Ignore. */
1716                            if (xevent.type == ButtonPress)
1717                                    return;
1718                    }
1719                    else
1720                    {
1721                            /* The title bar. */
1722                            if (xevent.type == ButtonPress)
1723                            {
1724                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1725                                    {
1726                                            g_moving_wnd = True;
1727                                            g_move_x_offset = xevent.xbutton.x;
1728                                            g_move_y_offset = xevent.xbutton.y;
1729                                    }
1730                                    return;
1731                            }
1732                    }
1733            }
1734    
1735            if (xevent.xmotion.window == g_wnd)
1736            {
1737                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1738                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1739            }
1740            else
1741            {
1742                    /* SeamlessRDP */
1743                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1744                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1745            }
1746    }
1747    
1748    /* Process events in Xlib queue
1749     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1750  static int  static int
1751  xwin_process_events(void)  xwin_process_events(void)
1752  {  {
1753          XEvent xevent;          XEvent xevent;
1754          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1755          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1756          char str[256];          char str[256];
1757          Status status;          Status status;
1758          unsigned int state;          int events = 0;
1759          Window wdummy;          seamless_window *sw;
         int dummy;  
1760    
1761          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1762          {          {
1763                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1764    
# Line 938  xwin_process_events(void) Line 1768  xwin_process_events(void)
1768                          continue;                          continue;
1769                  }                  }
1770    
                 flags = 0;  
   
1771                  switch (xevent.type)                  switch (xevent.type)
1772                  {                  {
1773                            case VisibilityNotify:
1774                                    if (xevent.xvisibility.window == g_wnd)
1775                                            g_Unobscured =
1776                                                    xevent.xvisibility.state == VisibilityUnobscured;
1777    
1778                                    break;
1779                          case ClientMessage:                          case ClientMessage:
1780                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1781                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
# Line 973  xwin_process_events(void) Line 1807  xwin_process_events(void)
1807                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1808                                  }                                  }
1809    
1810                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1811                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1812    
1813                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1814                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1815                                          break;                                          break;
1816    
1817                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1818                                                             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);  
   
1819                                  break;                                  break;
1820    
1821                          case KeyRelease:                          case KeyRelease:
# Line 998  xwin_process_events(void) Line 1823  xwin_process_events(void)
1823                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1824                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1825    
1826                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1827                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1828    
1829                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1830                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1831                                          break;                                          break;
1832    
1833                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1834                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1835                                  break;                                  break;
1836    
1837                          case ButtonPress:                          case ButtonPress:
1838                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1839                                  /* fall through */                                  break;
1840    
1841                          case ButtonRelease:                          case ButtonRelease:
1842                                  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);  
1843                                  break;                                  break;
1844    
1845                          case MotionNotify:                          case MotionNotify:
# Line 1091  xwin_process_events(void) Line 1854  xwin_process_events(void)
1854                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1855                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1856                                                         CurrentTime);                                                         CurrentTime);
1857                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1858                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1859                                    {
1860                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1861                                                           xevent.xmotion.x, xevent.xmotion.y);
1862                                    }
1863                                    else
1864                                    {
1865                                            /* SeamlessRDP */
1866                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1867                                                           xevent.xmotion.x_root,
1868                                                           xevent.xmotion.y_root);
1869                                    }
1870                                  break;                                  break;
1871    
1872                          case FocusIn:                          case FocusIn:
1873                                  if (xevent.xfocus.mode == NotifyGrab)                                  if (xevent.xfocus.mode == NotifyGrab)
1874                                          break;                                          break;
1875                                  g_focused = True;                                  g_focused = True;
1876                                  XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,                                  reset_modifier_keys();
                                               &dummy, &dummy, &state);  
                                 reset_modifier_keys(state);  
1877                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
1878                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
1879                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
# Line 1137  xwin_process_events(void) Line 1909  xwin_process_events(void)
1909                                  break;                                  break;
1910    
1911                          case Expose:                          case Expose:
1912                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
1913                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1914                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1915                                            xevent.xexpose.height,                                                    g_gc,
1916                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1917                                                      xevent.xexpose.width, xevent.xexpose.height,
1918                                                      xevent.xexpose.x, xevent.xexpose.y);
1919                                    }
1920                                    else
1921                                    {
1922                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1923                                            if (sw)
1924                                                    XCopyArea(g_display, g_backstore,
1925                                                              xevent.xexpose.window, g_gc,
1926                                                              xevent.xexpose.x + sw->xoffset,
1927                                                              xevent.xexpose.y + sw->yoffset,
1928                                                              xevent.xexpose.width,
1929                                                              xevent.xexpose.height, xevent.xexpose.x,
1930                                                              xevent.xexpose.y);
1931                                            else
1932                                            {
1933                                                    error("Expose for unknown window 0x%lx\n",
1934                                                          xevent.xexpose.window);
1935                                            }
1936                                    }
1937    
1938                                  break;                                  break;
1939    
1940                          case MappingNotify:                          case MappingNotify:
# Line 1170  xwin_process_events(void) Line 1963  xwin_process_events(void)
1963                                  break;                                  break;
1964                          case PropertyNotify:                          case PropertyNotify:
1965                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1966                                    if (xevent.xproperty.window == g_wnd)
1967                                            break;
1968                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
1969                                            break;
1970    
1971                                    /* seamless */
1972                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
1973                                    if (!sw)
1974                                            break;
1975    
1976                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
1977                                        && (xevent.xproperty.state == PropertyNewValue))
1978                                    {
1979                                            sw->state = ewmh_get_window_state(sw->wnd);
1980                                            seamless_send_state(sw->id, sw->state, 0);
1981                                    }
1982    
1983                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
1984                                        && (xevent.xproperty.state == PropertyNewValue))
1985                                    {
1986                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
1987                                            seamless_all_to_desktop(sw->wnd, sw->desktop);
1988                                    }
1989    
1990                                    break;
1991                            case MapNotify:
1992                                    if (!g_seamless_rdp)
1993                                            rdp_send_client_window_status(1);
1994                                    break;
1995                            case UnmapNotify:
1996                                    if (!g_seamless_rdp)
1997                                            rdp_send_client_window_status(0);
1998                                  break;                                  break;
1999                  }                  }
2000          }          }
# Line 1181  xwin_process_events(void) Line 2006  xwin_process_events(void)
2006  int  int
2007  ui_select(int rdp_socket)  ui_select(int rdp_socket)
2008  {  {
2009          int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;          int n;
2010          fd_set rfds, wfds;          fd_set rfds, wfds;
2011            struct timeval tv;
2012            BOOL s_timeout = False;
2013    
2014          while (True)          while (True)
2015          {          {
2016                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
2017                  /* Process any events already waiting */                  /* Process any events already waiting */
2018                  if (!xwin_process_events())                  if (!xwin_process_events())
2019                          /* User quit */                          /* User quit */
# Line 1201  ui_select(int rdp_socket) Line 2029  ui_select(int rdp_socket)
2029                  if (g_dsp_busy)                  if (g_dsp_busy)
2030                  {                  {
2031                          FD_SET(g_dsp_fd, &wfds);                          FD_SET(g_dsp_fd, &wfds);
2032                          n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;                          n = (g_dsp_fd > n) ? g_dsp_fd : n;
2033                  }                  }
2034  #endif  #endif
2035                    /* default timeout */
2036                    tv.tv_sec = 60;
2037                    tv.tv_usec = 0;
2038    
2039                  switch (select(n, &rfds, &wfds, NULL, NULL))                  /* add redirection handles */
2040                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2041    
2042                    n++;
2043    
2044                    switch (select(n, &rfds, &wfds, NULL, &tv))
2045                  {                  {
2046                          case -1:                          case -1:
2047                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2048    
2049                          case 0:                          case 0:
2050                                    /* Abort serial read calls */
2051                                    if (s_timeout)
2052                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
2053                                  continue;                                  continue;
2054                  }                  }
2055    
2056                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
2057    
2058                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2059                          return 1;                          return 1;
2060    
# Line 1236  ui_create_bitmap(int width, int height, Line 2077  ui_create_bitmap(int width, int height,
2077          XImage *image;          XImage *image;
2078          Pixmap bitmap;          Pixmap bitmap;
2079          uint8 *tdata;          uint8 *tdata;
2080            int bitmap_pad;
2081    
2082            if (g_server_depth == 8)
2083            {
2084                    bitmap_pad = 8;
2085            }
2086            else
2087            {
2088                    bitmap_pad = g_bpp;
2089    
2090                    if (g_bpp == 24)
2091                            bitmap_pad = 32;
2092            }
2093    
2094          tdata = (g_owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
2095          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
2096          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2097                               (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
2098    
2099          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);
2100    
2101          XFree(image);          XFree(image);
2102          if (!g_owncolmap)          if (tdata != data)
2103                  xfree(tdata);                  xfree(tdata);
2104          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
2105  }  }
# Line 1255  ui_paint_bitmap(int x, int y, int cx, in Line 2109  ui_paint_bitmap(int x, int y, int cx, in
2109  {  {
2110          XImage *image;          XImage *image;
2111          uint8 *tdata;          uint8 *tdata;
2112            int bitmap_pad;
2113    
2114            if (g_server_depth == 8)
2115            {
2116                    bitmap_pad = 8;
2117            }
2118            else
2119            {
2120                    bitmap_pad = g_bpp;
2121    
2122                    if (g_bpp == 24)
2123                            bitmap_pad = 32;
2124            }
2125    
2126          tdata = (g_owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
2127          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2128                               (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
2129    
2130          if (g_ownbackstore)          if (g_ownbackstore)
2131          {          {
2132                  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);
2133                  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);
2134                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2135                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2136                                             x - sw->xoffset, y - sw->yoffset));
2137          }          }
2138          else          else
2139          {          {
2140                  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);
2141                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2142                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2143                                             x - sw->xoffset, y - sw->yoffset));
2144          }          }
2145    
2146          XFree(image);          XFree(image);
2147          if (!g_owncolmap)          if (tdata != data)
2148                  xfree(tdata);                  xfree(tdata);
2149  }  }
2150    
# Line 1286  ui_create_glyph(int width, int height, u Line 2160  ui_create_glyph(int width, int height, u
2160          XImage *image;          XImage *image;
2161          Pixmap bitmap;          Pixmap bitmap;
2162          int scanline;          int scanline;
         GC gc;  
2163    
2164          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
2165    
2166          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
2167          gc = XCreateGC(g_display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
2168                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
2169    
2170          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
2171                               width, height, 8, scanline);                               width, height, 8, scanline);
# Line 1299  ui_create_glyph(int width, int height, u Line 2173  ui_create_glyph(int width, int height, u
2173          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
2174          XInitImage(image);          XInitImage(image);
2175    
2176          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);
2177    
2178          XFree(image);          XFree(image);
         XFreeGC(g_display, gc);  
2179          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
2180  }  }
2181    
# Line 1388  ui_set_cursor(HCURSOR cursor) Line 2261  ui_set_cursor(HCURSOR cursor)
2261  {  {
2262          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2263          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2264            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2265  }  }
2266    
2267  void  void
# Line 1396  ui_destroy_cursor(HCURSOR cursor) Line 2270  ui_destroy_cursor(HCURSOR cursor)
2270          XFreeCursor(g_display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2271  }  }
2272    
2273    void
2274    ui_set_null_cursor(void)
2275    {
2276            ui_set_cursor(g_null_cursor);
2277    }
2278    
2279  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
2280                  (xc)->red   = ((c)->red   << 8) | (c)->red; \                  (xc)->red   = ((c)->red   << 8) | (c)->red; \
2281                  (xc)->green = ((c)->green << 8) | (c)->green; \                  (xc)->green = ((c)->green << 8) | (c)->green; \
# Line 1477  ui_create_colourmap(COLOURMAP * colours) Line 2357  ui_create_colourmap(COLOURMAP * colours)
2357    
2358                          }                          }
2359    
2360                            map[i] = colour;
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
2361                  }                  }
2362                  return map;                  return map;
2363          }          }
# Line 1525  ui_set_colourmap(HCOLOURMAP map) Line 2403  ui_set_colourmap(HCOLOURMAP map)
2403                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2404          }          }
2405          else          else
2406            {
2407                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2408                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2409            }
2410  }  }
2411    
2412  void  void
2413  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2414  {  {
2415          XRectangle rect;          g_clip_rectangle.x = x;
2416            g_clip_rectangle.y = y;
2417          rect.x = x;          g_clip_rectangle.width = cx;
2418          rect.y = y;          g_clip_rectangle.height = cy;
2419          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);  
2420  }  }
2421    
2422  void  void
2423  ui_reset_clip(void)  ui_reset_clip(void)
2424  {  {
2425          XRectangle rect;          g_clip_rectangle.x = 0;
2426            g_clip_rectangle.y = 0;
2427          rect.x = 0;          g_clip_rectangle.width = g_width;
2428          rect.y = 0;          g_clip_rectangle.height = g_height;
2429          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);  
2430  }  }
2431    
2432  void  void
# Line 1590  ui_patblt(uint8 opcode, Line 2467  ui_patblt(uint8 opcode,
2467          {          {
2468                  case 0: /* Solid */                  case 0: /* Solid */
2469                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2470                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2471                          break;                          break;
2472    
2473                  case 2: /* Hatch */                  case 2: /* Hatch */
# Line 1601  ui_patblt(uint8 opcode, Line 2478  ui_patblt(uint8 opcode,
2478                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2479                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2480                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2481                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2482                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2483                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2484                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1611  ui_patblt(uint8 opcode, Line 2488  ui_patblt(uint8 opcode,
2488                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2489                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2490                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
2491                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2492                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2493                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2494                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2495                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2496                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
                         FILL_RECTANGLE(x, y, cx, cy);  
   
2497                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2498                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2499                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1630  ui_patblt(uint8 opcode, Line 2504  ui_patblt(uint8 opcode,
2504          }          }
2505    
2506          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2507    
2508            if (g_ownbackstore)
2509                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2510            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2511                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2512                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2513  }  }
2514    
2515  void  void
# Line 1638  ui_screenblt(uint8 opcode, Line 2518  ui_screenblt(uint8 opcode,
2518               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2519  {  {
2520          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
         XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
2521          if (g_ownbackstore)          if (g_ownbackstore)
2522            {
2523                    XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2524                              g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2525                  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);
2526            }
2527            else
2528            {
2529                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2530            }
2531    
2532            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2533                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2534                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2535    
2536          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2537  }  }
2538    
# Line 1651  ui_memblt(uint8 opcode, Line 2543  ui_memblt(uint8 opcode,
2543  {  {
2544          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2545          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);
2546            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2547                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2548                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2549          if (g_ownbackstore)          if (g_ownbackstore)
2550                  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);
2551          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1697  ui_line(uint8 opcode, Line 2592  ui_line(uint8 opcode,
2592          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2593          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2594          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2595            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2596                                                startx - sw->xoffset, starty - sw->yoffset,
2597                                                endx - sw->xoffset, endy - sw->yoffset));
2598          if (g_ownbackstore)          if (g_ownbackstore)
2599                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2600          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 1711  ui_rect( Line 2609  ui_rect(
2609          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2610  }  }
2611    
2612    void
2613    ui_polygon(uint8 opcode,
2614               /* mode */ uint8 fillmode,
2615               /* dest */ POINT * point, int npoints,
2616               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2617    {
2618            uint8 style, i, ipattern[8];
2619            Pixmap fill;
2620    
2621            SET_FUNCTION(opcode);
2622    
2623            switch (fillmode)
2624            {
2625                    case ALTERNATE:
2626                            XSetFillRule(g_display, g_gc, EvenOddRule);
2627                            break;
2628                    case WINDING:
2629                            XSetFillRule(g_display, g_gc, WindingRule);
2630                            break;
2631                    default:
2632                            unimpl("fill mode %d\n", fillmode);
2633            }
2634    
2635            if (brush)
2636                    style = brush->style;
2637            else
2638                    style = 0;
2639    
2640            switch (style)
2641            {
2642                    case 0: /* Solid */
2643                            SET_FOREGROUND(fgcolour);
2644                            FILL_POLYGON((XPoint *) point, npoints);
2645                            break;
2646    
2647                    case 2: /* Hatch */
2648                            fill = (Pixmap) ui_create_glyph(8, 8,
2649                                                            hatch_patterns + brush->pattern[0] * 8);
2650                            SET_FOREGROUND(fgcolour);
2651                            SET_BACKGROUND(bgcolour);
2652                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2653                            XSetStipple(g_display, g_gc, fill);
2654                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2655                            FILL_POLYGON((XPoint *) point, npoints);
2656                            XSetFillStyle(g_display, g_gc, FillSolid);
2657                            XSetTSOrigin(g_display, g_gc, 0, 0);
2658                            ui_destroy_glyph((HGLYPH) fill);
2659                            break;
2660    
2661                    case 3: /* Pattern */
2662                            for (i = 0; i != 8; i++)
2663                                    ipattern[7 - i] = brush->pattern[i];
2664                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2665                            SET_FOREGROUND(bgcolour);
2666                            SET_BACKGROUND(fgcolour);
2667                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2668                            XSetStipple(g_display, g_gc, fill);
2669                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2670                            FILL_POLYGON((XPoint *) point, npoints);
2671                            XSetFillStyle(g_display, g_gc, FillSolid);
2672                            XSetTSOrigin(g_display, g_gc, 0, 0);
2673                            ui_destroy_glyph((HGLYPH) fill);
2674                            break;
2675    
2676                    default:
2677                            unimpl("brush %d\n", brush->style);
2678            }
2679    
2680            RESET_FUNCTION(opcode);
2681    }
2682    
2683    void
2684    ui_polyline(uint8 opcode,
2685                /* dest */ POINT * points, int npoints,
2686                /* pen */ PEN * pen)
2687    {
2688            /* TODO: set join style */
2689            SET_FUNCTION(opcode);
2690            SET_FOREGROUND(pen->colour);
2691            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2692            if (g_ownbackstore)
2693                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2694                               CoordModePrevious);
2695    
2696            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2697                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2698    
2699            RESET_FUNCTION(opcode);
2700    }
2701    
2702    void
2703    ui_ellipse(uint8 opcode,
2704               /* mode */ uint8 fillmode,
2705               /* dest */ int x, int y, int cx, int cy,
2706               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2707    {
2708            uint8 style, i, ipattern[8];
2709            Pixmap fill;
2710    
2711            SET_FUNCTION(opcode);
2712    
2713            if (brush)
2714                    style = brush->style;
2715            else
2716                    style = 0;
2717    
2718            switch (style)
2719            {
2720                    case 0: /* Solid */
2721                            SET_FOREGROUND(fgcolour);
2722                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2723                            break;
2724    
2725                    case 2: /* Hatch */
2726                            fill = (Pixmap) ui_create_glyph(8, 8,
2727                                                            hatch_patterns + brush->pattern[0] * 8);
2728                            SET_FOREGROUND(fgcolour);
2729                            SET_BACKGROUND(bgcolour);
2730                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2731                            XSetStipple(g_display, g_gc, fill);
2732                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2733                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2734                            XSetFillStyle(g_display, g_gc, FillSolid);
2735                            XSetTSOrigin(g_display, g_gc, 0, 0);
2736                            ui_destroy_glyph((HGLYPH) fill);
2737                            break;
2738    
2739                    case 3: /* Pattern */
2740                            for (i = 0; i != 8; i++)
2741                                    ipattern[7 - i] = brush->pattern[i];
2742                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2743                            SET_FOREGROUND(bgcolour);
2744                            SET_BACKGROUND(fgcolour);
2745                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2746                            XSetStipple(g_display, g_gc, fill);
2747                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2748                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2749                            XSetFillStyle(g_display, g_gc, FillSolid);
2750                            XSetTSOrigin(g_display, g_gc, 0, 0);
2751                            ui_destroy_glyph((HGLYPH) fill);
2752                            break;
2753    
2754                    default:
2755                            unimpl("brush %d\n", brush->style);
2756            }
2757    
2758            RESET_FUNCTION(opcode);
2759    }
2760    
2761  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2762  void  void
2763  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1735  ui_draw_glyph(int mixmode, Line 2782  ui_draw_glyph(int mixmode,
2782  {\  {\
2783    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
2784    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
2785      {\
2786        xyoffset = ttext[++idx];\
2787        if ((xyoffset & 0x80))\
2788      {\      {\
2789        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
2790        if ((xyoffset & 0x80))\          y += ttext[idx+1] | (ttext[idx+2] << 8);\
         {\  
           if (flags & TEXT2_VERTICAL) \  
             y += ttext[idx+1] | (ttext[idx+2] << 8);\  
           else\  
             x += ttext[idx+1] | (ttext[idx+2] << 8);\  
           idx += 2;\  
         }\  
2791        else\        else\
2792          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
2793            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
2794      }\      }\
2795    if (glyph != NULL)\      else\
2796      {\      {\
2797        ui_draw_glyph (mixmode, x + glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2798                       y + glyph->baseline,\          y += xyoffset;\
2799                       glyph->width, glyph->height,\        else\
2800                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
2801      }\      }\
2802      }\
2803      if (glyph != NULL)\
2804      {\
2805        x1 = x + glyph->offset;\
2806        y1 = y + glyph->baseline;\
2807        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2808        XSetTSOrigin(g_display, g_gc, x1, y1);\
2809        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2810        if (flags & TEXT2_IMPLICIT_X)\
2811          x += glyph->width;\
2812      }\
2813  }  }
2814    
2815  void  void
2816  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,
2817               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2818               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2819               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2820  {  {
2821            /* TODO: use brush appropriately */
2822    
2823          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2824          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2825          DATABLOB *entry;          DATABLOB *entry;
2826    
2827          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2828    
2829            /* Sometimes, the boxcx value is something really large, like
2830               32691. This makes XCopyArea fail with Xvnc. The code below
2831               is a quick fix. */
2832            if (boxx + boxcx > g_width)
2833                    boxcx = g_width - boxx;
2834    
2835          if (boxcx > 1)          if (boxcx > 1)
2836          {          {
2837                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
# Line 1785  ui_draw_text(uint8 font, uint8 flags, in Line 2841  ui_draw_text(uint8 font, uint8 flags, in
2841                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2842          }          }
2843    
2844            SET_FOREGROUND(fgcolour);
2845            SET_BACKGROUND(bgcolour);
2846            XSetFillStyle(g_display, g_gc, FillStippled);
2847    
2848          /* Paint text, character by character */          /* Paint text, character by character */
2849          for (i = 0; i < length;)          for (i = 0; i < length;)
2850          {          {
2851                  switch (text[i])                  switch (text[i])
2852                  {                  {
2853                          case 0xff:                          case 0xff:
2854                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2855                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2856                                  {                                  {
2857                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2858                                          exit(1);                                          for (j = 0; j < length; j++)
2859                                                    fprintf(stderr, "%02x ", text[j]);
2860                                            fprintf(stderr, "\n");
2861                                            i = length = 0;
2862                                            break;
2863                                  }                                  }
2864                                    cache_put_text(text[i + 1], text, text[i + 2]);
2865                                    i += 3;
2866                                    length -= i;
2867                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2868                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2869                                  i = 0;                                  i = 0;
2870                                  break;                                  break;
2871    
2872                          case 0xfe:                          case 0xfe:
2873                                    /* At least one byte needs to follow */
2874                                    if (i + 2 > length)
2875                                    {
2876                                            warning("Skipping short 0xfe command:");
2877                                            for (j = 0; j < length; j++)
2878                                                    fprintf(stderr, "%02x ", text[j]);
2879                                            fprintf(stderr, "\n");
2880                                            i = length = 0;
2881                                            break;
2882                                    }
2883                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2884                                  if (entry != NULL)                                  if (entry->data != NULL)
2885                                  {                                  {
2886                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2887                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2888                                          {                                          {
2889                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2890                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 1835  ui_draw_text(uint8 font, uint8 flags, in Line 2910  ui_draw_text(uint8 font, uint8 flags, in
2910                                  break;                                  break;
2911                  }                  }
2912          }          }
2913    
2914            XSetFillStyle(g_display, g_gc, FillSolid);
2915    
2916          if (g_ownbackstore)          if (g_ownbackstore)
2917          {          {
2918                  if (boxcx > 1)                  if (boxcx > 1)
2919                    {
2920                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2921                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2922                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2923                                                    (g_display, g_backstore, sw->wnd, g_gc,
2924                                                     boxx, boxy,
2925                                                     boxcx, boxcy,
2926                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2927                    }
2928                  else                  else
2929                    {
2930                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2931                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2932                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2933                                                    (g_display, g_backstore, sw->wnd, g_gc,
2934                                                     clipx, clipy,
2935                                                     clipcx, clipcy, clipx - sw->xoffset,
2936                                                     clipy - sw->yoffset));
2937                    }
2938          }          }
2939  }  }
2940    
# Line 1888  ui_desktop_restore(uint32 offset, int x, Line 2980  ui_desktop_restore(uint32 offset, int x,
2980          {          {
2981                  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);
2982                  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);
2983                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2984                                            (g_display, g_backstore, sw->wnd, g_gc,
2985                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2986          }          }
2987          else          else
2988          {          {
2989                  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);
2990                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2991                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2992                                             x - sw->xoffset, y - sw->yoffset));
2993          }          }
2994    
2995          XFree(image);          XFree(image);
2996  }  }
2997    
2998    /* these do nothing here but are used in uiports */
2999    void
3000    ui_begin_update(void)
3001    {
3002    }
3003    
3004    void
3005    ui_end_update(void)
3006    {
3007    }
3008    
3009    void
3010    ui_seamless_toggle()
3011    {
3012            if (g_seamless_rdp)
3013            {
3014                    /* Deactivate */
3015                    while (g_seamless_windows)
3016                    {
3017                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3018                            seamless_remove_window(g_seamless_windows);
3019                    }
3020                    XMapWindow(g_display, g_wnd);
3021            }
3022            else
3023            {
3024                    /* Activate */
3025                    if (g_win_button_size)
3026                    {
3027                            error("SeamlessRDP mode cannot be activated when using single application mode\n");
3028                            return;
3029                    }
3030                    if (!g_using_full_workarea)
3031                    {
3032                            error("SeamlessRDP mode requires a session that covers the whole screen");
3033                            return;
3034                    }
3035    
3036                    XUnmapWindow(g_display, g_wnd);
3037                    seamless_send_sync();
3038            }
3039    
3040            g_seamless_rdp = !g_seamless_rdp;
3041    }
3042    
3043    void
3044    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3045    {
3046            Window wnd;
3047            XSetWindowAttributes attribs;
3048            XClassHint *classhints;
3049            XSizeHints *sizehints;
3050            long input_mask;
3051            seamless_window *sw, *sw_parent;
3052    
3053            /* Ignore CREATEs for existing windows */
3054            sw = seamless_get_window_by_id(id);
3055            if (sw)
3056                    return;
3057    
3058            get_window_attribs(&attribs);
3059            attribs.override_redirect = False;
3060    
3061            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3062                                InputOutput, g_visual,
3063                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3064                                CWBorderPixel, &attribs);
3065    
3066            XStoreName(g_display, wnd, "SeamlessRDP");
3067            ewmh_set_wm_name(wnd, "SeamlessRDP");
3068    
3069            mwm_hide_decorations(wnd);
3070    
3071            classhints = XAllocClassHint();
3072            if (classhints != NULL)
3073            {
3074                    classhints->res_name = "rdesktop";
3075                    classhints->res_class = "SeamlessRDP";
3076                    XSetClassHint(g_display, wnd, classhints);
3077                    XFree(classhints);
3078            }
3079    
3080            /* WM_NORMAL_HINTS */
3081            sizehints = XAllocSizeHints();
3082            if (sizehints != NULL)
3083            {
3084                    sizehints->flags = USPosition;
3085                    XSetWMNormalHints(g_display, wnd, sizehints);
3086                    XFree(sizehints);
3087            }
3088    
3089            /* Handle popups without parents through some ewm hints */
3090            if (parent == 0xFFFFFFFF)
3091                    ewmh_set_window_popup(wnd);
3092            /* Set WM_TRANSIENT_FOR, if necessary */
3093            else if (parent != 0x00000000)
3094            {
3095                    sw_parent = seamless_get_window_by_id(parent);
3096                    if (sw_parent)
3097                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3098                    else
3099                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3100            }
3101    
3102    
3103            /* FIXME: Support for Input Context:s */
3104    
3105            get_input_mask(&input_mask);
3106            input_mask |= PropertyChangeMask;
3107    
3108            XSelectInput(g_display, wnd, input_mask);
3109    
3110            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3111               seamless window, we could try to close the window on the
3112               serverside, instead of terminating rdesktop */
3113            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3114    
3115            sw = malloc(sizeof(seamless_window));
3116            sw->wnd = wnd;
3117            sw->id = id;
3118            sw->hints = XAllocWMHints();
3119            sw->hints->flags = 0;
3120            sw->xoffset = 0;
3121            sw->yoffset = 0;
3122            sw->width = 0;
3123            sw->height = 0;
3124            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3125            sw->desktop = 0;
3126            sw->next = g_seamless_windows;
3127            g_seamless_windows = sw;
3128    }
3129    
3130    
3131    void
3132    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3133    {
3134            seamless_window *sw;
3135    
3136            sw = seamless_get_window_by_id(id);
3137            if (!sw)
3138            {
3139                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3140                    return;
3141            }
3142    
3143            XDestroyWindow(g_display, sw->wnd);
3144            seamless_remove_window(sw);
3145    }
3146    
3147    
3148    void
3149    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3150    {
3151            seamless_window *sw;
3152    
3153            sw = seamless_get_window_by_id(id);
3154            if (!sw)
3155            {
3156                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3157                    return;
3158            }
3159    
3160            if (!width || !height)
3161                    /* X11 windows must be at least 1x1 */
3162                    return;
3163    
3164            /* About MAX and MIN: Windows allows moving a window outside
3165               the desktop. This happens, for example, when maximizing an
3166               application. In this case, the position is set to something
3167               like -4,-4,1288,1032. Many WMs does not allow windows
3168               outside the desktop, however. Therefore, clip the window
3169               ourselves. */
3170            sw->xoffset = MAX(0, x);
3171            sw->yoffset = MAX(0, y);
3172            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3173            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3174    
3175            /* If we move the window in a maximized state, then KDE won't
3176               accept restoration */
3177            switch (sw->state)
3178            {
3179                    case SEAMLESSRDP_MINIMIZED:
3180                    case SEAMLESSRDP_MAXIMIZED:
3181                            return;
3182            }
3183    
3184            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3185            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3186    }
3187    
3188    
3189    void
3190    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3191    {
3192            seamless_window *sw;
3193    
3194            sw = seamless_get_window_by_id(id);
3195            if (!sw)
3196            {
3197                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3198                    return;
3199            }
3200    
3201            /* FIXME: Might want to convert the name for non-EWMH WMs */
3202            XStoreName(g_display, sw->wnd, title);
3203            ewmh_set_wm_name(sw->wnd, title);
3204    }
3205    
3206    
3207    void
3208    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3209    {
3210            seamless_window *sw;
3211    
3212            sw = seamless_get_window_by_id(id);
3213            if (!sw)
3214            {
3215                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3216                    return;
3217            }
3218    
3219            switch (state)
3220            {
3221                    case SEAMLESSRDP_NORMAL:
3222                    case SEAMLESSRDP_MAXIMIZED:
3223                            ewmh_change_state(sw->wnd, state);
3224                            XMapWindow(g_display, sw->wnd);
3225                            break;
3226                    case SEAMLESSRDP_MINIMIZED:
3227                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3228                               the Window Manager should probably just ignore the request, since
3229                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3230                               such as minimization, rather than an independent state." Besides,
3231                               XIconifyWindow is easier. */
3232                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3233                            {
3234                                    sw->hints->flags |= StateHint;
3235                                    sw->hints->initial_state = IconicState;
3236                                    XSetWMHints(g_display, sw->wnd, sw->hints);
3237                                    XMapWindow(g_display, sw->wnd);
3238                            }
3239                            else
3240                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3241                            break;
3242                    default:
3243                            warning("SeamlessRDP: Invalid state %d\n", state);
3244                            break;
3245            }
3246    
3247            sw->state = state;
3248    }
3249    
3250    
3251    void
3252    ui_seamless_syncbegin(unsigned long flags)
3253    {
3254            /* Destroy all seamless windows */
3255            while (g_seamless_windows)
3256            {
3257                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3258                    seamless_remove_window(g_seamless_windows);
3259            }
3260    }

Legend:
Removed from v.487  
changed lines
  Added in v.1142

  ViewVC Help
Powered by ViewVC 1.1.26