/[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 432 by matthewc, Tue Jul 1 09:31:25 2003 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1107 by astrand, Fri Mar 10 14:09:16 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 width;  extern int g_width;
32  extern int height;  extern int g_height;
33  extern BOOL sendmotion;  extern int g_xpos;
34  extern BOOL fullscreen;  extern int g_ypos;
35  extern BOOL grab_keyboard;  extern int g_pos;
36  extern BOOL hide_decorations;  extern BOOL g_sendmotion;
37  extern char title[];  extern BOOL g_fullscreen;
38  extern int server_bpp;  extern BOOL g_grab_keyboard;
39  extern int win_button_size;  extern BOOL g_hide_decorations;
40  BOOL enable_compose = False;  extern char g_title[];
41  BOOL focused;  /* Color depth of the RDP session.
42  BOOL mouse_in_wnd;     As of RDP 5.1, it may be 8, 15, 16 or 24. */
43    extern int g_server_depth;
44  Display *display;  extern int g_win_button_size;
45  Time last_gesturetime;  
46  static int x_socket;  Display *g_display;
47  static Screen *screen;  Time g_last_gesturetime;
48  Window wnd;  static int g_x_socket;
49  static GC gc;  static Screen *g_screen;
50  static Visual *visual;  Window g_wnd;
51  static int depth;  
52  static int bpp;  /* SeamlessRDP support */
53  static XIM IM;  typedef struct _seamless_window
54  static XIC IC;  {
55  static XModifierKeymap *mod_map;          Window wnd;
56  static Cursor current_cursor;          unsigned long id;
57  static Atom protocol_atom, kill_atom;          int xoffset, yoffset;
58            int width, height;
59            struct _seamless_window *next;
60    } seamless_window;
61    static seamless_window *g_seamless_windows = NULL;
62    extern BOOL g_seamless_rdp;
63    
64    extern uint32 g_embed_wnd;
65    BOOL g_enable_compose = False;
66    BOOL g_Unobscured;              /* used for screenblt */
67    static GC g_gc = NULL;
68    static GC g_create_bitmap_gc = NULL;
69    static GC g_create_glyph_gc = NULL;
70    static XRectangle g_clip_rectangle;
71    static Visual *g_visual;
72    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
73       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
74       as far as we're concerned. */
75    static int g_depth;
76    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
77       This may be larger than g_depth, in which case some of the bits would
78       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
79    static int g_bpp;
80    static XIM g_IM;
81    static XIC g_IC;
82    static XModifierKeymap *g_mod_map;
83    static Cursor g_current_cursor;
84    static HCURSOR g_null_cursor = NULL;
85    static Atom g_protocol_atom, g_kill_atom;
86    static BOOL g_focused;
87    static BOOL g_mouse_in_wnd;
88    /* Indicates that:
89       1) visual has 15, 16 or 24 depth and the same color channel masks
90          as its RDP equivalent (implies X server is LE),
91       2) host is LE
92       This will trigger an optimization whose real value is questionable.
93    */
94    static BOOL g_compatible_arch;
95    /* Indicates whether RDP's bitmaps and our XImages have the same
96       binary format. If so, we can avoid an expensive translation.
97       Note that this can be true when g_compatible_arch is false,
98       e.g.:
99      
100         RDP(LE) <-> host(BE) <-> X-Server(LE)
101        
102       ('host' is the machine running rdesktop; the host simply memcpy's
103        so its endianess doesn't matter)
104     */
105    static BOOL g_no_translate_image = False;
106    
107  /* endianness */  /* endianness */
108  static BOOL host_be;  static BOOL g_host_be;
109  static BOOL xserver_be;  static BOOL g_xserver_be;
110    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
111    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
112    
113  /* software backing store */  /* software backing store */
114  static BOOL ownbackstore;  extern BOOL g_ownbackstore;
115  static Pixmap backstore;  static Pixmap g_backstore = 0;
116    
117  /* Moving in single app mode */  /* Moving in single app mode */
118  static BOOL moving_wnd;  static BOOL g_moving_wnd;
119  static int move_x_offset = 0;  static int g_move_x_offset = 0;
120  static int move_y_offset = 0;  static int g_move_y_offset = 0;
121    static BOOL g_using_full_workarea = False;
122    
123    #ifdef WITH_RDPSND
124    extern int g_dsp_fd;
125    extern BOOL g_dsp_busy;
126    extern BOOL g_rdpsnd;
127    #endif
128    
129  /* MWM decorations */  /* MWM decorations */
130  #define MWM_HINTS_DECORATIONS   (1L << 1)  #define MWM_HINTS_DECORATIONS   (1L << 1)
131  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
132  typedef struct  typedef struct
133  {  {
134          uint32 flags;          unsigned long flags;
135          uint32 functions;          unsigned long functions;
136          uint32 decorations;          unsigned long decorations;
137          sint32 inputMode;          long inputMode;
138          uint32 status;          unsigned long status;
139  }  }
140  PropMotifWmHints;  PropMotifWmHints;
141    
# Line 87  typedef struct Line 147  typedef struct
147  }  }
148  PixelColour;  PixelColour;
149    
150    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
151            do { \
152                    seamless_window *sw; \
153                    XRectangle rect; \
154                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
155                        rect.x = g_clip_rectangle.x - sw->xoffset; \
156                        rect.y = g_clip_rectangle.y - sw->yoffset; \
157                        rect.width = g_clip_rectangle.width; \
158                        rect.height = g_clip_rectangle.height; \
159                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
160                        func args; \
161                    } \
162                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
163            } while (0)
164    
165    static void
166    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
167    {
168            points[0].x -= xoffset;
169            points[0].y -= yoffset;
170            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
171            points[0].x += xoffset;
172            points[0].y += yoffset;
173    }
174    
175    static void
176    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
177    {
178            points[0].x -= xoffset;
179            points[0].y -= yoffset;
180            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
181            points[0].x += xoffset;
182            points[0].y += yoffset;
183    }
184    
185  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
186  { \  { \
187          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
188          if (ownbackstore) \          ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
189                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \          if (g_ownbackstore) \
190                    XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
191  }  }
192    
193  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
194  { \  { \
195          XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
196    }
197    
198    #define FILL_POLYGON(p,np)\
199    { \
200            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
201            if (g_ownbackstore) \
202                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
203            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
204    }
205    
206    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
207    { \
208            switch (m) \
209            { \
210                    case 0: /* Outline */ \
211                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
212                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
213                            if (g_ownbackstore) \
214                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
215                            break; \
216                    case 1: /* Filled */ \
217                            XFillArc(g_display, g_wnd, g_gc, x, y, \
218                                     cx, cy, 0, 360*64); \
219                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc, x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \
220                            if (g_ownbackstore) \
221                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
222                            break; \
223            } \
224  }  }
225    
226  /* colour maps */  /* colour maps */
227  BOOL owncolmap = False;  extern BOOL g_owncolmap;
228  static Colormap xcolmap;  static Colormap g_xcolmap;
229  static uint32 *colmap;  static uint32 *g_colmap = NULL;
230    
231  #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
232  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
233  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
234    
235  static int rop2_map[] = {  static int rop2_map[] = {
236          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 128  static int rop2_map[] = { Line 251  static int rop2_map[] = {
251          GXset                   /* 1 */          GXset                   /* 1 */
252  };  };
253    
254  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
255  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
256    
257    static seamless_window *
258    seamless_get_window_by_id(unsigned long id)
259    {
260            seamless_window *sw;
261            for (sw = g_seamless_windows; sw; sw = sw->next)
262            {
263                    if (sw->id == id)
264                            return sw;
265            }
266            return NULL;
267    }
268    
269    
270    static seamless_window *
271    seamless_get_window_by_wnd(Window wnd)
272    {
273            seamless_window *sw;
274            for (sw = g_seamless_windows; sw; sw = sw->next)
275            {
276                    if (sw->wnd == wnd)
277                            return sw;
278            }
279            return NULL;
280    }
281    
282    
283    static void
284    seamless_remove_window(seamless_window * win)
285    {
286            seamless_window *sw, **prevnext = &g_seamless_windows;
287            for (sw = g_seamless_windows; sw; sw = sw->next)
288            {
289                    if (sw == win)
290                    {
291                            *prevnext = sw->next;
292                            xfree(sw);
293                            return;
294                    }
295                    prevnext = &sw->next;
296            }
297            return;
298    }
299    
300    
301  static void  static void
302  mwm_hide_decorations(void)  mwm_hide_decorations(Window wnd)
303  {  {
304          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
305          Atom hintsatom;          Atom hintsatom;
# Line 142  mwm_hide_decorations(void) Line 309  mwm_hide_decorations(void)
309          motif_hints.decorations = 0;          motif_hints.decorations = 0;
310    
311          /* get the atom for the property */          /* get the atom for the property */
312          hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);          hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
313          if (!hintsatom)          if (!hintsatom)
314          {          {
315                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
316                  return;                  return;
317          }          }
318    
319          XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
320                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
 }  
321    
 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;  
322  }  }
323    
324  static uint32  #define SPLITCOLOUR15(colour, rv) \
325  make_colour16(PixelColour pc)  { \
326  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
327          pc.red = (pc.red * 0x1f) / 0xff;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
328          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;  
329  }  }
330    
331  static uint32  #define SPLITCOLOUR16(colour, rv) \
332  make_colour24(PixelColour pc)  { \
333  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
334          return (pc.red << 16) | (pc.green << 8) | pc.blue;          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
335  }          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
336    } \
337    
338  static uint32  #define SPLITCOLOUR24(colour, rv) \
339  make_colour32(PixelColour pc)  { \
340  {          rv.blue = (colour & 0xff0000) >> 16; \
341          return (pc.red << 16) | (pc.green << 8) | pc.blue;          rv.green = (colour & 0x00ff00) >> 8; \
342            rv.red = (colour & 0x0000ff); \
343  }  }
344    
345    #define MAKECOLOUR(pc) \
346            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
347                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
348                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
349    
350  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
351  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
352  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
353                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
354    
355    /* The following macros output the same octet sequences
356       on both BE and LE hosts: */
357    
358    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
359    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
360    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
361    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
362    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
363    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
364    
365  static uint32  static uint32
366  translate_colour(uint32 colour)  translate_colour(uint32 colour)
367  {  {
368          switch (server_bpp)          PixelColour pc;
369            switch (g_server_depth)
370          {          {
371                  case 15:                  case 15:
372                          switch (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;  
                         }  
373                          break;                          break;
374                  case 16:                  case 16:
375                          switch (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;  
                         }  
376                          break;                          break;
377                  case 24:                  case 24:
378                          switch (bpp)                          SPLITCOLOUR24(colour, pc);
                         {  
                                 case 16:  
                                         colour = make_colour16(split_colour24(colour));  
                                         break;  
                                 case 24:  
                                         break;  
                                 case 32:  
                                         colour = make_colour32(split_colour24(colour));  
                                         break;  
                         }  
379                          break;                          break;
380          }                  default:
381          switch (bpp)                          /* Avoid warning */
382          {                          pc.red = 0;
383                  case 16:                          pc.green = 0;
384                          if (host_be != xserver_be)                          pc.blue = 0;
                                 BSWAP16(colour);  
385                          break;                          break;
386            }
387            return MAKECOLOUR(pc);
388    }
389    
390                  case 24:  /* indent is confused by UNROLL8 */
391                          if (xserver_be)  /* *INDENT-OFF* */
                                 BSWAP24(colour);  
                         break;  
392    
393                  case 32:  /* repeat and unroll, similar to bitmap.c */
394                          if (host_be != xserver_be)  /* potentialy any of the following translate */
395                                  BSWAP32(colour);  /* functions can use repeat but just doing */
396                          break;  /* the most common ones */
         }  
397    
398          return colour;  #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
399    /* 2 byte output repeat */
400    #define REPEAT2(stm) \
401    { \
402            while (out <= end - 8 * 2) \
403                    UNROLL8(stm) \
404            while (out < end) \
405                    { stm } \
406    }
407    /* 3 byte output repeat */
408    #define REPEAT3(stm) \
409    { \
410            while (out <= end - 8 * 3) \
411                    UNROLL8(stm) \
412            while (out < end) \
413                    { stm } \
414    }
415    /* 4 byte output repeat */
416    #define REPEAT4(stm) \
417    { \
418            while (out <= end - 8 * 4) \
419                    UNROLL8(stm) \
420            while (out < end) \
421                    { stm } \
422  }  }
423    /* *INDENT-ON* */
424    
425  static void  static void
426  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
427  {  {
428          while (out < end)          while (out < end)
429                  *(out++) = (uint8) colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
430  }  }
431    
432  static void  static void
433  translate8to16(uint8 * data, uint16 * out, uint16 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
434  {  {
435          while (out < end)          uint16 value;
436                  *(out++) = (uint16) colmap[*(data++)];  
437            if (g_compatible_arch)
438            {
439                    /* *INDENT-OFF* */
440                    REPEAT2
441                    (
442                            *((uint16 *) out) = g_colmap[*(data++)];
443                            out += 2;
444                    )
445                    /* *INDENT-ON* */
446            }
447            else if (g_xserver_be)
448            {
449                    while (out < end)
450                    {
451                            value = (uint16) g_colmap[*(data++)];
452                            BOUT16(out, value);
453                    }
454            }
455            else
456            {
457                    while (out < end)
458                    {
459                            value = (uint16) g_colmap[*(data++)];
460                            LOUT16(out, value);
461                    }
462            }
463  }  }
464    
465  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
466  static void  static void
467  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
468  {  {
469          uint32 value;          uint32 value;
470    
471          while (out < end)          if (g_compatible_arch)
472            {
473                    while (out < end)
474                    {
475                            value = g_colmap[*(data++)];
476                            BOUT24(out, value);
477                    }
478            }
479            else
480          {          {
481                  value = colmap[*(data++)];                  while (out < end)
482                  *(out++) = value;                  {
483                  *(out++) = value >> 8;                          value = g_colmap[*(data++)];
484                  *(out++) = value >> 16;                          LOUT24(out, value);
485                    }
486          }          }
487  }  }
488    
489  static void  static void
490  translate8to32(uint8 * data, uint32 * out, uint32 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
491  {  {
492          while (out < end)          uint32 value;
                 *(out++) = colmap[*(data++)];  
 }  
493    
494  /* todo the remaining translate function might need some big endian check ?? */          if (g_compatible_arch)
495            {
496                    /* *INDENT-OFF* */
497                    REPEAT4
498                    (
499                            *((uint32 *) out) = g_colmap[*(data++)];
500                            out += 4;
501                    )
502                    /* *INDENT-ON* */
503            }
504            else if (g_xserver_be)
505            {
506                    while (out < end)
507                    {
508                            value = g_colmap[*(data++)];
509                            BOUT32(out, value);
510                    }
511            }
512            else
513            {
514                    while (out < end)
515                    {
516                            value = g_colmap[*(data++)];
517                            LOUT32(out, value);
518                    }
519            }
520    }
521    
522  static void  static void
523  translate15to16(uint16 * data, uint16 * out, uint16 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
524  {  {
525          while (out < end)          uint16 pixel;
526                  *(out++) = (uint16) make_colour16(split_colour15(*(data++)));          uint16 value;
527            PixelColour pc;
528    
529            if (g_xserver_be)
530            {
531                    while (out < end)
532                    {
533                            pixel = *(data++);
534                            if (g_host_be)
535                            {
536                                    BSWAP16(pixel);
537                            }
538                            SPLITCOLOUR15(pixel, pc);
539                            value = MAKECOLOUR(pc);
540                            BOUT16(out, value);
541                    }
542            }
543            else
544            {
545                    while (out < end)
546                    {
547                            pixel = *(data++);
548                            if (g_host_be)
549                            {
550                                    BSWAP16(pixel);
551                            }
552                            SPLITCOLOUR15(pixel, pc);
553                            value = MAKECOLOUR(pc);
554                            LOUT16(out, value);
555                    }
556            }
557  }  }
558    
559  static void  static void
560  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
561  {  {
562          uint32 value;          uint32 value;
563            uint16 pixel;
564            PixelColour pc;
565    
566          while (out < end)          if (g_compatible_arch)
567          {          {
568                  value = make_colour24(split_colour15(*(data++)));                  /* *INDENT-OFF* */
569                  *(out++) = value;                  REPEAT3
570                  *(out++) = value >> 8;                  (
571                  *(out++) = value >> 16;                          pixel = *(data++);
572                            SPLITCOLOUR15(pixel, pc);
573                            *(out++) = pc.blue;
574                            *(out++) = pc.green;
575                            *(out++) = pc.red;
576                    )
577                    /* *INDENT-ON* */
578            }
579            else if (g_xserver_be)
580            {
581                    while (out < end)
582                    {
583                            pixel = *(data++);
584                            if (g_host_be)
585                            {
586                                    BSWAP16(pixel);
587                            }
588                            SPLITCOLOUR15(pixel, pc);
589                            value = MAKECOLOUR(pc);
590                            BOUT24(out, value);
591                    }
592            }
593            else
594            {
595                    while (out < end)
596                    {
597                            pixel = *(data++);
598                            if (g_host_be)
599                            {
600                                    BSWAP16(pixel);
601                            }
602                            SPLITCOLOUR15(pixel, pc);
603                            value = MAKECOLOUR(pc);
604                            LOUT24(out, value);
605                    }
606          }          }
607  }  }
608    
609  static void  static void
610  translate15to32(uint16 * data, uint32 * out, uint32 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
611  {  {
612          while (out < end)          uint16 pixel;
613                  *(out++) = make_colour32(split_colour15(*(data++)));          uint32 value;
614            PixelColour pc;
615    
616            if (g_compatible_arch)
617            {
618                    /* *INDENT-OFF* */
619                    REPEAT4
620                    (
621                            pixel = *(data++);
622                            SPLITCOLOUR15(pixel, pc);
623                            *(out++) = pc.blue;
624                            *(out++) = pc.green;
625                            *(out++) = pc.red;
626                            *(out++) = 0;
627                    )
628                    /* *INDENT-ON* */
629            }
630            else if (g_xserver_be)
631            {
632                    while (out < end)
633                    {
634                            pixel = *(data++);
635                            if (g_host_be)
636                            {
637                                    BSWAP16(pixel);
638                            }
639                            SPLITCOLOUR15(pixel, pc);
640                            value = MAKECOLOUR(pc);
641                            BOUT32(out, value);
642                    }
643            }
644            else
645            {
646                    while (out < end)
647                    {
648                            pixel = *(data++);
649                            if (g_host_be)
650                            {
651                                    BSWAP16(pixel);
652                            }
653                            SPLITCOLOUR15(pixel, pc);
654                            value = MAKECOLOUR(pc);
655                            LOUT32(out, value);
656                    }
657            }
658  }  }
659    
660  static void  static void
661  translate16to16(uint16 * data, uint16 * out, uint16 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
662  {  {
663          while (out < end)          uint16 pixel;
664                  *(out++) = (uint16) (*(data++));          uint16 value;
665  }          PixelColour pc;
666    
667            if (g_xserver_be)
668            {
669                    if (g_host_be)
670                    {
671                            while (out < end)
672                            {
673                                    pixel = *(data++);
674                                    BSWAP16(pixel);
675                                    SPLITCOLOUR16(pixel, pc);
676                                    value = MAKECOLOUR(pc);
677                                    BOUT16(out, value);
678                            }
679                    }
680                    else
681                    {
682                            while (out < end)
683                            {
684                                    pixel = *(data++);
685                                    SPLITCOLOUR16(pixel, pc);
686                                    value = MAKECOLOUR(pc);
687                                    BOUT16(out, value);
688                            }
689                    }
690            }
691            else
692            {
693                    if (g_host_be)
694                    {
695                            while (out < end)
696                            {
697                                    pixel = *(data++);
698                                    BSWAP16(pixel);
699                                    SPLITCOLOUR16(pixel, pc);
700                                    value = MAKECOLOUR(pc);
701                                    LOUT16(out, value);
702                            }
703                    }
704                    else
705                    {
706                            while (out < end)
707                            {
708                                    pixel = *(data++);
709                                    SPLITCOLOUR16(pixel, pc);
710                                    value = MAKECOLOUR(pc);
711                                    LOUT16(out, value);
712                            }
713                    }
714            }
715    }
716    
717  static void  static void
718  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
719  {  {
720          uint32 value;          uint32 value;
721            uint16 pixel;
722            PixelColour pc;
723    
724          while (out < end)          if (g_compatible_arch)
725            {
726                    /* *INDENT-OFF* */
727                    REPEAT3
728                    (
729                            pixel = *(data++);
730                            SPLITCOLOUR16(pixel, pc);
731                            *(out++) = pc.blue;
732                            *(out++) = pc.green;
733                            *(out++) = pc.red;
734                    )
735                    /* *INDENT-ON* */
736            }
737            else if (g_xserver_be)
738            {
739                    if (g_host_be)
740                    {
741                            while (out < end)
742                            {
743                                    pixel = *(data++);
744                                    BSWAP16(pixel);
745                                    SPLITCOLOUR16(pixel, pc);
746                                    value = MAKECOLOUR(pc);
747                                    BOUT24(out, value);
748                            }
749                    }
750                    else
751                    {
752                            while (out < end)
753                            {
754                                    pixel = *(data++);
755                                    SPLITCOLOUR16(pixel, pc);
756                                    value = MAKECOLOUR(pc);
757                                    BOUT24(out, value);
758                            }
759                    }
760            }
761            else
762          {          {
763                  value = make_colour24(split_colour16(*(data++)));                  if (g_host_be)
764                  *(out++) = value;                  {
765                  *(out++) = value >> 8;                          while (out < end)
766                  *(out++) = value >> 16;                          {
767                                    pixel = *(data++);
768                                    BSWAP16(pixel);
769                                    SPLITCOLOUR16(pixel, pc);
770                                    value = MAKECOLOUR(pc);
771                                    LOUT24(out, value);
772                            }
773                    }
774                    else
775                    {
776                            while (out < end)
777                            {
778                                    pixel = *(data++);
779                                    SPLITCOLOUR16(pixel, pc);
780                                    value = MAKECOLOUR(pc);
781                                    LOUT24(out, value);
782                            }
783                    }
784          }          }
785  }  }
786    
787  static void  static void
788  translate16to32(uint16 * data, uint32 * out, uint32 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
789  {  {
790          while (out < end)          uint16 pixel;
791                  *(out++) = make_colour32(split_colour16(*(data++)));          uint32 value;
792            PixelColour pc;
793    
794            if (g_compatible_arch)
795            {
796                    /* *INDENT-OFF* */
797                    REPEAT4
798                    (
799                            pixel = *(data++);
800                            SPLITCOLOUR16(pixel, pc);
801                            *(out++) = pc.blue;
802                            *(out++) = pc.green;
803                            *(out++) = pc.red;
804                            *(out++) = 0;
805                    )
806                    /* *INDENT-ON* */
807            }
808            else if (g_xserver_be)
809            {
810                    if (g_host_be)
811                    {
812                            while (out < end)
813                            {
814                                    pixel = *(data++);
815                                    BSWAP16(pixel);
816                                    SPLITCOLOUR16(pixel, pc);
817                                    value = MAKECOLOUR(pc);
818                                    BOUT32(out, value);
819                            }
820                    }
821                    else
822                    {
823                            while (out < end)
824                            {
825                                    pixel = *(data++);
826                                    SPLITCOLOUR16(pixel, pc);
827                                    value = MAKECOLOUR(pc);
828                                    BOUT32(out, value);
829                            }
830                    }
831            }
832            else
833            {
834                    if (g_host_be)
835                    {
836                            while (out < end)
837                            {
838                                    pixel = *(data++);
839                                    BSWAP16(pixel);
840                                    SPLITCOLOUR16(pixel, pc);
841                                    value = MAKECOLOUR(pc);
842                                    LOUT32(out, value);
843                            }
844                    }
845                    else
846                    {
847                            while (out < end)
848                            {
849                                    pixel = *(data++);
850                                    SPLITCOLOUR16(pixel, pc);
851                                    value = MAKECOLOUR(pc);
852                                    LOUT32(out, value);
853                            }
854                    }
855            }
856  }  }
857    
858  static void  static void
859  translate24to16(uint8 * data, uint16 * out, uint16 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
860  {  {
861          uint32 pixel = 0;          uint32 pixel = 0;
862            uint16 value;
863            PixelColour pc;
864    
865          while (out < end)          while (out < end)
866          {          {
867                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
868                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
869                  pixel |= *(data++);                  pixel |= *(data++);
870                  *(out++) = (uint16) make_colour16(split_colour24(pixel));                  SPLITCOLOUR24(pixel, pc);
871                    value = MAKECOLOUR(pc);
872                    if (g_xserver_be)
873                    {
874                            BOUT16(out, value);
875                    }
876                    else
877                    {
878                            LOUT16(out, value);
879                    }
880          }          }
881  }  }
882    
883  static void  static void
884  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
885  {  {
886          while (out < end)          uint32 pixel;
887            uint32 value;
888            PixelColour pc;
889    
890            if (g_xserver_be)
891            {
892                    while (out < end)
893                    {
894                            pixel = *(data++) << 16;
895                            pixel |= *(data++) << 8;
896                            pixel |= *(data++);
897                            SPLITCOLOUR24(pixel, pc);
898                            value = MAKECOLOUR(pc);
899                            BOUT24(out, value);
900                    }
901            }
902            else
903          {          {
904                  *(out++) = (*(data++));                  while (out < end)
905                    {
906                            pixel = *(data++) << 16;
907                            pixel |= *(data++) << 8;
908                            pixel |= *(data++);
909                            SPLITCOLOUR24(pixel, pc);
910                            value = MAKECOLOUR(pc);
911                            LOUT24(out, value);
912                    }
913          }          }
914  }  }
915    
916  static void  static void
917  translate24to32(uint8 * data, uint32 * out, uint32 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
918  {  {
919          uint32 pixel = 0;          uint32 pixel;
920          while (out < end)          uint32 value;
921            PixelColour pc;
922    
923            if (g_compatible_arch)
924          {          {
925                  pixel = *(data++);                  /* *INDENT-OFF* */
926                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
927                  pixel |= *(data++) << 16;                  REPEAT4
928                  *(out++) = pixel;                  (
929                            *(out++) = *(data++);
930                            *(out++) = *(data++);
931                            *(out++) = *(data++);
932                            *(out++) = 0;
933                    )
934    #else
935                    REPEAT4
936                    (
937                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
938                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
939                     out += 4;
940                     data += 3;
941                    )
942    #endif
943                    /* *INDENT-ON* */
944            }
945            else if (g_xserver_be)
946            {
947                    while (out < end)
948                    {
949                            pixel = *(data++) << 16;
950                            pixel |= *(data++) << 8;
951                            pixel |= *(data++);
952                            SPLITCOLOUR24(pixel, pc);
953                            value = MAKECOLOUR(pc);
954                            BOUT32(out, value);
955                    }
956            }
957            else
958            {
959                    while (out < end)
960                    {
961                            pixel = *(data++) << 16;
962                            pixel |= *(data++) << 8;
963                            pixel |= *(data++);
964                            SPLITCOLOUR24(pixel, pc);
965                            value = MAKECOLOUR(pc);
966                            LOUT32(out, value);
967                    }
968          }          }
969  }  }
970    
971  static uint8 *  static uint8 *
972  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
973  {  {
974          int size = width * height * bpp / 8;          int size;
975          uint8 *out = (uint8 *) xmalloc(size);          uint8 *out;
976          uint8 *end = out + size;          uint8 *end;
977    
978            /*
979               If RDP depth and X Visual depths match,
980               and arch(endian) matches, no need to translate:
981               just return data.
982               Note: select_visual should've already ensured g_no_translate
983               is only set for compatible depths, but the RDP depth might've
984               changed during connection negotiations.
985             */
986            if (g_no_translate_image)
987            {
988                    if ((g_depth == 15 && g_server_depth == 15) ||
989                        (g_depth == 16 && g_server_depth == 16) ||
990                        (g_depth == 24 && g_server_depth == 24))
991                            return data;
992            }
993    
994            size = width * height * (g_bpp / 8);
995            out = (uint8 *) xmalloc(size);
996            end = out + size;
997    
998          switch (server_bpp)          switch (g_server_depth)
999          {          {
1000                  case 24:                  case 24:
1001                          switch (bpp)                          switch (g_bpp)
1002                          {                          {
1003                                  case 32:                                  case 32:
1004                                          translate24to32(data, (uint32 *) out, (uint32 *) end);                                          translate24to32(data, out, end);
1005                                          break;                                          break;
1006                                  case 24:                                  case 24:
1007                                          translate24to24(data, out, end);                                          translate24to24(data, out, end);
1008                                          break;                                          break;
1009                                  case 16:                                  case 16:
1010                                          translate24to16(data, (uint16 *) out, (uint16 *) end);                                          translate24to16(data, out, end);
1011                                          break;                                          break;
1012                          }                          }
1013                          break;                          break;
1014                  case 16:                  case 16:
1015                          switch (bpp)                          switch (g_bpp)
1016                          {                          {
1017                                  case 32:                                  case 32:
1018                                          translate16to32((uint16 *) data, (uint32 *) out,                                          translate16to32((uint16 *) data, out, end);
                                                         (uint32 *) end);  
1019                                          break;                                          break;
1020                                  case 24:                                  case 24:
1021                                          translate16to24((uint16 *) data, out, end);                                          translate16to24((uint16 *) data, out, end);
1022                                          break;                                          break;
1023                                  case 16:                                  case 16:
1024                                          translate16to16((uint16 *) data, (uint16 *) out,                                          translate16to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
1025                                          break;                                          break;
1026                          }                          }
1027                          break;                          break;
1028                  case 15:                  case 15:
1029                          switch (bpp)                          switch (g_bpp)
1030                          {                          {
1031                                  case 32:                                  case 32:
1032                                          translate15to32((uint16 *) data, (uint32 *) out,                                          translate15to32((uint16 *) data, out, end);
                                                         (uint32 *) end);  
1033                                          break;                                          break;
1034                                  case 24:                                  case 24:
1035                                          translate15to24((uint16 *) data, out, end);                                          translate15to24((uint16 *) data, out, end);
1036                                          break;                                          break;
1037                                  case 16:                                  case 16:
1038                                          translate15to16((uint16 *) data, (uint16 *) out,                                          translate15to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
1039                                          break;                                          break;
1040                          }                          }
1041                          break;                          break;
1042                  case 8:                  case 8:
1043                          switch (bpp)                          switch (g_bpp)
1044                          {                          {
1045                                  case 8:                                  case 8:
1046                                          translate8to8(data, out, end);                                          translate8to8(data, out, end);
1047                                          break;                                          break;
1048                                  case 16:                                  case 16:
1049                                          translate8to16(data, (uint16 *) out, (uint16 *) end);                                          translate8to16(data, out, end);
1050                                          break;                                          break;
1051                                  case 24:                                  case 24:
1052                                          translate8to24(data, out, end);                                          translate8to24(data, out, end);
1053                                          break;                                          break;
1054                                  case 32:                                  case 32:
1055                                          translate8to32(data, (uint32 *) out, (uint32 *) end);                                          translate8to32(data, out, end);
1056                                          break;                                          break;
1057                          }                          }
1058                          break;                          break;
# Line 494  get_key_state(unsigned int state, uint32 Line 1066  get_key_state(unsigned int state, uint32
1066          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
1067          int offset;          int offset;
1068    
1069          KeyCode keycode = XKeysymToKeycode(display, keysym);          KeyCode keycode = XKeysymToKeycode(g_display, keysym);
1070    
1071          if (keycode == NoSymbol)          if (keycode == NoSymbol)
1072                  return False;                  return False;
1073    
1074          for (modifierpos = 0; modifierpos < 8; modifierpos++)          for (modifierpos = 0; modifierpos < 8; modifierpos++)
1075          {          {
1076                  offset = mod_map->max_keypermod * modifierpos;                  offset = g_mod_map->max_keypermod * modifierpos;
1077    
1078                  for (key = 0; key < mod_map->max_keypermod; key++)                  for (key = 0; key < g_mod_map->max_keypermod; key++)
1079                  {                  {
1080                          if (mod_map->modifiermap[offset + key] == keycode)                          if (g_mod_map->modifiermap[offset + key] == keycode)
1081                                  keysymMask |= 1 << modifierpos;                                  keysymMask |= 1 << modifierpos;
1082                  }                  }
1083          }          }
# Line 513  get_key_state(unsigned int state, uint32 Line 1085  get_key_state(unsigned int state, uint32
1085          return (state & keysymMask) ? True : False;          return (state & keysymMask) ? True : False;
1086  }  }
1087    
1088  BOOL  static void
1089  ui_init(void)  calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
1090    {
1091            *shift_l = ffs(mask) - 1;
1092            mask >>= *shift_l;
1093            *shift_r = 8 - ffs(mask & ~(mask >> 1));
1094    }
1095    
1096    /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1097       calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1098     */
1099    static unsigned
1100    calculate_mask_weight(uint32 mask)
1101    {
1102            unsigned weight = 0;
1103            do
1104            {
1105                    weight += (mask & 1);
1106            }
1107            while (mask >>= 1);
1108            return weight;
1109    }
1110    
1111    static BOOL
1112    select_visual()
1113  {  {
1114          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1115          uint16 test;          int pixmap_formats_count, visuals_count;
1116            XVisualInfo *vmatches = NULL;
1117            XVisualInfo template;
1118          int i;          int i;
1119            unsigned red_weight, blue_weight, green_weight;
1120    
1121          display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1122          if (display == NULL)  
1123            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1124            if (pfm == NULL)
1125          {          {
1126                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1127                    XCloseDisplay(g_display);
1128                  return False;                  return False;
1129          }          }
1130    
1131          x_socket = ConnectionNumber(display);          /* Search for best TrueColor visual */
1132          screen = DefaultScreenOfDisplay(display);          template.class = TrueColor;
1133          visual = DefaultVisualOfScreen(screen);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1134          depth = DefaultDepthOfScreen(screen);          g_visual = NULL;
1135            g_no_translate_image = False;
1136            g_compatible_arch = False;
1137            if (vmatches != NULL)
1138            {
1139                    for (i = 0; i < visuals_count; ++i)
1140                    {
1141                            XVisualInfo *visual_info = &vmatches[i];
1142    
1143                            /* Try to find a no-translation visual that'll
1144                               allow us to use RDP bitmaps directly as ZPixmaps. */
1145                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1146                                                   /* R5G5B5 */
1147                                                   (visual_info->red_mask == 0x7c00) &&
1148                                                   (visual_info->green_mask == 0x3e0) &&
1149                                                   (visual_info->blue_mask == 0x1f)) ||
1150                                                  ((visual_info->depth == 16) &&
1151                                                   /* R5G6B5 */
1152                                                   (visual_info->red_mask == 0xf800) &&
1153                                                   (visual_info->green_mask == 0x7e0) &&
1154                                                   (visual_info->blue_mask == 0x1f)) ||
1155                                                  ((visual_info->depth == 24) &&
1156                                                   /* R8G8B8 */
1157                                                   (visual_info->red_mask == 0xff0000) &&
1158                                                   (visual_info->green_mask == 0xff00) &&
1159                                                   (visual_info->blue_mask == 0xff))))
1160                            {
1161                                    g_visual = visual_info->visual;
1162                                    g_depth = visual_info->depth;
1163                                    g_compatible_arch = !g_host_be;
1164                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1165                                    if (g_no_translate_image)
1166                                            /* We found the best visual */
1167                                            break;
1168                            }
1169                            else
1170                            {
1171                                    g_compatible_arch = False;
1172                            }
1173    
1174                            if (visual_info->depth > 24)
1175                            {
1176                                    /* Avoid 32-bit visuals and likes like the plague.
1177                                       They're either untested or proven to work bad
1178                                       (e.g. nvidia's Composite 32-bit visual).
1179                                       Most implementation offer a 24-bit visual anyway. */
1180                                    continue;
1181                            }
1182    
1183                            /* Only care for visuals, for whose BPPs (not depths!)
1184                               we have a translateXtoY function. */
1185                            BOOL can_translate_to_bpp = False;
1186                            int j;
1187                            for (j = 0; j < pixmap_formats_count; ++j)
1188                            {
1189                                    if (pfm[j].depth == visual_info->depth)
1190                                    {
1191                                            if ((pfm[j].bits_per_pixel == 16) ||
1192                                                (pfm[j].bits_per_pixel == 24) ||
1193                                                (pfm[j].bits_per_pixel == 32))
1194                                            {
1195                                                    can_translate_to_bpp = True;
1196                                            }
1197                                            break;
1198                                    }
1199                            }
1200    
1201                            /* Prefer formats which have the most colour depth.
1202                               We're being truly aristocratic here, minding each
1203                               weight on its own. */
1204                            if (can_translate_to_bpp)
1205                            {
1206                                    unsigned vis_red_weight =
1207                                            calculate_mask_weight(visual_info->red_mask);
1208                                    unsigned vis_green_weight =
1209                                            calculate_mask_weight(visual_info->green_mask);
1210                                    unsigned vis_blue_weight =
1211                                            calculate_mask_weight(visual_info->blue_mask);
1212                                    if ((vis_red_weight >= red_weight)
1213                                        && (vis_green_weight >= green_weight)
1214                                        && (vis_blue_weight >= blue_weight))
1215                                    {
1216                                            red_weight = vis_red_weight;
1217                                            green_weight = vis_green_weight;
1218                                            blue_weight = vis_blue_weight;
1219                                            g_visual = visual_info->visual;
1220                                            g_depth = visual_info->depth;
1221                                    }
1222                            }
1223                    }
1224                    XFree(vmatches);
1225            }
1226    
1227            if (g_visual != NULL)
1228            {
1229                    g_owncolmap = False;
1230                    calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1231                    calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1232                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1233            }
1234            else
1235            {
1236                    template.class = PseudoColor;
1237                    template.depth = 8;
1238                    template.colormap_size = 256;
1239                    vmatches =
1240                            XGetVisualInfo(g_display,
1241                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1242                                           &template, &visuals_count);
1243                    if (vmatches == NULL)
1244                    {
1245                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1246                            XCloseDisplay(g_display);
1247                            XFree(pfm);
1248                            return False;
1249                    }
1250    
1251          pfm = XListPixmapFormats(display, &i);                  /* we use a colourmap, so the default visual should do */
1252          if (pfm != NULL)                  g_owncolmap = True;
1253                    g_visual = vmatches[0].visual;
1254                    g_depth = vmatches[0].depth;
1255            }
1256    
1257            g_bpp = 0;
1258            for (i = 0; i < pixmap_formats_count; ++i)
1259          {          {
1260                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1261                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1262                  {                  {
1263                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))                          g_bpp = pf->bits_per_pixel;
1264    
1265                            if (g_no_translate_image)
1266                          {                          {
1267                                  bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1268                                    {
1269                                            case 15:
1270                                            case 16:
1271                                                    if (g_bpp != 16)
1272                                                            g_no_translate_image = False;
1273                                                    break;
1274                                            case 24:
1275                                                    /* Yes, this will force image translation
1276                                                       on most modern servers which use 32 bits
1277                                                       for R8G8B8. */
1278                                                    if (g_bpp != 24)
1279                                                            g_no_translate_image = False;
1280                                                    break;
1281                                            default:
1282                                                    g_no_translate_image = False;
1283                                                    break;
1284                                    }
1285                          }                          }
1286    
1287                            /* Pixmap formats list is a depth-to-bpp mapping --
1288                               there's just a single entry for every depth,
1289                               so we can safely break here */
1290                            break;
1291                  }                  }
1292                  XFree(pfm);          }
1293            XFree(pfm);
1294            pfm = NULL;
1295            return True;
1296    }
1297    
1298    BOOL
1299    ui_init(void)
1300    {
1301            int screen_num;
1302    
1303            g_display = XOpenDisplay(NULL);
1304            if (g_display == NULL)
1305            {
1306                    error("Failed to open display: %s\n", XDisplayName(NULL));
1307                    return False;
1308          }          }
1309    
         if (bpp < 8)  
1310          {          {
1311                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1312                  XCloseDisplay(display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1313            }
1314    
1315            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1316            screen_num = DefaultScreen(g_display);
1317            g_x_socket = ConnectionNumber(g_display);
1318            g_screen = ScreenOfDisplay(g_display, screen_num);
1319            g_depth = DefaultDepthOfScreen(g_screen);
1320    
1321            if (!select_visual())
1322                  return False;                  return False;
1323    
1324            if (g_no_translate_image)
1325            {
1326                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1327          }          }
1328    
1329          if (owncolmap != True)          if (g_server_depth > g_bpp)
1330          {          {
1331                  xcolmap = DefaultColormapOfScreen(screen);                  warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1332                  if (depth <= 8)                          g_server_depth, g_bpp);
                         warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");  
1333          }          }
1334    
1335          gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);          DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1336                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1337    
1338          if (DoesBackingStore(screen) != Always)          if (!g_owncolmap)
1339                  ownbackstore = True;          {
1340                    g_xcolmap =
1341                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1342                                            AllocNone);
1343                    if (g_depth <= 8)
1344                            warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1345            }
1346    
1347          test = 1;          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1348          host_be = !(BOOL) (*(uint8 *) (&test));          {
1349          xserver_be = (ImageByteOrder(display) == MSBFirst);                  warning("External BackingStore not available. Using internal.\n");
1350                    g_ownbackstore = True;
1351            }
1352    
1353          if ((width == 0) || (height == 0))          /*
1354             * Determine desktop size
1355             */
1356            if (g_fullscreen)
1357            {
1358                    g_width = WidthOfScreen(g_screen);
1359                    g_height = HeightOfScreen(g_screen);
1360                    g_using_full_workarea = True;
1361            }
1362            else if (g_width < 0)
1363            {
1364                    /* Percent of screen */
1365                    if (-g_width >= 100)
1366                            g_using_full_workarea = True;
1367                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1368                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1369            }
1370            else if (g_width == 0)
1371          {          {
1372                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1373                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1374                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1375                  {                  {
1376                          width = cx;                          g_width = cx;
1377                          height = cy;                          g_height = cy;
1378                            g_using_full_workarea = True;
1379                  }                  }
1380                  else                  else
1381                  {                  {
1382                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1383                          width = 800;                          g_width = WidthOfScreen(g_screen);
1384                          height = 600;                          g_height = HeightOfScreen(g_screen);
1385                  }                  }
1386          }          }
1387    
         if (fullscreen)  
         {  
                 width = WidthOfScreen(screen);  
                 height = HeightOfScreen(screen);  
         }  
   
1388          /* make sure width is a multiple of 4 */          /* make sure width is a multiple of 4 */
1389          width = (width + 3) & ~3;          g_width = (g_width + 3) & ~3;
   
         if (ownbackstore)  
         {  
                 backstore =  
                         XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);  
1390    
1391                  /* clear to prevent rubbish being exposed at startup */          g_mod_map = XGetModifierMapping(g_display);
                 XSetForeground(display, gc, BlackPixelOfScreen(screen));  
                 XFillRectangle(display, backstore, gc, 0, 0, width, height);  
         }  
1392    
1393          mod_map = XGetModifierMapping(display);          xkeymap_init();
1394    
1395          if (enable_compose)          if (g_enable_compose)
1396                  IM = XOpenIM(display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1397    
         xkeymap_init();  
1398          xclip_init();          xclip_init();
1399            if (g_seamless_rdp)
1400                    seamless_init();
1401    
1402          /* 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", server_bpp, bpp, depth);  
1403    
1404          return True;          return True;
1405  }  }
# Line 624  ui_init(void) Line 1407  ui_init(void)
1407  void  void
1408  ui_deinit(void)  ui_deinit(void)
1409  {  {
1410          if (IM != NULL)          if (g_IM != NULL)
1411                  XCloseIM(IM);                  XCloseIM(g_IM);
1412    
1413            if (g_null_cursor != NULL)
1414                    ui_destroy_cursor(g_null_cursor);
1415    
1416          XFreeModifiermap(mod_map);          XFreeModifiermap(g_mod_map);
1417    
1418          if (ownbackstore)          if (g_ownbackstore)
1419                  XFreePixmap(display, backstore);                  XFreePixmap(g_display, g_backstore);
1420    
1421          XFreeGC(display, gc);          XFreeGC(g_display, g_gc);
1422          XCloseDisplay(display);          XCloseDisplay(g_display);
1423          display = NULL;          g_display = NULL;
1424    }
1425    
1426    
1427    static void
1428    get_window_attribs(XSetWindowAttributes * attribs)
1429    {
1430            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1431            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1432            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1433            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1434            attribs->override_redirect = g_fullscreen;
1435            attribs->colormap = g_xcolmap;
1436    }
1437    
1438    static void
1439    get_input_mask(long *input_mask)
1440    {
1441            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1442                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1443    
1444            if (g_sendmotion)
1445                    *input_mask |= PointerMotionMask;
1446            if (g_ownbackstore)
1447                    *input_mask |= ExposureMask;
1448            if (g_fullscreen || g_grab_keyboard)
1449                    *input_mask |= EnterWindowMask;
1450            if (g_grab_keyboard)
1451                    *input_mask |= LeaveWindowMask;
1452  }  }
1453    
1454  BOOL  BOOL
1455  ui_create_window(void)  ui_create_window(void)
1456  {  {
1457            uint8 null_pointer_mask[1] = { 0x80 };
1458            uint8 null_pointer_data[24] = { 0x00 };
1459    
1460          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1461          XClassHint *classhints;          XClassHint *classhints;
1462          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 647  ui_create_window(void) Line 1464  ui_create_window(void)
1464          long input_mask, ic_input_mask;          long input_mask, ic_input_mask;
1465          XEvent xevent;          XEvent xevent;
1466    
1467          wndwidth = fullscreen ? WidthOfScreen(screen) : width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1468          wndheight = fullscreen ? HeightOfScreen(screen) : height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1469    
1470            /* Handle -x-y portion of geometry string */
1471            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1472                    g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1473            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1474                    g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1475    
1476            get_window_attribs(&attribs);
1477    
1478            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1479                                  wndheight, 0, g_depth, InputOutput, g_visual,
1480                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1481                                  CWBorderPixel, &attribs);
1482    
1483          attribs.background_pixel = BlackPixelOfScreen(screen);          if (g_gc == NULL)
1484          attribs.backing_store = ownbackstore ? NotUseful : Always;          {
1485          attribs.override_redirect = fullscreen;                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1486                    ui_reset_clip();
1487            }
1488    
1489            if (g_create_bitmap_gc == NULL)
1490                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1491    
1492          wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,          if ((g_ownbackstore) && (g_backstore == 0))
1493                              0, CopyFromParent, InputOutput, CopyFromParent,          {
1494                              CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);                  g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1495    
1496                    /* clear to prevent rubbish being exposed at startup */
1497                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1498                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1499            }
1500    
1501          XStoreName(display, wnd, title);          XStoreName(g_display, g_wnd, g_title);
1502    
1503          if (hide_decorations)          if (g_hide_decorations)
1504                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1505    
1506          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1507          if (classhints != NULL)          if (classhints != NULL)
1508          {          {
1509                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
1510                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
1511                  XFree(classhints);                  XFree(classhints);
1512          }          }
1513    
# Line 675  ui_create_window(void) Line 1515  ui_create_window(void)
1515          if (sizehints)          if (sizehints)
1516          {          {
1517                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1518                  sizehints->min_width = sizehints->max_width = width;                  if (g_pos)
1519                  sizehints->min_height = sizehints->max_height = height;                          sizehints->flags |= PPosition;
1520                  XSetWMNormalHints(display, wnd, sizehints);                  sizehints->min_width = sizehints->max_width = g_width;
1521                    sizehints->min_height = sizehints->max_height = g_height;
1522                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1523                  XFree(sizehints);                  XFree(sizehints);
1524          }          }
1525    
1526          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          if (g_embed_wnd)
1527                  VisibilityChangeMask | FocusChangeMask;          {
1528                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1529            }
1530    
1531          if (sendmotion)          get_input_mask(&input_mask);
                 input_mask |= PointerMotionMask;  
         if (ownbackstore)  
                 input_mask |= ExposureMask;  
         if (fullscreen || grab_keyboard)  
                 input_mask |= EnterWindowMask;  
         if (grab_keyboard)  
                 input_mask |= LeaveWindowMask;  
1532    
1533          if (IM != NULL)          if (g_IM != NULL)
1534          {          {
1535                  IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),                  g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1536                                 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);                                   XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1537    
1538                  if ((IC != NULL)                  if ((g_IC != NULL)
1539                      && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1540                          input_mask |= ic_input_mask;                          input_mask |= ic_input_mask;
1541          }          }
1542    
1543          XSelectInput(display, wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1544          XMapWindow(display, wnd);          if (!g_seamless_rdp)
   
         /* wait for VisibilityNotify */  
         do  
1545          {          {
1546                  XMaskEvent(display, VisibilityChangeMask, &xevent);                  XMapWindow(g_display, g_wnd);
1547                    /* wait for VisibilityNotify */
1548                    do
1549                    {
1550                            XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1551                    }
1552                    while (xevent.type != VisibilityNotify);
1553                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1554          }          }
         while (xevent.type != VisibilityNotify);  
1555    
1556          focused = False;          g_focused = False;
1557          mouse_in_wnd = False;          g_mouse_in_wnd = False;
1558    
1559          /* handle the WM_DELETE_WINDOW protocol */          /* handle the WM_DELETE_WINDOW protocol */
1560          protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);          g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1561          kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);          g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1562          XSetWMProtocols(display, wnd, &kill_atom, 1);          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1563    
1564            /* create invisible 1x1 cursor to be used as null cursor */
1565            if (g_null_cursor == NULL)
1566                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1567    
1568          return True;          return True;
1569  }  }
1570    
1571  void  void
1572    ui_resize_window()
1573    {
1574            XSizeHints *sizehints;
1575            Pixmap bs;
1576    
1577            sizehints = XAllocSizeHints();
1578            if (sizehints)
1579            {
1580                    sizehints->flags = PMinSize | PMaxSize;
1581                    sizehints->min_width = sizehints->max_width = g_width;
1582                    sizehints->min_height = sizehints->max_height = g_height;
1583                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1584                    XFree(sizehints);
1585            }
1586    
1587            if (!(g_fullscreen || g_embed_wnd))
1588            {
1589                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1590            }
1591    
1592            /* create new backstore pixmap */
1593            if (g_backstore != 0)
1594            {
1595                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1596                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1597                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1598                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1599                    XFreePixmap(g_display, g_backstore);
1600                    g_backstore = bs;
1601            }
1602    }
1603    
1604    void
1605  ui_destroy_window(void)  ui_destroy_window(void)
1606  {  {
1607          if (IC != NULL)          if (g_IC != NULL)
1608                  XDestroyIC(IC);                  XDestroyIC(g_IC);
1609    
1610          XDestroyWindow(display, wnd);          XDestroyWindow(g_display, g_wnd);
1611  }  }
1612    
1613  void  void
# Line 738  xwin_toggle_fullscreen(void) Line 1615  xwin_toggle_fullscreen(void)
1615  {  {
1616          Pixmap contents = 0;          Pixmap contents = 0;
1617    
1618          if (!ownbackstore)          if (g_seamless_rdp)
1619                    /* Turn off SeamlessRDP mode */
1620                    ui_seamless_toggle();
1621    
1622            if (!g_ownbackstore)
1623          {          {
1624                  /* need to save contents of window */                  /* need to save contents of window */
1625                  contents = XCreatePixmap(display, wnd, width, height, depth);                  contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1626                  XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);                  XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1627          }          }
1628    
1629          ui_destroy_window();          ui_destroy_window();
1630          fullscreen = !fullscreen;          g_fullscreen = !g_fullscreen;
1631          ui_create_window();          ui_create_window();
1632    
1633          XDefineCursor(display, wnd, current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
1634    
1635            if (!g_ownbackstore)
1636            {
1637                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1638                    XFreePixmap(g_display, contents);
1639            }
1640    }
1641    
1642    static void
1643    handle_button_event(XEvent xevent, BOOL down)
1644    {
1645            uint16 button, flags = 0;
1646            g_last_gesturetime = xevent.xbutton.time;
1647            button = xkeymap_translate_button(xevent.xbutton.button);
1648            if (button == 0)
1649                    return;
1650    
1651            if (down)
1652                    flags = MOUSE_FLAG_DOWN;
1653    
1654            /* Stop moving window when button is released, regardless of cursor position */
1655            if (g_moving_wnd && (xevent.type == ButtonRelease))
1656                    g_moving_wnd = False;
1657    
1658          if (!ownbackstore)          /* If win_button_size is nonzero, enable single app mode */
1659            if (xevent.xbutton.y < g_win_button_size)
1660          {          {
1661                  XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);                  /*  Check from right to left: */
1662                  XFreePixmap(display, contents);                  if (xevent.xbutton.x >= g_width - g_win_button_size)
1663                    {
1664                            /* The close button, continue */
1665                            ;
1666                    }
1667                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1668                    {
1669                            /* The maximize/restore button. Do not send to
1670                               server.  It might be a good idea to change the
1671                               cursor or give some other visible indication
1672                               that rdesktop inhibited this click */
1673                            if (xevent.type == ButtonPress)
1674                                    return;
1675                    }
1676                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1677                    {
1678                            /* The minimize button. Iconify window. */
1679                            if (xevent.type == ButtonRelease)
1680                            {
1681                                    /* Release the mouse button outside the minimize button, to prevent the
1682                                       actual minimazation to happen */
1683                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1684                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1685                                    return;
1686                            }
1687                    }
1688                    else if (xevent.xbutton.x <= g_win_button_size)
1689                    {
1690                            /* The system menu. Ignore. */
1691                            if (xevent.type == ButtonPress)
1692                                    return;
1693                    }
1694                    else
1695                    {
1696                            /* The title bar. */
1697                            if (xevent.type == ButtonPress)
1698                            {
1699                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1700                                    {
1701                                            g_moving_wnd = True;
1702                                            g_move_x_offset = xevent.xbutton.x;
1703                                            g_move_y_offset = xevent.xbutton.y;
1704                                    }
1705                                    return;
1706                            }
1707                    }
1708            }
1709    
1710            if (xevent.xmotion.window == g_wnd)
1711            {
1712                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1713                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1714            }
1715            else
1716            {
1717                    /* SeamlessRDP */
1718                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1719                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1720          }          }
1721  }  }
1722    
1723  /* Process all events in Xlib queue  /* Process events in Xlib queue
1724     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1725  static int  static int
1726  xwin_process_events(void)  xwin_process_events(void)
1727  {  {
1728          XEvent xevent;          XEvent xevent;
1729          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1730          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1731          char str[256];          char str[256];
1732          Status status;          Status status;
1733          unsigned int state;          int events = 0;
1734          Window wdummy;          seamless_window *sw;
         int dummy;  
1735    
1736          while (XPending(display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1737          {          {
1738                  XNextEvent(display, &xevent);                  XNextEvent(g_display, &xevent);
1739    
1740                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1741                  {                  {
1742                          DEBUG_KBD(("Filtering event\n"));                          DEBUG_KBD(("Filtering event\n"));
1743                          continue;                          continue;
1744                  }                  }
1745    
                 flags = 0;  
   
1746                  switch (xevent.type)                  switch (xevent.type)
1747                  {                  {
1748                            case VisibilityNotify:
1749                                    if (xevent.xvisibility.window == g_wnd)
1750                                            g_Unobscured =
1751                                                    xevent.xvisibility.state == VisibilityUnobscured;
1752    
1753                                    break;
1754                          case ClientMessage:                          case ClientMessage:
1755                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1756                                  if ((xevent.xclient.message_type == protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
1757                                      && ((Atom) xevent.xclient.data.l[0] == kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1758                                          /* Quit */                                          /* Quit */
1759                                          return 0;                                          return 0;
1760                                  break;                                  break;
1761    
1762                          case KeyPress:                          case KeyPress:
1763                                  last_gesturetime = xevent.xkey.time;                                  g_last_gesturetime = xevent.xkey.time;
1764                                  if (IC != NULL)                                  if (g_IC != NULL)
1765                                          /* Multi_key compatible version */                                          /* Multi_key compatible version */
1766                                  {                                  {
1767                                          XmbLookupString(IC,                                          XmbLookupString(g_IC,
1768                                                          &xevent.xkey, str, sizeof(str), &keysym, &status);                                                          &xevent.xkey, str, sizeof(str), &keysym,
1769                                                            &status);
1770                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1771                                          {                                          {
1772                                                  error("XmbLookupString failed with status 0x%x\n",                                                  error("XmbLookupString failed with status 0x%x\n",
# Line 818  xwin_process_events(void) Line 1782  xwin_process_events(void)
1782                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1783                                  }                                  }
1784    
1785                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1786                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1787    
1788                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1789                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1790                                          break;                                          break;
1791    
1792                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1793                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, True, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 ensure_remote_modifiers(ev_time, tr);  
   
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);  
1794                                  break;                                  break;
1795    
1796                          case KeyRelease:                          case KeyRelease:
1797                                  last_gesturetime = xevent.xkey.time;                                  g_last_gesturetime = xevent.xkey.time;
1798                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1799                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1800    
1801                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1802                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1803    
1804                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1805                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1806                                          break;                                          break;
1807    
1808                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1809                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1810                                  break;                                  break;
1811    
1812                          case ButtonPress:                          case ButtonPress:
1813                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1814                                  /* fall through */                                  break;
1815    
1816                          case ButtonRelease:                          case ButtonRelease:
1817                                  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 < win_button_size)  
                                 {  
                                         /* Stop moving window when button is released, regardless of cursor position */  
                                         if (moving_wnd && (xevent.type == ButtonRelease))  
                                                 moving_wnd = False;  
   
                                         /*  Check from right to left: */  
   
                                         if (xevent.xbutton.x >= width - win_button_size)  
                                         {  
                                                 /* The close button, continue */  
                                                 ;  
                                         }  
                                         else if (xevent.xbutton.x >= width - 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 >= width - win_button_size * 3)  
                                         {  
                                                 /* The minimize button. Iconify window. */  
                                                 XIconifyWindow(display, wnd,  
                                                                DefaultScreen(display));  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x <= win_button_size)  
                                         {  
                                                 /* The system menu. Ignore. */  
                                                 break;  
                                         }  
                                         else  
                                         {  
                                                 /* The title bar. */  
                                                 if ((xevent.type == ButtonPress) && !fullscreen  
                                                     && hide_decorations)  
                                                 {  
                                                         moving_wnd = True;  
                                                         move_x_offset = xevent.xbutton.x;  
                                                         move_y_offset = xevent.xbutton.y;  
                                                 }  
                                                 break;  
   
                                         }  
                                 }  
   
                                 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
                                                flags | button, xevent.xbutton.x, xevent.xbutton.y);  
1818                                  break;                                  break;
1819    
1820                          case MotionNotify:                          case MotionNotify:
1821                                  if (moving_wnd)                                  if (g_moving_wnd)
1822                                  {                                  {
1823                                          XMoveWindow(display, wnd,                                          XMoveWindow(g_display, g_wnd,
1824                                                      xevent.xmotion.x_root - move_x_offset,                                                      xevent.xmotion.x_root - g_move_x_offset,
1825                                                      xevent.xmotion.y_root - move_y_offset);                                                      xevent.xmotion.y_root - g_move_y_offset);
1826                                          break;                                          break;
1827                                  }                                  }
1828    
1829                                  if (fullscreen && !focused)                                  if (g_fullscreen && !g_focused)
1830                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1831                                                         CurrentTime);                                                         CurrentTime);
1832                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1833                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1834                                    {
1835                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1836                                                           xevent.xmotion.x, xevent.xmotion.y);
1837                                    }
1838                                    else
1839                                    {
1840                                            /* SeamlessRDP */
1841                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1842                                                           xevent.xmotion.x_root,
1843                                                           xevent.xmotion.y_root);
1844                                    }
1845                                  break;                                  break;
1846    
1847                          case FocusIn:                          case FocusIn:
1848                                  if (xevent.xfocus.mode == NotifyGrab)                                  if (xevent.xfocus.mode == NotifyGrab)
1849                                          break;                                          break;
1850                                  focused = True;                                  g_focused = True;
1851                                  XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,                                  reset_modifier_keys();
1852                                                &dummy, &dummy, &state);                                  if (g_grab_keyboard && g_mouse_in_wnd)
1853                                  reset_modifier_keys(state);                                          XGrabKeyboard(g_display, g_wnd, True,
                                 if (grab_keyboard && mouse_in_wnd)  
                                         XGrabKeyboard(display, wnd, True,  
1854                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1855                                  break;                                  break;
1856    
1857                          case FocusOut:                          case FocusOut:
1858                                  if (xevent.xfocus.mode == NotifyUngrab)                                  if (xevent.xfocus.mode == NotifyUngrab)
1859                                          break;                                          break;
1860                                  focused = False;                                  g_focused = False;
1861                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)
1862                                          XUngrabKeyboard(display, CurrentTime);                                          XUngrabKeyboard(g_display, CurrentTime);
1863                                  break;                                  break;
1864    
1865                          case EnterNotify:                          case EnterNotify:
1866                                  /* we only register for this event when in fullscreen mode */                                  /* we only register for this event when in fullscreen mode */
1867                                  /* or grab_keyboard */                                  /* or grab_keyboard */
1868                                  mouse_in_wnd = True;                                  g_mouse_in_wnd = True;
1869                                  if (fullscreen)                                  if (g_fullscreen)
1870                                  {                                  {
1871                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1872                                                         CurrentTime);                                                         CurrentTime);
1873                                          break;                                          break;
1874                                  }                                  }
1875                                  if (focused)                                  if (g_focused)
1876                                          XGrabKeyboard(display, wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
1877                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1878                                  break;                                  break;
1879    
1880                          case LeaveNotify:                          case LeaveNotify:
1881                                  /* we only register for this event when grab_keyboard */                                  /* we only register for this event when grab_keyboard */
1882                                  mouse_in_wnd = False;                                  g_mouse_in_wnd = False;
1883                                  XUngrabKeyboard(display, CurrentTime);                                  XUngrabKeyboard(g_display, CurrentTime);
1884                                  break;                                  break;
1885    
1886                          case Expose:                          case Expose:
1887                                  XCopyArea(display, backstore, wnd, gc,                                  if (xevent.xexpose.window == g_wnd)
1888                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1889                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1890                                            xevent.xexpose.height,                                                    g_gc,
1891                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1892                                                      xevent.xexpose.width, xevent.xexpose.height,
1893                                                      xevent.xexpose.x, xevent.xexpose.y);
1894                                    }
1895                                    else
1896                                    {
1897                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1898                                            if (sw)
1899                                                    XCopyArea(g_display, g_backstore,
1900                                                              xevent.xexpose.window, g_gc,
1901                                                              xevent.xexpose.x + sw->xoffset,
1902                                                              xevent.xexpose.y + sw->yoffset,
1903                                                              xevent.xexpose.width,
1904                                                              xevent.xexpose.height, xevent.xexpose.x,
1905                                                              xevent.xexpose.y);
1906                                            else
1907                                            {
1908                                                    error("Expose for unknown window 0x%lx\n",
1909                                                          xevent.xexpose.window);
1910                                            }
1911                                    }
1912    
1913                                  break;                                  break;
1914    
1915                          case MappingNotify:                          case MappingNotify:
# Line 994  xwin_process_events(void) Line 1921  xwin_process_events(void)
1921    
1922                                  if (xevent.xmapping.request == MappingModifier)                                  if (xevent.xmapping.request == MappingModifier)
1923                                  {                                  {
1924                                          XFreeModifiermap(mod_map);                                          XFreeModifiermap(g_mod_map);
1925                                          mod_map = XGetModifierMapping(display);                                          g_mod_map = XGetModifierMapping(g_display);
1926                                  }                                  }
1927                                  break;                                  break;
1928    
1929                          /* clipboard stuff */                                  /* clipboard stuff */
1930                          case SelectionNotify:                          case SelectionNotify:
1931                                  xclip_handle_SelectionNotify(&xevent.xselection);                                  xclip_handle_SelectionNotify(&xevent.xselection);
1932                                  break;                                  break;
# Line 1012  xwin_process_events(void) Line 1939  xwin_process_events(void)
1939                          case PropertyNotify:                          case PropertyNotify:
1940                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1941                                  break;                                  break;
1942                            case MapNotify:
1943                                    if (!g_seamless_rdp)
1944                                            rdp_send_client_window_status(1);
1945                                    break;
1946                            case UnmapNotify:
1947                                    if (!g_seamless_rdp)
1948                                            rdp_send_client_window_status(0);
1949                                    break;
1950                  }                  }
1951          }          }
1952          /* Keep going */          /* Keep going */
# Line 1022  xwin_process_events(void) Line 1957  xwin_process_events(void)
1957  int  int
1958  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1959  {  {
1960          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;          int n;
1961          fd_set rfds;          fd_set rfds, wfds;
1962            struct timeval tv;
1963          FD_ZERO(&rfds);          BOOL s_timeout = False;
1964    
1965          while (True)          while (True)
1966          {          {
1967                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1968                  /* Process any events already waiting */                  /* Process any events already waiting */
1969                  if (!xwin_process_events())                  if (!xwin_process_events())
1970                          /* User quit */                          /* User quit */
1971                          return 0;                          return 0;
1972    
1973                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1974                    FD_ZERO(&wfds);
1975                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1976                  FD_SET(x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
1977    
1978    #ifdef WITH_RDPSND
1979                    /* FIXME: there should be an API for registering fds */
1980                    if (g_dsp_busy)
1981                    {
1982                            FD_SET(g_dsp_fd, &wfds);
1983                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
1984                    }
1985    #endif
1986                    /* default timeout */
1987                    tv.tv_sec = 60;
1988                    tv.tv_usec = 0;
1989    
1990                  switch (select(n, &rfds, NULL, NULL, NULL))                  /* add redirection handles */
1991                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1992    
1993                    n++;
1994    
1995                    switch (select(n, &rfds, &wfds, NULL, &tv))
1996                  {                  {
1997                          case -1:                          case -1:
1998                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1999    
2000                          case 0:                          case 0:
2001                                    /* Abort serial read calls */
2002                                    if (s_timeout)
2003                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
2004                                  continue;                                  continue;
2005                  }                  }
2006    
2007                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
2008    
2009                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2010                          return 1;                          return 1;
2011    
2012    #ifdef WITH_RDPSND
2013                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
2014                            wave_out_play();
2015    #endif
2016          }          }
2017  }  }
2018    
2019  void  void
2020  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
2021  {  {
2022          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
2023  }  }
2024    
2025  HBITMAP  HBITMAP
# Line 1064  ui_create_bitmap(int width, int height, Line 2028  ui_create_bitmap(int width, int height,
2028          XImage *image;          XImage *image;
2029          Pixmap bitmap;          Pixmap bitmap;
2030          uint8 *tdata;          uint8 *tdata;
2031            int bitmap_pad;
2032    
2033            if (g_server_depth == 8)
2034            {
2035                    bitmap_pad = 8;
2036            }
2037            else
2038            {
2039                    bitmap_pad = g_bpp;
2040    
2041          tdata = (owncolmap ? data : translate_image(width, height, data));                  if (g_bpp == 24)
2042          bitmap = XCreatePixmap(display, wnd, width, height, depth);                          bitmap_pad = 32;
2043          image = XCreateImage(display, visual, depth, ZPixmap, 0,          }
2044                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);  
2045            tdata = (g_owncolmap ? data : translate_image(width, height, data));
2046            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
2047            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2048                                 (char *) tdata, width, height, bitmap_pad, 0);
2049    
2050          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
2051    
2052          XFree(image);          XFree(image);
2053          if (!owncolmap)          if (tdata != data)
2054                  xfree(tdata);                  xfree(tdata);
2055          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
2056  }  }
# Line 1083  ui_paint_bitmap(int x, int y, int cx, in Line 2060  ui_paint_bitmap(int x, int y, int cx, in
2060  {  {
2061          XImage *image;          XImage *image;
2062          uint8 *tdata;          uint8 *tdata;
2063          tdata = (owncolmap ? data : translate_image(width, height, data));          int bitmap_pad;
         image = XCreateImage(display, visual, depth, ZPixmap, 0,  
                              (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);  
2064    
2065          if (ownbackstore)          if (g_server_depth == 8)
2066          {          {
2067                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  bitmap_pad = 8;
                 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);  
2068          }          }
2069          else          else
2070          {          {
2071                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  bitmap_pad = g_bpp;
2072    
2073                    if (g_bpp == 24)
2074                            bitmap_pad = 32;
2075            }
2076    
2077            tdata = (g_owncolmap ? data : translate_image(width, height, data));
2078            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2079                                 (char *) tdata, width, height, bitmap_pad, 0);
2080    
2081            if (g_ownbackstore)
2082            {
2083                    XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2084                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2085                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2086                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2087                                             x - sw->xoffset, y - sw->yoffset));
2088            }
2089            else
2090            {
2091                    XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2092                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2093                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2094                                             x - sw->xoffset, y - sw->yoffset));
2095          }          }
2096    
2097          XFree(image);          XFree(image);
2098          if (!owncolmap)          if (tdata != data)
2099                  xfree(tdata);                  xfree(tdata);
2100  }  }
2101    
2102  void  void
2103  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
2104  {  {
2105          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2106  }  }
2107    
2108  HGLYPH  HGLYPH
# Line 1114  ui_create_glyph(int width, int height, u Line 2111  ui_create_glyph(int width, int height, u
2111          XImage *image;          XImage *image;
2112          Pixmap bitmap;          Pixmap bitmap;
2113          int scanline;          int scanline;
         GC gc;  
2114    
2115          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
2116    
2117          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
2118          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
2119                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
2120    
2121          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
2122                               width, height, 8, scanline);                               width, height, 8, scanline);
2123          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
2124          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
2125          XInitImage(image);          XInitImage(image);
2126    
2127          XPutImage(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);
2128    
2129          XFree(image);          XFree(image);
         XFreeGC(display, gc);  
2130          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
2131  }  }
2132    
2133  void  void
2134  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
2135  {  {
2136          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2137  }  }
2138    
2139  HCURSOR  HCURSOR
# Line 1201  ui_create_cursor(unsigned int x, unsigne Line 2197  ui_create_cursor(unsigned int x, unsigne
2197          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
2198    
2199          xcursor =          xcursor =
2200                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
2201                                      (Pixmap) maskglyph, &fg, &bg, x, y);                                      (Pixmap) maskglyph, &fg, &bg, x, y);
2202    
2203          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
# Line 1214  ui_create_cursor(unsigned int x, unsigne Line 2210  ui_create_cursor(unsigned int x, unsigne
2210  void  void
2211  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
2212  {  {
2213          current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2214          XDefineCursor(display, wnd, current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2215            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2216  }  }
2217    
2218  void  void
2219  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
2220  {  {
2221          XFreeCursor(display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2222    }
2223    
2224    void
2225    ui_set_null_cursor(void)
2226    {
2227            ui_set_cursor(g_null_cursor);
2228  }  }
2229    
2230  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 1236  ui_create_colourmap(COLOURMAP * colours) Line 2239  ui_create_colourmap(COLOURMAP * colours)
2239  {  {
2240          COLOURENTRY *entry;          COLOURENTRY *entry;
2241          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
2242          if (!owncolmap)          if (!g_owncolmap)
2243          {          {
2244                  uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
2245                  XColor xentry;                  XColor xentry;
2246                  XColor xc_cache[256];                  XColor xc_cache[256];
2247                  uint32 colour;                  uint32 colour;
# Line 1248  ui_create_colourmap(COLOURMAP * colours) Line 2251  ui_create_colourmap(COLOURMAP * colours)
2251                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2252                          MAKE_XCOLOR(&xentry, entry);                          MAKE_XCOLOR(&xentry, entry);
2253    
2254                          if (XAllocColor(display, xcolmap, &xentry) == 0)                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
2255                          {                          {
2256                                  /* Allocation failed, find closest match. */                                  /* Allocation failed, find closest match. */
2257                                  int j = 256;                                  int j = 256;
# Line 1262  ui_create_colourmap(COLOURMAP * colours) Line 2265  ui_create_colourmap(COLOURMAP * colours)
2265                                          xc_cache[colLookup].red = xc_cache[colLookup].green =                                          xc_cache[colLookup].red = xc_cache[colLookup].green =
2266                                                  xc_cache[colLookup].blue = 0;                                                  xc_cache[colLookup].blue = 0;
2267                                          xc_cache[colLookup].flags = 0;                                          xc_cache[colLookup].flags = 0;
2268                                          XQueryColor(display,                                          XQueryColor(g_display,
2269                                                      DefaultColormap(display,                                                      DefaultColormap(g_display,
2270                                                                      DefaultScreen(display)),                                                                      DefaultScreen(g_display)),
2271                                                      &xc_cache[colLookup]);                                                      &xc_cache[colLookup]);
2272                                  }                                  }
2273                                  colLookup = 0;                                  colLookup = 0;
# Line 1305  ui_create_colourmap(COLOURMAP * colours) Line 2308  ui_create_colourmap(COLOURMAP * colours)
2308    
2309                          }                          }
2310    
2311                            map[i] = colour;
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
2312                  }                  }
2313                  return map;                  return map;
2314          }          }
# Line 1325  ui_create_colourmap(COLOURMAP * colours) Line 2326  ui_create_colourmap(COLOURMAP * colours)
2326                          MAKE_XCOLOR(xentry, entry);                          MAKE_XCOLOR(xentry, entry);
2327                  }                  }
2328    
2329                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
2330                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2331    
2332                  xfree(xcolours);                  xfree(xcolours);
2333                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
# Line 1336  ui_create_colourmap(COLOURMAP * colours) Line 2337  ui_create_colourmap(COLOURMAP * colours)
2337  void  void
2338  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
2339  {  {
2340          if (!owncolmap)          if (!g_owncolmap)
2341                  xfree(map);                  xfree(map);
2342          else          else
2343                  XFreeColormap(display, (Colormap) map);                  XFreeColormap(g_display, (Colormap) map);
2344  }  }
2345    
2346  void  void
2347  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
2348  {  {
2349          if (!owncolmap)          if (!g_owncolmap)
2350                  colmap = (uint32 *) map;          {
2351                    if (g_colmap)
2352                            xfree(g_colmap);
2353    
2354                    g_colmap = (uint32 *) map;
2355            }
2356          else          else
2357                  XSetWindowColormap(display, wnd, (Colormap) map);          {
2358                    XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2359                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2360            }
2361  }  }
2362    
2363  void  void
2364  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2365  {  {
2366          XRectangle rect;          g_clip_rectangle.x = x;
2367            g_clip_rectangle.y = y;
2368          rect.x = x;          g_clip_rectangle.width = cx;
2369          rect.y = y;          g_clip_rectangle.height = cy;
2370          rect.width = cx;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = cy;  
         XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);  
2371  }  }
2372    
2373  void  void
2374  ui_reset_clip(void)  ui_reset_clip(void)
2375  {  {
2376          XRectangle rect;          g_clip_rectangle.x = 0;
2377            g_clip_rectangle.y = 0;
2378          rect.x = 0;          g_clip_rectangle.width = g_width;
2379          rect.y = 0;          g_clip_rectangle.height = g_height;
2380          rect.width = width;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = height;  
         XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);  
2381  }  }
2382    
2383  void  void
2384  ui_bell(void)  ui_bell(void)
2385  {  {
2386          XBell(display, 0);          XBell(g_display, 0);
2387  }  }
2388    
2389  void  void
# Line 1413  ui_patblt(uint8 opcode, Line 2418  ui_patblt(uint8 opcode,
2418          {          {
2419                  case 0: /* Solid */                  case 0: /* Solid */
2420                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2421                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2422                          break;                          break;
2423    
2424                  case 2: /* Hatch */                  case 2: /* Hatch */
2425                          fill = (Pixmap) ui_create_glyph(8, 8,                          fill = (Pixmap) ui_create_glyph(8, 8,
2426                                                          hatch_patterns + brush->pattern[0] * 8);                                                          hatch_patterns + brush->pattern[0] * 8);
2427                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(fgcolour);
2428                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(bgcolour);
2429                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2430                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
2431                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2432                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2433                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2434                          XSetTSOrigin(display, gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2435                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
2436                          break;                          break;
2437    
# Line 1434  ui_patblt(uint8 opcode, Line 2439  ui_patblt(uint8 opcode,
2439                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2440                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2441                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
2442                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2443                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2444                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2445                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
2446                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2447                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2448                          FILL_RECTANGLE(x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
2449                            XSetTSOrigin(g_display, g_gc, 0, 0);
                         XSetFillStyle(display, gc, FillSolid);  
                         XSetTSOrigin(display, gc, 0, 0);  
2450                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
2451                          break;                          break;
2452    
# Line 1453  ui_patblt(uint8 opcode, Line 2455  ui_patblt(uint8 opcode,
2455          }          }
2456    
2457          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2458    
2459            if (g_ownbackstore)
2460                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2461            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2462                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2463                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2464  }  }
2465    
2466  void  void
# Line 1461  ui_screenblt(uint8 opcode, Line 2469  ui_screenblt(uint8 opcode,
2469               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2470  {  {
2471          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2472          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
2473          if (ownbackstore)          {
2474                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2475                              g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2476                    XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2477            }
2478            else
2479            {
2480                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2481            }
2482    
2483            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2484                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2485                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2486    
2487          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2488  }  }
2489    
# Line 1473  ui_memblt(uint8 opcode, Line 2493  ui_memblt(uint8 opcode,
2493            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
2494  {  {
2495          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2496          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2497          if (ownbackstore)          ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2498                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);                                  (g_display, (Pixmap) src, sw->wnd, g_gc,
2499                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2500            if (g_ownbackstore)
2501                    XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2502          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2503  }  }
2504    
# Line 1519  ui_line(uint8 opcode, Line 2542  ui_line(uint8 opcode,
2542  {  {
2543          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2544          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2545          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2546          if (ownbackstore)          ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2547                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                                              startx - sw->xoffset, starty - sw->yoffset,
2548                                                endx - sw->xoffset, endy - sw->yoffset));
2549            if (g_ownbackstore)
2550                    XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2551          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2552  }  }
2553    
# Line 1534  ui_rect( Line 2560  ui_rect(
2560          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2561  }  }
2562    
2563    void
2564    ui_polygon(uint8 opcode,
2565               /* mode */ uint8 fillmode,
2566               /* dest */ POINT * point, int npoints,
2567               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2568    {
2569            uint8 style, i, ipattern[8];
2570            Pixmap fill;
2571    
2572            SET_FUNCTION(opcode);
2573    
2574            switch (fillmode)
2575            {
2576                    case ALTERNATE:
2577                            XSetFillRule(g_display, g_gc, EvenOddRule);
2578                            break;
2579                    case WINDING:
2580                            XSetFillRule(g_display, g_gc, WindingRule);
2581                            break;
2582                    default:
2583                            unimpl("fill mode %d\n", fillmode);
2584            }
2585    
2586            if (brush)
2587                    style = brush->style;
2588            else
2589                    style = 0;
2590    
2591            switch (style)
2592            {
2593                    case 0: /* Solid */
2594                            SET_FOREGROUND(fgcolour);
2595                            FILL_POLYGON((XPoint *) point, npoints);
2596                            break;
2597    
2598                    case 2: /* Hatch */
2599                            fill = (Pixmap) ui_create_glyph(8, 8,
2600                                                            hatch_patterns + brush->pattern[0] * 8);
2601                            SET_FOREGROUND(fgcolour);
2602                            SET_BACKGROUND(bgcolour);
2603                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2604                            XSetStipple(g_display, g_gc, fill);
2605                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2606                            FILL_POLYGON((XPoint *) point, npoints);
2607                            XSetFillStyle(g_display, g_gc, FillSolid);
2608                            XSetTSOrigin(g_display, g_gc, 0, 0);
2609                            ui_destroy_glyph((HGLYPH) fill);
2610                            break;
2611    
2612                    case 3: /* Pattern */
2613                            for (i = 0; i != 8; i++)
2614                                    ipattern[7 - i] = brush->pattern[i];
2615                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2616                            SET_FOREGROUND(bgcolour);
2617                            SET_BACKGROUND(fgcolour);
2618                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2619                            XSetStipple(g_display, g_gc, fill);
2620                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2621                            FILL_POLYGON((XPoint *) point, npoints);
2622                            XSetFillStyle(g_display, g_gc, FillSolid);
2623                            XSetTSOrigin(g_display, g_gc, 0, 0);
2624                            ui_destroy_glyph((HGLYPH) fill);
2625                            break;
2626    
2627                    default:
2628                            unimpl("brush %d\n", brush->style);
2629            }
2630    
2631            RESET_FUNCTION(opcode);
2632    }
2633    
2634    void
2635    ui_polyline(uint8 opcode,
2636                /* dest */ POINT * points, int npoints,
2637                /* pen */ PEN * pen)
2638    {
2639            /* TODO: set join style */
2640            SET_FUNCTION(opcode);
2641            SET_FOREGROUND(pen->colour);
2642            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2643            if (g_ownbackstore)
2644                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2645                               CoordModePrevious);
2646    
2647            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2648                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2649    
2650            RESET_FUNCTION(opcode);
2651    }
2652    
2653    void
2654    ui_ellipse(uint8 opcode,
2655               /* mode */ uint8 fillmode,
2656               /* dest */ int x, int y, int cx, int cy,
2657               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2658    {
2659            uint8 style, i, ipattern[8];
2660            Pixmap fill;
2661    
2662            SET_FUNCTION(opcode);
2663    
2664            if (brush)
2665                    style = brush->style;
2666            else
2667                    style = 0;
2668    
2669            switch (style)
2670            {
2671                    case 0: /* Solid */
2672                            SET_FOREGROUND(fgcolour);
2673                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2674                            break;
2675    
2676                    case 2: /* Hatch */
2677                            fill = (Pixmap) ui_create_glyph(8, 8,
2678                                                            hatch_patterns + brush->pattern[0] * 8);
2679                            SET_FOREGROUND(fgcolour);
2680                            SET_BACKGROUND(bgcolour);
2681                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2682                            XSetStipple(g_display, g_gc, fill);
2683                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2684                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2685                            XSetFillStyle(g_display, g_gc, FillSolid);
2686                            XSetTSOrigin(g_display, g_gc, 0, 0);
2687                            ui_destroy_glyph((HGLYPH) fill);
2688                            break;
2689    
2690                    case 3: /* Pattern */
2691                            for (i = 0; i != 8; i++)
2692                                    ipattern[7 - i] = brush->pattern[i];
2693                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2694                            SET_FOREGROUND(bgcolour);
2695                            SET_BACKGROUND(fgcolour);
2696                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2697                            XSetStipple(g_display, g_gc, fill);
2698                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2699                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2700                            XSetFillStyle(g_display, g_gc, FillSolid);
2701                            XSetTSOrigin(g_display, g_gc, 0, 0);
2702                            ui_destroy_glyph((HGLYPH) fill);
2703                            break;
2704    
2705                    default:
2706                            unimpl("brush %d\n", brush->style);
2707            }
2708    
2709            RESET_FUNCTION(opcode);
2710    }
2711    
2712  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2713  void  void
2714  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1544  ui_draw_glyph(int mixmode, Line 2719  ui_draw_glyph(int mixmode,
2719          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
2720          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2721    
2722          XSetFillStyle(display, gc,          XSetFillStyle(g_display, g_gc,
2723                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2724          XSetStipple(display, gc, (Pixmap) glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2725          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
2726    
2727          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2728    
2729          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
2730  }  }
2731    
2732  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
2733  {\  {\
2734    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
2735    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
2736      {\
2737        xyoffset = ttext[++idx];\
2738        if ((xyoffset & 0x80))\
2739      {\      {\
2740        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
2741        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;\  
         }\  
2742        else\        else\
2743          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
2744            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
2745      }\      }\
2746    if (glyph != NULL)\      else\
2747      {\      {\
2748        ui_draw_glyph (mixmode, x + glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2749                       y + glyph->baseline,\          y += xyoffset;\
2750                       glyph->width, glyph->height,\        else\
2751                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
2752      }\      }\
2753      }\
2754      if (glyph != NULL)\
2755      {\
2756        x1 = x + glyph->offset;\
2757        y1 = y + glyph->baseline;\
2758        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2759        XSetTSOrigin(g_display, g_gc, x1, y1);\
2760        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2761        if (flags & TEXT2_IMPLICIT_X)\
2762          x += glyph->width;\
2763      }\
2764  }  }
2765    
2766  void  void
2767  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,
2768               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2769               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2770               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2771  {  {
2772            /* TODO: use brush appropriately */
2773    
2774          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2775          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2776          DATABLOB *entry;          DATABLOB *entry;
2777    
2778          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2779    
2780            /* Sometimes, the boxcx value is something really large, like
2781               32691. This makes XCopyArea fail with Xvnc. The code below
2782               is a quick fix. */
2783            if (boxx + boxcx > g_width)
2784                    boxcx = g_width - boxx;
2785    
2786          if (boxcx > 1)          if (boxcx > 1)
2787          {          {
2788                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
# Line 1608  ui_draw_text(uint8 font, uint8 flags, in Line 2792  ui_draw_text(uint8 font, uint8 flags, in
2792                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2793          }          }
2794    
2795            SET_FOREGROUND(fgcolour);
2796            SET_BACKGROUND(bgcolour);
2797            XSetFillStyle(g_display, g_gc, FillStippled);
2798    
2799          /* Paint text, character by character */          /* Paint text, character by character */
2800          for (i = 0; i < length;)          for (i = 0; i < length;)
2801          {          {
2802                  switch (text[i])                  switch (text[i])
2803                  {                  {
2804                          case 0xff:                          case 0xff:
2805                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2806                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2807                                  {                                  {
2808                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2809                                          exit(1);                                          for (j = 0; j < length; j++)
2810                                                    fprintf(stderr, "%02x ", text[j]);
2811                                            fprintf(stderr, "\n");
2812                                            i = length = 0;
2813                                            break;
2814                                  }                                  }
2815                                    cache_put_text(text[i + 1], text, text[i + 2]);
2816                                    i += 3;
2817                                    length -= i;
2818                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2819                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2820                                  i = 0;                                  i = 0;
2821                                  break;                                  break;
2822    
2823                          case 0xfe:                          case 0xfe:
2824                                    /* At least one byte needs to follow */
2825                                    if (i + 2 > length)
2826                                    {
2827                                            warning("Skipping short 0xfe command:");
2828                                            for (j = 0; j < length; j++)
2829                                                    fprintf(stderr, "%02x ", text[j]);
2830                                            fprintf(stderr, "\n");
2831                                            i = length = 0;
2832                                            break;
2833                                    }
2834                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2835                                  if (entry != NULL)                                  if (entry->data != NULL)
2836                                  {                                  {
2837                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2838                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2839                                          {                                          {
2840                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2841                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 1658  ui_draw_text(uint8 font, uint8 flags, in Line 2861  ui_draw_text(uint8 font, uint8 flags, in
2861                                  break;                                  break;
2862                  }                  }
2863          }          }
2864          if (ownbackstore)  
2865            XSetFillStyle(g_display, g_gc, FillSolid);
2866    
2867            if (g_ownbackstore)
2868          {          {
2869                  if (boxcx > 1)                  if (boxcx > 1)
2870                          XCopyArea(display, backstore, wnd, gc, boxx,                  {
2871                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2872                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2873                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2874                                                    (g_display, g_backstore, sw->wnd, g_gc,
2875                                                     boxx, boxy,
2876                                                     boxcx, boxcy,
2877                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2878                    }
2879                  else                  else
2880                          XCopyArea(display, backstore, wnd, gc, clipx,                  {
2881                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2882                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2883                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2884                                                    (g_display, g_backstore, sw->wnd, g_gc,
2885                                                     clipx, clipy,
2886                                                     clipcx, clipcy, clipx - sw->xoffset,
2887                                                     clipy - sw->yoffset));
2888                    }
2889          }          }
2890  }  }
2891    
# Line 1675  ui_desktop_save(uint32 offset, int x, in Line 2895  ui_desktop_save(uint32 offset, int x, in
2895          Pixmap pix;          Pixmap pix;
2896          XImage *image;          XImage *image;
2897    
2898          if (ownbackstore)          if (g_ownbackstore)
2899          {          {
2900                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2901          }          }
2902          else          else
2903          {          {
2904                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2905                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2906                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2907                  XFreePixmap(display, pix);                  XFreePixmap(g_display, pix);
2908          }          }
2909    
2910          offset *= bpp / 8;          offset *= g_bpp / 8;
2911          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2912    
2913          XDestroyImage(image);          XDestroyImage(image);
2914  }  }
# Line 1699  ui_desktop_restore(uint32 offset, int x, Line 2919  ui_desktop_restore(uint32 offset, int x,
2919          XImage *image;          XImage *image;
2920          uint8 *data;          uint8 *data;
2921    
2922          offset *= bpp / 8;          offset *= g_bpp / 8;
2923          data = cache_get_desktop(offset, cx, cy, bpp / 8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2924          if (data == NULL)          if (data == NULL)
2925                  return;                  return;
2926    
2927          image = XCreateImage(display, visual, depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2928                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2929    
2930          if (ownbackstore)          if (g_ownbackstore)
2931          {          {
2932                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2933                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2934                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2935                                            (g_display, g_backstore, sw->wnd, g_gc,
2936                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2937          }          }
2938          else          else
2939          {          {
2940                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2941                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2942                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2943                                             x - sw->xoffset, y - sw->yoffset));
2944          }          }
2945    
2946          XFree(image);          XFree(image);
2947  }  }
2948    
2949    /* these do nothing here but are used in uiports */
2950    void
2951    ui_begin_update(void)
2952    {
2953    }
2954    
2955    void
2956    ui_end_update(void)
2957    {
2958    }
2959    
2960    void
2961    ui_seamless_toggle()
2962    {
2963            if (g_seamless_rdp)
2964            {
2965                    /* Deactivate */
2966                    while (g_seamless_windows)
2967                    {
2968                            XDestroyWindow(g_display, g_seamless_windows->wnd);
2969                            seamless_remove_window(g_seamless_windows);
2970                    }
2971                    XMapWindow(g_display, g_wnd);
2972            }
2973            else
2974            {
2975                    /* Activate */
2976                    if (g_win_button_size)
2977                    {
2978                            error("SeamlessRDP mode cannot be activated when using single application mode\n");
2979                            return;
2980                    }
2981                    if (!g_using_full_workarea)
2982                    {
2983                            error("SeamlessRDP mode requires a session that covers the whole screen");
2984                            return;
2985                    }
2986    
2987                    XUnmapWindow(g_display, g_wnd);
2988                    seamless_send_sync();
2989            }
2990    
2991            g_seamless_rdp = !g_seamless_rdp;
2992    }
2993    
2994    void
2995    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
2996    {
2997            Window wnd;
2998            XSetWindowAttributes attribs;
2999            XClassHint *classhints;
3000            long input_mask;
3001            seamless_window *sw, *sw_parent;
3002    
3003            get_window_attribs(&attribs);
3004    
3005            attribs.override_redirect = False;
3006    
3007            /* FIXME: Do not assume that -1, -1 is outside screen Consider
3008               wait with showing the window until STATE and others have
3009               been recieved. */
3010            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, 0,
3011                                InputOutput, g_visual,
3012                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3013                                CWBorderPixel, &attribs);
3014    
3015            XStoreName(g_display, wnd, "rdesktop-seamless");
3016    
3017            mwm_hide_decorations(wnd);
3018    
3019            classhints = XAllocClassHint();
3020            if (classhints != NULL)
3021            {
3022                    classhints->res_name = classhints->res_class = "rdesktop";
3023                    XSetClassHint(g_display, wnd, classhints);
3024                    XFree(classhints);
3025            }
3026    
3027            /* Set WM_TRANSIENT_FOR, if necessary */
3028            if (parent)
3029            {
3030                    sw_parent = seamless_get_window_by_id(parent);
3031                    if (sw_parent)
3032                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3033                    else
3034                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3035            }
3036    
3037            /* FIXME: Support for Input Context:s */
3038    
3039            get_input_mask(&input_mask);
3040    
3041            XSelectInput(g_display, wnd, input_mask);
3042    
3043            XMapWindow(g_display, wnd);
3044    
3045            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3046               seamless window, we could try to close the window on the
3047               serverside, instead of terminating rdesktop */
3048            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3049    
3050            sw = malloc(sizeof(seamless_window));
3051            sw->wnd = wnd;
3052            sw->id = id;
3053            sw->xoffset = 0;
3054            sw->yoffset = 0;
3055            sw->width = 0;
3056            sw->height = 0;
3057            sw->next = g_seamless_windows;
3058            g_seamless_windows = sw;
3059    }
3060    
3061    
3062    void
3063    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3064    {
3065            seamless_window *sw;
3066    
3067            sw = seamless_get_window_by_id(id);
3068            if (!sw)
3069            {
3070                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3071                    return;
3072            }
3073    
3074            XDestroyWindow(g_display, sw->wnd);
3075            seamless_remove_window(sw);
3076    }
3077    
3078    
3079    void
3080    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3081    {
3082            seamless_window *sw;
3083    
3084            sw = seamless_get_window_by_id(id);
3085            if (!sw)
3086            {
3087                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3088                    return;
3089            }
3090    
3091            if (!width || !height)
3092                    /* X11 windows must be at least 1x1 */
3093                    return;
3094    
3095            /* About MAX and MIN: Windows allows moving a window outside
3096               the desktop. This happens, for example, when maximizing an
3097               application. In this case, the position is set to something
3098               like -4,-4,1288,1032. Many WMs does not allow windows
3099               outside the desktop, however. Therefore, clip the window
3100               ourselves. */
3101            sw->xoffset = MAX(0, x);
3102            sw->yoffset = MAX(0, y);
3103            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3104            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3105    
3106            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3107            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3108    }
3109    
3110    
3111    void
3112    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3113    {
3114            seamless_window *sw;
3115    
3116            sw = seamless_get_window_by_id(id);
3117            if (!sw)
3118            {
3119                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3120                    return;
3121            }
3122    
3123            XStoreName(g_display, sw->wnd, title);
3124    }
3125    
3126    
3127    void
3128    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3129    {
3130            seamless_window *sw;
3131    
3132            sw = seamless_get_window_by_id(id);
3133            if (!sw)
3134            {
3135                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3136                    return;
3137            }
3138    
3139            switch (state)
3140            {
3141                    case SEAMLESSRDP_NORMAL:
3142                    case SEAMLESSRDP_MAXIMIZED:
3143                            XMapWindow(g_display, sw->wnd);
3144                            break;
3145                    case SEAMLESSRDP_MINIMIZED:
3146                            XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3147                            break;
3148                    default:
3149                            warning("SeamlessRDP: Invalid state %d\n", state);
3150                            break;
3151            }
3152    }

Legend:
Removed from v.432  
changed lines
  Added in v.1107

  ViewVC Help
Powered by ViewVC 1.1.26