/[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 376 by jsorg71, Mon May 19 21:36:33 2003 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1159 by ossman_, Fri Mar 17 15:16:52 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- 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"
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  static int x_socket;  
46  static Screen *screen;  Display *g_display;
47  static Window wnd;  Time g_last_gesturetime;
48  static GC gc;  static int g_x_socket;
49  static Visual *visual;  static Screen *g_screen;
50  static int depth;  Window g_wnd;
51  static int bpp;  
52  static XIM IM;  /* SeamlessRDP support */
53  static XIC IC;  typedef struct _seamless_window
54  static XModifierKeymap *mod_map;  {
55  static Cursor current_cursor;          Window wnd;
56  static Atom protocol_atom, kill_atom;          unsigned long id;
57            unsigned long behind;
58            int xoffset, yoffset;
59            int width, height;
60            int state;              /* normal/minimized/maximized. */
61            unsigned int desktop;
62            struct timeval *position_timer;
63            struct _seamless_window *next;
64    } seamless_window;
65    static seamless_window *g_seamless_windows = NULL;
66    static unsigned long g_seamless_focused = 0;
67    static BOOL g_seamless_started = False; /* Server end is up and running */
68    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
69    extern BOOL g_seamless_rdp;
70    
71    extern uint32 g_embed_wnd;
72    BOOL g_enable_compose = False;
73    BOOL g_Unobscured;              /* used for screenblt */
74    static GC g_gc = NULL;
75    static GC g_create_bitmap_gc = NULL;
76    static GC g_create_glyph_gc = NULL;
77    static XRectangle g_clip_rectangle;
78    static Visual *g_visual;
79    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
80       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
81       as far as we're concerned. */
82    static int g_depth;
83    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
84       This may be larger than g_depth, in which case some of the bits would
85       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
86    static int g_bpp;
87    static XIM g_IM;
88    static XIC g_IC;
89    static XModifierKeymap *g_mod_map;
90    static Cursor g_current_cursor;
91    static HCURSOR g_null_cursor = NULL;
92    static Atom g_protocol_atom, g_kill_atom;
93    extern Atom g_net_wm_state_atom;
94    extern Atom g_net_wm_desktop_atom;
95    static BOOL g_focused;
96    static BOOL g_mouse_in_wnd;
97    /* Indicates that:
98       1) visual has 15, 16 or 24 depth and the same color channel masks
99          as its RDP equivalent (implies X server is LE),
100       2) host is LE
101       This will trigger an optimization whose real value is questionable.
102    */
103    static BOOL g_compatible_arch;
104    /* Indicates whether RDP's bitmaps and our XImages have the same
105       binary format. If so, we can avoid an expensive translation.
106       Note that this can be true when g_compatible_arch is false,
107       e.g.:
108      
109         RDP(LE) <-> host(BE) <-> X-Server(LE)
110        
111       ('host' is the machine running rdesktop; the host simply memcpy's
112        so its endianess doesn't matter)
113     */
114    static BOOL g_no_translate_image = False;
115    
116  /* endianness */  /* endianness */
117  static BOOL host_be;  static BOOL g_host_be;
118  static BOOL xserver_be;  static BOOL g_xserver_be;
119    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
120    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
121    
122  /* software backing store */  /* software backing store */
123  static BOOL ownbackstore;  extern BOOL g_ownbackstore;
124  static Pixmap backstore;  static Pixmap g_backstore = 0;
125    
126  /* Moving in single app mode */  /* Moving in single app mode */
127  static BOOL moving_wnd;  static BOOL g_moving_wnd;
128  static int move_x_offset = 0;  static int g_move_x_offset = 0;
129  static int move_y_offset = 0;  static int g_move_y_offset = 0;
130    static BOOL g_using_full_workarea = False;
131    
132    #ifdef WITH_RDPSND
133    extern int g_dsp_fd;
134    extern BOOL g_dsp_busy;
135    extern BOOL g_rdpsnd;
136    #endif
137    
138  /* MWM decorations */  /* MWM decorations */
139  #define MWM_HINTS_DECORATIONS   (1L << 1)  #define MWM_HINTS_DECORATIONS   (1L << 1)
140  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
141  typedef struct  typedef struct
142  {  {
143          uint32 flags;          unsigned long flags;
144          uint32 functions;          unsigned long functions;
145          uint32 decorations;          unsigned long decorations;
146          sint32 inputMode;          long inputMode;
147          uint32 status;          unsigned long status;
148  }  }
149  PropMotifWmHints;  PropMotifWmHints;
150    
# Line 85  typedef struct Line 156  typedef struct
156  }  }
157  PixelColour;  PixelColour;
158    
159    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
160            do { \
161                    seamless_window *sw; \
162                    XRectangle rect; \
163                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
164                        rect.x = g_clip_rectangle.x - sw->xoffset; \
165                        rect.y = g_clip_rectangle.y - sw->yoffset; \
166                        rect.width = g_clip_rectangle.width; \
167                        rect.height = g_clip_rectangle.height; \
168                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
169                        func args; \
170                    } \
171                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
172            } while (0)
173    
174    static void
175    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
176    {
177            points[0].x -= xoffset;
178            points[0].y -= yoffset;
179            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
180            points[0].x += xoffset;
181            points[0].y += yoffset;
182    }
183    
184    static void
185    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
186    {
187            points[0].x -= xoffset;
188            points[0].y -= yoffset;
189            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
190            points[0].x += xoffset;
191            points[0].y += yoffset;
192    }
193    
194  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
195  { \  { \
196          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
197          if (ownbackstore) \          ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
198                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \          if (g_ownbackstore) \
199                    XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
200  }  }
201    
202  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
203  { \  { \
204          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); \
205    }
206    
207    #define FILL_POLYGON(p,np)\
208    { \
209            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
210            if (g_ownbackstore) \
211                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
212            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
213    }
214    
215    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
216    { \
217            switch (m) \
218            { \
219                    case 0: /* Outline */ \
220                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
221                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
222                            if (g_ownbackstore) \
223                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
224                            break; \
225                    case 1: /* Filled */ \
226                            XFillArc(g_display, g_wnd, g_gc, x, y, \
227                                     cx, cy, 0, 360*64); \
228                            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)); \
229                            if (g_ownbackstore) \
230                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
231                            break; \
232            } \
233  }  }
234    
235  /* colour maps */  /* colour maps */
236  BOOL owncolmap = False;  extern BOOL g_owncolmap;
237  static Colormap xcolmap;  static Colormap g_xcolmap;
238  static uint32 *colmap;  static uint32 *g_colmap = NULL;
239    
240  #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] )
241  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
242  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
243    
244  static int rop2_map[] = {  static int rop2_map[] = {
245          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 125  static int rop2_map[] = { Line 260  static int rop2_map[] = {
260          GXset                   /* 1 */          GXset                   /* 1 */
261  };  };
262    
263  #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]); }
264  #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); }
265    
266    static seamless_window *
267    seamless_get_window_by_id(unsigned long id)
268    {
269            seamless_window *sw;
270            for (sw = g_seamless_windows; sw; sw = sw->next)
271            {
272                    if (sw->id == id)
273                            return sw;
274            }
275            return NULL;
276    }
277    
278    
279    static seamless_window *
280    seamless_get_window_by_wnd(Window wnd)
281    {
282            seamless_window *sw;
283            for (sw = g_seamless_windows; sw; sw = sw->next)
284            {
285                    if (sw->wnd == wnd)
286                            return sw;
287            }
288            return NULL;
289    }
290    
291    
292    static void
293    seamless_remove_window(seamless_window * win)
294    {
295            seamless_window *sw, **prevnext = &g_seamless_windows;
296            for (sw = g_seamless_windows; sw; sw = sw->next)
297            {
298                    if (sw == win)
299                    {
300                            *prevnext = sw->next;
301                            xfree(sw);
302                            return;
303                    }
304                    prevnext = &sw->next;
305            }
306            return;
307    }
308    
309    
310    /* Move all windows except wnd to new desktop */
311  static void  static void
312  mwm_hide_decorations(void)  seamless_all_to_desktop(Window wnd, unsigned int desktop)
313    {
314            seamless_window *sw;
315            for (sw = g_seamless_windows; sw; sw = sw->next)
316            {
317                    if (sw->wnd == wnd)
318                            continue;
319                    if (sw->desktop != desktop)
320                    {
321                            ewmh_move_to_desktop(sw->wnd, desktop);
322                            sw->desktop = desktop;
323                    }
324            }
325    }
326    
327    
328    /* Send our position */
329    static void
330    seamless_update_position(seamless_window * sw)
331    {
332            XWindowAttributes wa;
333            int x, y;
334            Window child_return;
335    
336            XGetWindowAttributes(g_display, sw->wnd, &wa);
337            XTranslateCoordinates(g_display, sw->wnd, wa.root,
338                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
339    
340            seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
341            sw->xoffset = x;
342            sw->yoffset = y;
343            sw->width = wa.width;
344            sw->height = wa.height;
345    }
346    
347    
348    /* Check if it's time to send our position */
349    static void
350    seamless_check_timers()
351    {
352            seamless_window *sw;
353            struct timeval now;
354    
355            gettimeofday(&now, NULL);
356            for (sw = g_seamless_windows; sw; sw = sw->next)
357            {
358                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
359                    {
360                            timerclear(sw->position_timer);
361                            seamless_update_position(sw);
362                    }
363            }
364    }
365    
366    
367    static void
368    seamless_restack_window(seamless_window * sw, unsigned long behind)
369    {
370            seamless_window *sw_above;
371    
372            /* Remove window from stack */
373            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
374            {
375                    if (sw_above->behind == sw->id)
376                            break;
377            }
378    
379            if (sw_above)
380                    sw_above->behind = sw->behind;
381    
382            /* And then add it at the new position */
383    
384            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
385            {
386                    if (sw_above->behind == behind)
387                            break;
388            }
389    
390            if (sw_above)
391                    sw_above->behind = sw->id;
392    
393            sw->behind = behind;
394    }
395    
396    
397    static void
398    mwm_hide_decorations(Window wnd)
399  {  {
400          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
401          Atom hintsatom;          Atom hintsatom;
# Line 139  mwm_hide_decorations(void) Line 405  mwm_hide_decorations(void)
405          motif_hints.decorations = 0;          motif_hints.decorations = 0;
406    
407          /* get the atom for the property */          /* get the atom for the property */
408          hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);          hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
409          if (!hintsatom)          if (!hintsatom)
410          {          {
411                  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");
412                  return;                  return;
413          }          }
414    
415          XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
416                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
 }  
417    
 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;  
418  }  }
419    
420  static uint32  #define SPLITCOLOUR15(colour, rv) \
421  make_colour16(PixelColour pc)  { \
422  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
423          pc.red = (pc.red * 0x1f) / 0xff;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
424          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;  
425  }  }
426    
427  static uint32  #define SPLITCOLOUR16(colour, rv) \
428  make_colour24(PixelColour pc)  { \
429  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
430          return (pc.red << 16) | (pc.green << 8) | pc.blue;          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
431  }          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
432    } \
433    
434  static uint32  #define SPLITCOLOUR24(colour, rv) \
435  make_colour32(PixelColour pc)  { \
436  {          rv.blue = (colour & 0xff0000) >> 16; \
437          return (pc.red << 16) | (pc.green << 8) | pc.blue;          rv.green = (colour & 0x00ff00) >> 8; \
438            rv.red = (colour & 0x0000ff); \
439  }  }
440    
441    #define MAKECOLOUR(pc) \
442            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
443                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
444                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
445    
446  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
447  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
448  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
449                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
450    
451    /* The following macros output the same octet sequences
452       on both BE and LE hosts: */
453    
454    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
455    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
456    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
457    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
458    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
459    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
460    
461  static uint32  static uint32
462  translate_colour(uint32 colour)  translate_colour(uint32 colour)
463  {  {
464          switch (server_bpp)          PixelColour pc;
465            switch (g_server_depth)
466          {          {
467                  case 15:                  case 15:
468                          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;  
                         }  
469                          break;                          break;
470                  case 16:                  case 16:
471                          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;  
                         }  
472                          break;                          break;
473                  case 24:                  case 24:
474                          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;  
                         }  
475                          break;                          break;
476          }                  default:
477          switch (bpp)                          /* Avoid warning */
478          {                          pc.red = 0;
479                  case 16:                          pc.green = 0;
480                          if (host_be != xserver_be)                          pc.blue = 0;
                                 BSWAP16(colour);  
481                          break;                          break;
482            }
483            return MAKECOLOUR(pc);
484    }
485    
486                  case 24:  /* indent is confused by UNROLL8 */
487                          if (xserver_be)  /* *INDENT-OFF* */
                                 BSWAP24(colour);  
                         break;  
488    
489                  case 32:  /* repeat and unroll, similar to bitmap.c */
490                          if (host_be != xserver_be)  /* potentialy any of the following translate */
491                                  BSWAP32(colour);  /* functions can use repeat but just doing */
492                          break;  /* the most common ones */
         }  
493    
494          return colour;  #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
495    /* 2 byte output repeat */
496    #define REPEAT2(stm) \
497    { \
498            while (out <= end - 8 * 2) \
499                    UNROLL8(stm) \
500            while (out < end) \
501                    { stm } \
502    }
503    /* 3 byte output repeat */
504    #define REPEAT3(stm) \
505    { \
506            while (out <= end - 8 * 3) \
507                    UNROLL8(stm) \
508            while (out < end) \
509                    { stm } \
510  }  }
511    /* 4 byte output repeat */
512    #define REPEAT4(stm) \
513    { \
514            while (out <= end - 8 * 4) \
515                    UNROLL8(stm) \
516            while (out < end) \
517                    { stm } \
518    }
519    /* *INDENT-ON* */
520    
521  static void  static void
522  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
523  {  {
524          while (out < end)          while (out < end)
525                  *(out++) = (uint8) colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
526  }  }
527    
528  static void  static void
529  translate8to16(uint8 * data, uint16 * out, uint16 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
530  {  {
531          while (out < end)          uint16 value;
532                  *(out++) = (uint16) colmap[*(data++)];  
533            if (g_compatible_arch)
534            {
535                    /* *INDENT-OFF* */
536                    REPEAT2
537                    (
538                            *((uint16 *) out) = g_colmap[*(data++)];
539                            out += 2;
540                    )
541                    /* *INDENT-ON* */
542            }
543            else if (g_xserver_be)
544            {
545                    while (out < end)
546                    {
547                            value = (uint16) g_colmap[*(data++)];
548                            BOUT16(out, value);
549                    }
550            }
551            else
552            {
553                    while (out < end)
554                    {
555                            value = (uint16) g_colmap[*(data++)];
556                            LOUT16(out, value);
557                    }
558            }
559  }  }
560    
561  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
562  static void  static void
563  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
564  {  {
565          uint32 value;          uint32 value;
566    
567          while (out < end)          if (g_compatible_arch)
568            {
569                    while (out < end)
570                    {
571                            value = g_colmap[*(data++)];
572                            BOUT24(out, value);
573                    }
574            }
575            else
576          {          {
577                  value = colmap[*(data++)];                  while (out < end)
578                  *(out++) = value;                  {
579                  *(out++) = value >> 8;                          value = g_colmap[*(data++)];
580                  *(out++) = value >> 16;                          LOUT24(out, value);
581                    }
582          }          }
583  }  }
584    
585  static void  static void
586  translate8to32(uint8 * data, uint32 * out, uint32 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
587  {  {
588          while (out < end)          uint32 value;
                 *(out++) = colmap[*(data++)];  
 }  
589    
590  /* todo the remaining translate function might need some big endian check ?? */          if (g_compatible_arch)
591            {
592                    /* *INDENT-OFF* */
593                    REPEAT4
594                    (
595                            *((uint32 *) out) = g_colmap[*(data++)];
596                            out += 4;
597                    )
598                    /* *INDENT-ON* */
599            }
600            else if (g_xserver_be)
601            {
602                    while (out < end)
603                    {
604                            value = g_colmap[*(data++)];
605                            BOUT32(out, value);
606                    }
607            }
608            else
609            {
610                    while (out < end)
611                    {
612                            value = g_colmap[*(data++)];
613                            LOUT32(out, value);
614                    }
615            }
616    }
617    
618  static void  static void
619  translate15to16(uint16 * data, uint16 * out, uint16 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
620  {  {
621          while (out < end)          uint16 pixel;
622                  *(out++) = (uint16) make_colour16(split_colour15(*(data++)));          uint16 value;
623            PixelColour pc;
624    
625            if (g_xserver_be)
626            {
627                    while (out < end)
628                    {
629                            pixel = *(data++);
630                            if (g_host_be)
631                            {
632                                    BSWAP16(pixel);
633                            }
634                            SPLITCOLOUR15(pixel, pc);
635                            value = MAKECOLOUR(pc);
636                            BOUT16(out, value);
637                    }
638            }
639            else
640            {
641                    while (out < end)
642                    {
643                            pixel = *(data++);
644                            if (g_host_be)
645                            {
646                                    BSWAP16(pixel);
647                            }
648                            SPLITCOLOUR15(pixel, pc);
649                            value = MAKECOLOUR(pc);
650                            LOUT16(out, value);
651                    }
652            }
653  }  }
654    
655  static void  static void
656  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
657  {  {
658          uint32 value;          uint32 value;
659            uint16 pixel;
660            PixelColour pc;
661    
662          while (out < end)          if (g_compatible_arch)
663          {          {
664                  value = make_colour24(split_colour15(*(data++)));                  /* *INDENT-OFF* */
665                  *(out++) = value;                  REPEAT3
666                  *(out++) = value >> 8;                  (
667                  *(out++) = value >> 16;                          pixel = *(data++);
668                            SPLITCOLOUR15(pixel, pc);
669                            *(out++) = pc.blue;
670                            *(out++) = pc.green;
671                            *(out++) = pc.red;
672                    )
673                    /* *INDENT-ON* */
674            }
675            else if (g_xserver_be)
676            {
677                    while (out < end)
678                    {
679                            pixel = *(data++);
680                            if (g_host_be)
681                            {
682                                    BSWAP16(pixel);
683                            }
684                            SPLITCOLOUR15(pixel, pc);
685                            value = MAKECOLOUR(pc);
686                            BOUT24(out, value);
687                    }
688            }
689            else
690            {
691                    while (out < end)
692                    {
693                            pixel = *(data++);
694                            if (g_host_be)
695                            {
696                                    BSWAP16(pixel);
697                            }
698                            SPLITCOLOUR15(pixel, pc);
699                            value = MAKECOLOUR(pc);
700                            LOUT24(out, value);
701                    }
702          }          }
703  }  }
704    
705  static void  static void
706  translate15to32(uint16 * data, uint32 * out, uint32 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
707  {  {
708          while (out < end)          uint16 pixel;
709                  *(out++) = make_colour32(split_colour15(*(data++)));          uint32 value;
710            PixelColour pc;
711    
712            if (g_compatible_arch)
713            {
714                    /* *INDENT-OFF* */
715                    REPEAT4
716                    (
717                            pixel = *(data++);
718                            SPLITCOLOUR15(pixel, pc);
719                            *(out++) = pc.blue;
720                            *(out++) = pc.green;
721                            *(out++) = pc.red;
722                            *(out++) = 0;
723                    )
724                    /* *INDENT-ON* */
725            }
726            else if (g_xserver_be)
727            {
728                    while (out < end)
729                    {
730                            pixel = *(data++);
731                            if (g_host_be)
732                            {
733                                    BSWAP16(pixel);
734                            }
735                            SPLITCOLOUR15(pixel, pc);
736                            value = MAKECOLOUR(pc);
737                            BOUT32(out, value);
738                    }
739            }
740            else
741            {
742                    while (out < end)
743                    {
744                            pixel = *(data++);
745                            if (g_host_be)
746                            {
747                                    BSWAP16(pixel);
748                            }
749                            SPLITCOLOUR15(pixel, pc);
750                            value = MAKECOLOUR(pc);
751                            LOUT32(out, value);
752                    }
753            }
754  }  }
755    
756  static void  static void
757  translate16to16(uint16 * data, uint16 * out, uint16 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
758  {  {
759          while (out < end)          uint16 pixel;
760                  *(out++) = (uint16) (*(data++));          uint16 value;
761  }          PixelColour pc;
762    
763            if (g_xserver_be)
764            {
765                    if (g_host_be)
766                    {
767                            while (out < end)
768                            {
769                                    pixel = *(data++);
770                                    BSWAP16(pixel);
771                                    SPLITCOLOUR16(pixel, pc);
772                                    value = MAKECOLOUR(pc);
773                                    BOUT16(out, value);
774                            }
775                    }
776                    else
777                    {
778                            while (out < end)
779                            {
780                                    pixel = *(data++);
781                                    SPLITCOLOUR16(pixel, pc);
782                                    value = MAKECOLOUR(pc);
783                                    BOUT16(out, value);
784                            }
785                    }
786            }
787            else
788            {
789                    if (g_host_be)
790                    {
791                            while (out < end)
792                            {
793                                    pixel = *(data++);
794                                    BSWAP16(pixel);
795                                    SPLITCOLOUR16(pixel, pc);
796                                    value = MAKECOLOUR(pc);
797                                    LOUT16(out, value);
798                            }
799                    }
800                    else
801                    {
802                            while (out < end)
803                            {
804                                    pixel = *(data++);
805                                    SPLITCOLOUR16(pixel, pc);
806                                    value = MAKECOLOUR(pc);
807                                    LOUT16(out, value);
808                            }
809                    }
810            }
811    }
812    
813  static void  static void
814  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
815  {  {
816          uint32 value;          uint32 value;
817            uint16 pixel;
818            PixelColour pc;
819    
820          while (out < end)          if (g_compatible_arch)
821            {
822                    /* *INDENT-OFF* */
823                    REPEAT3
824                    (
825                            pixel = *(data++);
826                            SPLITCOLOUR16(pixel, pc);
827                            *(out++) = pc.blue;
828                            *(out++) = pc.green;
829                            *(out++) = pc.red;
830                    )
831                    /* *INDENT-ON* */
832            }
833            else if (g_xserver_be)
834            {
835                    if (g_host_be)
836                    {
837                            while (out < end)
838                            {
839                                    pixel = *(data++);
840                                    BSWAP16(pixel);
841                                    SPLITCOLOUR16(pixel, pc);
842                                    value = MAKECOLOUR(pc);
843                                    BOUT24(out, value);
844                            }
845                    }
846                    else
847                    {
848                            while (out < end)
849                            {
850                                    pixel = *(data++);
851                                    SPLITCOLOUR16(pixel, pc);
852                                    value = MAKECOLOUR(pc);
853                                    BOUT24(out, value);
854                            }
855                    }
856            }
857            else
858          {          {
859                  value = make_colour24(split_colour16(*(data++)));                  if (g_host_be)
860                  *(out++) = value;                  {
861                  *(out++) = value >> 8;                          while (out < end)
862                  *(out++) = value >> 16;                          {
863                                    pixel = *(data++);
864                                    BSWAP16(pixel);
865                                    SPLITCOLOUR16(pixel, pc);
866                                    value = MAKECOLOUR(pc);
867                                    LOUT24(out, value);
868                            }
869                    }
870                    else
871                    {
872                            while (out < end)
873                            {
874                                    pixel = *(data++);
875                                    SPLITCOLOUR16(pixel, pc);
876                                    value = MAKECOLOUR(pc);
877                                    LOUT24(out, value);
878                            }
879                    }
880          }          }
881  }  }
882    
883  static void  static void
884  translate16to32(uint16 * data, uint32 * out, uint32 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
885  {  {
886          while (out < end)          uint16 pixel;
887                  *(out++) = make_colour32(split_colour16(*(data++)));          uint32 value;
888            PixelColour pc;
889    
890            if (g_compatible_arch)
891            {
892                    /* *INDENT-OFF* */
893                    REPEAT4
894                    (
895                            pixel = *(data++);
896                            SPLITCOLOUR16(pixel, pc);
897                            *(out++) = pc.blue;
898                            *(out++) = pc.green;
899                            *(out++) = pc.red;
900                            *(out++) = 0;
901                    )
902                    /* *INDENT-ON* */
903            }
904            else if (g_xserver_be)
905            {
906                    if (g_host_be)
907                    {
908                            while (out < end)
909                            {
910                                    pixel = *(data++);
911                                    BSWAP16(pixel);
912                                    SPLITCOLOUR16(pixel, pc);
913                                    value = MAKECOLOUR(pc);
914                                    BOUT32(out, value);
915                            }
916                    }
917                    else
918                    {
919                            while (out < end)
920                            {
921                                    pixel = *(data++);
922                                    SPLITCOLOUR16(pixel, pc);
923                                    value = MAKECOLOUR(pc);
924                                    BOUT32(out, value);
925                            }
926                    }
927            }
928            else
929            {
930                    if (g_host_be)
931                    {
932                            while (out < end)
933                            {
934                                    pixel = *(data++);
935                                    BSWAP16(pixel);
936                                    SPLITCOLOUR16(pixel, pc);
937                                    value = MAKECOLOUR(pc);
938                                    LOUT32(out, value);
939                            }
940                    }
941                    else
942                    {
943                            while (out < end)
944                            {
945                                    pixel = *(data++);
946                                    SPLITCOLOUR16(pixel, pc);
947                                    value = MAKECOLOUR(pc);
948                                    LOUT32(out, value);
949                            }
950                    }
951            }
952  }  }
953    
954  static void  static void
955  translate24to16(uint8 * data, uint16 * out, uint16 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
956  {  {
957          uint32 pixel = 0;          uint32 pixel = 0;
958            uint16 value;
959            PixelColour pc;
960    
961          while (out < end)          while (out < end)
962          {          {
963                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
964                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
965                  pixel |= *(data++);                  pixel |= *(data++);
966                  *(out++) = (uint16) make_colour16(split_colour24(pixel));                  SPLITCOLOUR24(pixel, pc);
967                    value = MAKECOLOUR(pc);
968                    if (g_xserver_be)
969                    {
970                            BOUT16(out, value);
971                    }
972                    else
973                    {
974                            LOUT16(out, value);
975                    }
976          }          }
977  }  }
978    
979  static void  static void
980  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
981  {  {
982          while (out < end)          uint32 pixel;
983            uint32 value;
984            PixelColour pc;
985    
986            if (g_xserver_be)
987            {
988                    while (out < end)
989                    {
990                            pixel = *(data++) << 16;
991                            pixel |= *(data++) << 8;
992                            pixel |= *(data++);
993                            SPLITCOLOUR24(pixel, pc);
994                            value = MAKECOLOUR(pc);
995                            BOUT24(out, value);
996                    }
997            }
998            else
999          {          {
1000                  *(out++) = (*(data++));                  while (out < end)
1001                    {
1002                            pixel = *(data++) << 16;
1003                            pixel |= *(data++) << 8;
1004                            pixel |= *(data++);
1005                            SPLITCOLOUR24(pixel, pc);
1006                            value = MAKECOLOUR(pc);
1007                            LOUT24(out, value);
1008                    }
1009          }          }
1010  }  }
1011    
1012  static void  static void
1013  translate24to32(uint8 * data, uint32 * out, uint32 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
1014  {  {
1015          uint32 pixel = 0;          uint32 pixel;
1016          while (out < end)          uint32 value;
1017            PixelColour pc;
1018    
1019            if (g_compatible_arch)
1020          {          {
1021                  pixel = *(data++);                  /* *INDENT-OFF* */
1022                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
1023                  pixel |= *(data++) << 16;                  REPEAT4
1024                  *(out++) = pixel;                  (
1025                            *(out++) = *(data++);
1026                            *(out++) = *(data++);
1027                            *(out++) = *(data++);
1028                            *(out++) = 0;
1029                    )
1030    #else
1031                    REPEAT4
1032                    (
1033                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
1034                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
1035                     out += 4;
1036                     data += 3;
1037                    )
1038    #endif
1039                    /* *INDENT-ON* */
1040            }
1041            else if (g_xserver_be)
1042            {
1043                    while (out < end)
1044                    {
1045                            pixel = *(data++) << 16;
1046                            pixel |= *(data++) << 8;
1047                            pixel |= *(data++);
1048                            SPLITCOLOUR24(pixel, pc);
1049                            value = MAKECOLOUR(pc);
1050                            BOUT32(out, value);
1051                    }
1052            }
1053            else
1054            {
1055                    while (out < end)
1056                    {
1057                            pixel = *(data++) << 16;
1058                            pixel |= *(data++) << 8;
1059                            pixel |= *(data++);
1060                            SPLITCOLOUR24(pixel, pc);
1061                            value = MAKECOLOUR(pc);
1062                            LOUT32(out, value);
1063                    }
1064          }          }
1065  }  }
1066    
1067  static uint8 *  static uint8 *
1068  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
1069  {  {
1070          int size = width * height * bpp / 8;          int size;
1071          uint8 *out = (uint8*)xmalloc(size);          uint8 *out;
1072          uint8 *end = out + size;          uint8 *end;
1073    
1074            /*
1075               If RDP depth and X Visual depths match,
1076               and arch(endian) matches, no need to translate:
1077               just return data.
1078               Note: select_visual should've already ensured g_no_translate
1079               is only set for compatible depths, but the RDP depth might've
1080               changed during connection negotiations.
1081             */
1082            if (g_no_translate_image)
1083            {
1084                    if ((g_depth == 15 && g_server_depth == 15) ||
1085                        (g_depth == 16 && g_server_depth == 16) ||
1086                        (g_depth == 24 && g_server_depth == 24))
1087                            return data;
1088            }
1089    
1090            size = width * height * (g_bpp / 8);
1091            out = (uint8 *) xmalloc(size);
1092            end = out + size;
1093    
1094          switch (server_bpp)          switch (g_server_depth)
1095          {          {
1096                  case 24:                  case 24:
1097                          switch (bpp)                          switch (g_bpp)
1098                          {                          {
1099                                  case 32:                                  case 32:
1100                                          translate24to32(data, (uint32 *) out, (uint32 *) end);                                          translate24to32(data, out, end);
1101                                          break;                                          break;
1102                                  case 24:                                  case 24:
1103                                          translate24to24(data, out, end);                                          translate24to24(data, out, end);
1104                                          break;                                          break;
1105                                  case 16:                                  case 16:
1106                                          translate24to16(data, (uint16 *) out, (uint16 *) end);                                          translate24to16(data, out, end);
1107                                          break;                                          break;
1108                          }                          }
1109                          break;                          break;
1110                  case 16:                  case 16:
1111                          switch (bpp)                          switch (g_bpp)
1112                          {                          {
1113                                  case 32:                                  case 32:
1114                                          translate16to32((uint16 *) data, (uint32 *) out,                                          translate16to32((uint16 *) data, out, end);
                                                         (uint32 *) end);  
1115                                          break;                                          break;
1116                                  case 24:                                  case 24:
1117                                          translate16to24((uint16 *) data, out, end);                                          translate16to24((uint16 *) data, out, end);
1118                                          break;                                          break;
1119                                  case 16:                                  case 16:
1120                                          translate16to16((uint16 *) data, (uint16 *) out,                                          translate16to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
1121                                          break;                                          break;
1122                          }                          }
1123                          break;                          break;
1124                  case 15:                  case 15:
1125                          switch (bpp)                          switch (g_bpp)
1126                          {                          {
1127                                  case 32:                                  case 32:
1128                                          translate15to32((uint16 *) data, (uint32 *) out,                                          translate15to32((uint16 *) data, out, end);
                                                         (uint32 *) end);  
1129                                          break;                                          break;
1130                                  case 24:                                  case 24:
1131                                          translate15to24((uint16 *) data, out, end);                                          translate15to24((uint16 *) data, out, end);
1132                                          break;                                          break;
1133                                  case 16:                                  case 16:
1134                                          translate15to16((uint16 *) data, (uint16 *) out,                                          translate15to16((uint16 *) data, out, end);
                                                         (uint16 *) end);  
1135                                          break;                                          break;
1136                          }                          }
1137                          break;                          break;
1138                  case 8:                  case 8:
1139                          switch (bpp)                          switch (g_bpp)
1140                          {                          {
1141                                  case 8:                                  case 8:
1142                                          translate8to8(data, out, end);                                          translate8to8(data, out, end);
1143                                          break;                                          break;
1144                                  case 16:                                  case 16:
1145                                          translate8to16(data, (uint16 *) out, (uint16 *) end);                                          translate8to16(data, out, end);
1146                                          break;                                          break;
1147                                  case 24:                                  case 24:
1148                                          translate8to24(data, out, end);                                          translate8to24(data, out, end);
1149                                          break;                                          break;
1150                                  case 32:                                  case 32:
1151                                          translate8to32(data, (uint32 *) out, (uint32 *) end);                                          translate8to32(data, out, end);
1152                                          break;                                          break;
1153                          }                          }
1154                          break;                          break;
# Line 491  get_key_state(unsigned int state, uint32 Line 1162  get_key_state(unsigned int state, uint32
1162          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
1163          int offset;          int offset;
1164    
1165          KeyCode keycode = XKeysymToKeycode(display, keysym);          KeyCode keycode = XKeysymToKeycode(g_display, keysym);
1166    
1167          if (keycode == NoSymbol)          if (keycode == NoSymbol)
1168                  return False;                  return False;
1169    
1170          for (modifierpos = 0; modifierpos < 8; modifierpos++)          for (modifierpos = 0; modifierpos < 8; modifierpos++)
1171          {          {
1172                  offset = mod_map->max_keypermod * modifierpos;                  offset = g_mod_map->max_keypermod * modifierpos;
1173    
1174                  for (key = 0; key < mod_map->max_keypermod; key++)                  for (key = 0; key < g_mod_map->max_keypermod; key++)
1175                  {                  {
1176                          if (mod_map->modifiermap[offset + key] == keycode)                          if (g_mod_map->modifiermap[offset + key] == keycode)
1177                                  keysymMask |= 1 << modifierpos;                                  keysymMask |= 1 << modifierpos;
1178                  }                  }
1179          }          }
# Line 510  get_key_state(unsigned int state, uint32 Line 1181  get_key_state(unsigned int state, uint32
1181          return (state & keysymMask) ? True : False;          return (state & keysymMask) ? True : False;
1182  }  }
1183    
1184  BOOL  static void
1185  ui_init(void)  calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
1186    {
1187            *shift_l = ffs(mask) - 1;
1188            mask >>= *shift_l;
1189            *shift_r = 8 - ffs(mask & ~(mask >> 1));
1190    }
1191    
1192    /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1193       calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1194     */
1195    static unsigned
1196    calculate_mask_weight(uint32 mask)
1197    {
1198            unsigned weight = 0;
1199            do
1200            {
1201                    weight += (mask & 1);
1202            }
1203            while (mask >>= 1);
1204            return weight;
1205    }
1206    
1207    static BOOL
1208    select_visual()
1209  {  {
1210          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1211          uint16 test;          int pixmap_formats_count, visuals_count;
1212            XVisualInfo *vmatches = NULL;
1213            XVisualInfo template;
1214          int i;          int i;
1215            unsigned red_weight, blue_weight, green_weight;
1216    
1217            red_weight = blue_weight = green_weight = 0;
1218    
1219          display = XOpenDisplay(NULL);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1220          if (display == NULL)          if (pfm == NULL)
1221          {          {
1222                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1223                    XCloseDisplay(g_display);
1224                  return False;                  return False;
1225          }          }
1226    
1227          x_socket = ConnectionNumber(display);          /* Search for best TrueColor visual */
1228          screen = DefaultScreenOfDisplay(display);          template.class = TrueColor;
1229          visual = DefaultVisualOfScreen(screen);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1230          depth = DefaultDepthOfScreen(screen);          g_visual = NULL;
1231            g_no_translate_image = False;
1232            g_compatible_arch = False;
1233            if (vmatches != NULL)
1234            {
1235                    for (i = 0; i < visuals_count; ++i)
1236                    {
1237                            XVisualInfo *visual_info = &vmatches[i];
1238    
1239          pfm = XListPixmapFormats(display, &i);                          /* Try to find a no-translation visual that'll
1240          if (pfm != NULL)                             allow us to use RDP bitmaps directly as ZPixmaps. */
1241                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1242                                                   /* R5G5B5 */
1243                                                   (visual_info->red_mask == 0x7c00) &&
1244                                                   (visual_info->green_mask == 0x3e0) &&
1245                                                   (visual_info->blue_mask == 0x1f)) ||
1246                                                  ((visual_info->depth == 16) &&
1247                                                   /* R5G6B5 */
1248                                                   (visual_info->red_mask == 0xf800) &&
1249                                                   (visual_info->green_mask == 0x7e0) &&
1250                                                   (visual_info->blue_mask == 0x1f)) ||
1251                                                  ((visual_info->depth == 24) &&
1252                                                   /* R8G8B8 */
1253                                                   (visual_info->red_mask == 0xff0000) &&
1254                                                   (visual_info->green_mask == 0xff00) &&
1255                                                   (visual_info->blue_mask == 0xff))))
1256                            {
1257                                    g_visual = visual_info->visual;
1258                                    g_depth = visual_info->depth;
1259                                    g_compatible_arch = !g_host_be;
1260                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1261                                    if (g_no_translate_image)
1262                                            /* We found the best visual */
1263                                            break;
1264                            }
1265                            else
1266                            {
1267                                    g_compatible_arch = False;
1268                            }
1269    
1270                            if (visual_info->depth > 24)
1271                            {
1272                                    /* Avoid 32-bit visuals and likes like the plague.
1273                                       They're either untested or proven to work bad
1274                                       (e.g. nvidia's Composite 32-bit visual).
1275                                       Most implementation offer a 24-bit visual anyway. */
1276                                    continue;
1277                            }
1278    
1279                            /* Only care for visuals, for whose BPPs (not depths!)
1280                               we have a translateXtoY function. */
1281                            BOOL can_translate_to_bpp = False;
1282                            int j;
1283                            for (j = 0; j < pixmap_formats_count; ++j)
1284                            {
1285                                    if (pfm[j].depth == visual_info->depth)
1286                                    {
1287                                            if ((pfm[j].bits_per_pixel == 16) ||
1288                                                (pfm[j].bits_per_pixel == 24) ||
1289                                                (pfm[j].bits_per_pixel == 32))
1290                                            {
1291                                                    can_translate_to_bpp = True;
1292                                            }
1293                                            break;
1294                                    }
1295                            }
1296    
1297                            /* Prefer formats which have the most colour depth.
1298                               We're being truly aristocratic here, minding each
1299                               weight on its own. */
1300                            if (can_translate_to_bpp)
1301                            {
1302                                    unsigned vis_red_weight =
1303                                            calculate_mask_weight(visual_info->red_mask);
1304                                    unsigned vis_green_weight =
1305                                            calculate_mask_weight(visual_info->green_mask);
1306                                    unsigned vis_blue_weight =
1307                                            calculate_mask_weight(visual_info->blue_mask);
1308                                    if ((vis_red_weight >= red_weight)
1309                                        && (vis_green_weight >= green_weight)
1310                                        && (vis_blue_weight >= blue_weight))
1311                                    {
1312                                            red_weight = vis_red_weight;
1313                                            green_weight = vis_green_weight;
1314                                            blue_weight = vis_blue_weight;
1315                                            g_visual = visual_info->visual;
1316                                            g_depth = visual_info->depth;
1317                                    }
1318                            }
1319                    }
1320                    XFree(vmatches);
1321            }
1322    
1323            if (g_visual != NULL)
1324            {
1325                    g_owncolmap = False;
1326                    calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1327                    calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1328                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1329            }
1330            else
1331          {          {
1332                  /* Use maximum bpp for this depth - this is generally                  template.class = PseudoColor;
1333                     desirable, e.g. 24 bits->32 bits. */                  template.depth = 8;
1334                  while (i--)                  template.colormap_size = 256;
1335                    vmatches =
1336                            XGetVisualInfo(g_display,
1337                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1338                                           &template, &visuals_count);
1339                    if (vmatches == NULL)
1340                  {                  {
1341                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))                          error("No usable TrueColor or PseudoColor visuals on this display.\n");
1342                            XCloseDisplay(g_display);
1343                            XFree(pfm);
1344                            return False;
1345                    }
1346    
1347                    /* we use a colourmap, so the default visual should do */
1348                    g_owncolmap = True;
1349                    g_visual = vmatches[0].visual;
1350                    g_depth = vmatches[0].depth;
1351            }
1352    
1353            g_bpp = 0;
1354            for (i = 0; i < pixmap_formats_count; ++i)
1355            {
1356                    XPixmapFormatValues *pf = &pfm[i];
1357                    if (pf->depth == g_depth)
1358                    {
1359                            g_bpp = pf->bits_per_pixel;
1360    
1361                            if (g_no_translate_image)
1362                          {                          {
1363                                  bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1364                                    {
1365                                            case 15:
1366                                            case 16:
1367                                                    if (g_bpp != 16)
1368                                                            g_no_translate_image = False;
1369                                                    break;
1370                                            case 24:
1371                                                    /* Yes, this will force image translation
1372                                                       on most modern servers which use 32 bits
1373                                                       for R8G8B8. */
1374                                                    if (g_bpp != 24)
1375                                                            g_no_translate_image = False;
1376                                                    break;
1377                                            default:
1378                                                    g_no_translate_image = False;
1379                                                    break;
1380                                    }
1381                          }                          }
1382    
1383                            /* Pixmap formats list is a depth-to-bpp mapping --
1384                               there's just a single entry for every depth,
1385                               so we can safely break here */
1386                            break;
1387                  }                  }
1388                  XFree(pfm);          }
1389            XFree(pfm);
1390            pfm = NULL;
1391            return True;
1392    }
1393    
1394    BOOL
1395    ui_init(void)
1396    {
1397            int screen_num;
1398    
1399            g_display = XOpenDisplay(NULL);
1400            if (g_display == NULL)
1401            {
1402                    error("Failed to open display: %s\n", XDisplayName(NULL));
1403                    return False;
1404          }          }
1405    
         if (bpp < 8)  
1406          {          {
1407                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1408                  XCloseDisplay(display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1409            }
1410    
1411            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1412            screen_num = DefaultScreen(g_display);
1413            g_x_socket = ConnectionNumber(g_display);
1414            g_screen = ScreenOfDisplay(g_display, screen_num);
1415            g_depth = DefaultDepthOfScreen(g_screen);
1416    
1417            if (!select_visual())
1418                  return False;                  return False;
1419    
1420            if (g_no_translate_image)
1421            {
1422                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1423          }          }
1424    
1425          if (owncolmap != True)          if (g_server_depth > g_bpp)
1426          {          {
1427                  xcolmap = DefaultColormapOfScreen(screen);                  warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1428                  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");  
1429          }          }
1430    
1431          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",
1432                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1433    
1434          if (DoesBackingStore(screen) != Always)          if (!g_owncolmap)
1435                  ownbackstore = True;          {
1436                    g_xcolmap =
1437                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1438                                            AllocNone);
1439                    if (g_depth <= 8)
1440                            warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1441            }
1442    
1443          test = 1;          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1444          host_be = !(BOOL) (*(uint8 *) (&test));          {
1445          xserver_be = (ImageByteOrder(display) == MSBFirst);                  warning("External BackingStore not available. Using internal.\n");
1446                    g_ownbackstore = True;
1447            }
1448    
1449          if ((width == 0) || (height == 0))          /*
1450             * Determine desktop size
1451             */
1452            if (g_fullscreen)
1453            {
1454                    g_width = WidthOfScreen(g_screen);
1455                    g_height = HeightOfScreen(g_screen);
1456                    g_using_full_workarea = True;
1457            }
1458            else if (g_width < 0)
1459            {
1460                    /* Percent of screen */
1461                    if (-g_width >= 100)
1462                            g_using_full_workarea = True;
1463                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1464                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1465            }
1466            else if (g_width == 0)
1467          {          {
1468                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1469                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1470                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1471                  {                  {
1472                          width = cx;                          g_width = cx;
1473                          height = cy;                          g_height = cy;
1474                            g_using_full_workarea = True;
1475                  }                  }
1476                  else                  else
1477                  {                  {
1478                          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");
1479                          width = 800;                          g_width = WidthOfScreen(g_screen);
1480                          height = 600;                          g_height = HeightOfScreen(g_screen);
1481                  }                  }
1482          }          }
1483    
         if (fullscreen)  
         {  
                 width = WidthOfScreen(screen);  
                 height = HeightOfScreen(screen);  
         }  
   
1484          /* make sure width is a multiple of 4 */          /* make sure width is a multiple of 4 */
1485          width = (width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1486    
1487          if (ownbackstore)          g_mod_map = XGetModifierMapping(g_display);
         {  
                 backstore =  
                         XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);  
   
                 /* clear to prevent rubbish being exposed at startup */  
                 XSetForeground(display, gc, BlackPixelOfScreen(screen));  
                 XFillRectangle(display, backstore, gc, 0, 0, width, height);  
         }  
1488    
1489          mod_map = XGetModifierMapping(display);          xkeymap_init();
1490    
1491          if (enable_compose)          if (g_enable_compose)
1492                  IM = XOpenIM(display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1493    
1494          xkeymap_init();          xclip_init();
1495            ewmh_init();
1496            if (g_seamless_rdp)
1497                    seamless_init();
1498    
1499          /* 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);  
1500    
1501          return True;          return True;
1502  }  }
# Line 620  ui_init(void) Line 1504  ui_init(void)
1504  void  void
1505  ui_deinit(void)  ui_deinit(void)
1506  {  {
1507          if (IM != NULL)          if (g_IM != NULL)
1508                  XCloseIM(IM);                  XCloseIM(g_IM);
1509    
1510            if (g_null_cursor != NULL)
1511                    ui_destroy_cursor(g_null_cursor);
1512    
1513            XFreeModifiermap(g_mod_map);
1514    
1515            if (g_ownbackstore)
1516                    XFreePixmap(g_display, g_backstore);
1517    
1518            XFreeGC(g_display, g_gc);
1519            XCloseDisplay(g_display);
1520            g_display = NULL;
1521    }
1522    
         XFreeModifiermap(mod_map);  
1523    
1524          if (ownbackstore)  static void
1525                  XFreePixmap(display, backstore);  get_window_attribs(XSetWindowAttributes * attribs)
1526    {
1527            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1528            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1529            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1530            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1531            attribs->override_redirect = g_fullscreen;
1532            attribs->colormap = g_xcolmap;
1533    }
1534    
1535          XFreeGC(display, gc);  static void
1536          XCloseDisplay(display);  get_input_mask(long *input_mask)
1537          display = NULL;  {
1538            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1539                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1540    
1541            if (g_sendmotion)
1542                    *input_mask |= PointerMotionMask;
1543            if (g_ownbackstore)
1544                    *input_mask |= ExposureMask;
1545            if (g_fullscreen || g_grab_keyboard)
1546                    *input_mask |= EnterWindowMask;
1547            if (g_grab_keyboard)
1548                    *input_mask |= LeaveWindowMask;
1549  }  }
1550    
1551  BOOL  BOOL
1552  ui_create_window(void)  ui_create_window(void)
1553  {  {
1554            uint8 null_pointer_mask[1] = { 0x80 };
1555            uint8 null_pointer_data[24] = { 0x00 };
1556    
1557          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1558          XClassHint *classhints;          XClassHint *classhints;
1559          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 643  ui_create_window(void) Line 1561  ui_create_window(void)
1561          long input_mask, ic_input_mask;          long input_mask, ic_input_mask;
1562          XEvent xevent;          XEvent xevent;
1563    
1564          wndwidth = fullscreen ? WidthOfScreen(screen) : width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1565          wndheight = fullscreen ? HeightOfScreen(screen) : height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1566    
1567          attribs.background_pixel = BlackPixelOfScreen(screen);          /* Handle -x-y portion of geometry string */
1568          attribs.backing_store = ownbackstore ? NotUseful : Always;          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1569          attribs.override_redirect = fullscreen;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1570            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1571                    g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1572    
1573          wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,          get_window_attribs(&attribs);
                             0, CopyFromParent, InputOutput, CopyFromParent,  
                             CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);  
1574    
1575          XStoreName(display, wnd, title);          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1576                                  wndheight, 0, g_depth, InputOutput, g_visual,
1577                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1578                                  CWBorderPixel, &attribs);
1579    
1580          if (hide_decorations)          if (g_gc == NULL)
1581                  mwm_hide_decorations();          {
1582                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1583                    ui_reset_clip();
1584            }
1585    
1586            if (g_create_bitmap_gc == NULL)
1587                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1588    
1589            if ((g_ownbackstore) && (g_backstore == 0))
1590            {
1591                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1592    
1593                    /* clear to prevent rubbish being exposed at startup */
1594                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1595                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1596            }
1597    
1598            XStoreName(g_display, g_wnd, g_title);
1599    
1600            if (g_hide_decorations)
1601                    mwm_hide_decorations(g_wnd);
1602    
1603          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1604          if (classhints != NULL)          if (classhints != NULL)
1605          {          {
1606                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
1607                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
1608                  XFree(classhints);                  XFree(classhints);
1609          }          }
1610    
# Line 671  ui_create_window(void) Line 1612  ui_create_window(void)
1612          if (sizehints)          if (sizehints)
1613          {          {
1614                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1615                  sizehints->min_width = sizehints->max_width = width;                  if (g_pos)
1616                  sizehints->min_height = sizehints->max_height = height;                          sizehints->flags |= PPosition;
1617                  XSetWMNormalHints(display, wnd, sizehints);                  sizehints->min_width = sizehints->max_width = g_width;
1618                    sizehints->min_height = sizehints->max_height = g_height;
1619                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1620                  XFree(sizehints);                  XFree(sizehints);
1621          }          }
1622    
1623          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          if (g_embed_wnd)
1624                  VisibilityChangeMask | FocusChangeMask;          {
1625                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1626            }
1627    
1628          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;  
1629    
1630          if (IM != NULL)          if (g_IM != NULL)
1631          {          {
1632                  IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),                  g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1633                                 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);                                   XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1634    
1635                  if ((IC != NULL)                  if ((g_IC != NULL)
1636                      && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1637                          input_mask |= ic_input_mask;                          input_mask |= ic_input_mask;
1638          }          }
1639    
1640          XSelectInput(display, wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
         XMapWindow(display, wnd);  
1641    
1642            XMapWindow(g_display, g_wnd);
1643          /* wait for VisibilityNotify */          /* wait for VisibilityNotify */
1644          do          do
1645          {          {
1646                  XMaskEvent(display, VisibilityChangeMask, &xevent);                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1647          }          }
1648          while (xevent.type != VisibilityNotify);          while (xevent.type != VisibilityNotify);
1649            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1650    
1651          focused = False;          g_focused = False;
1652          mouse_in_wnd = False;          g_mouse_in_wnd = False;
1653    
1654          /* handle the WM_DELETE_WINDOW protocol */          /* handle the WM_DELETE_WINDOW protocol */
1655          protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);          g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1656          kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);          g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1657          XSetWMProtocols(display, wnd, &kill_atom, 1);          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1658    
1659            /* create invisible 1x1 cursor to be used as null cursor */
1660            if (g_null_cursor == NULL)
1661                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1662    
1663          return True;          return True;
1664  }  }
1665    
1666  void  void
1667    ui_resize_window()
1668    {
1669            XSizeHints *sizehints;
1670            Pixmap bs;
1671    
1672            sizehints = XAllocSizeHints();
1673            if (sizehints)
1674            {
1675                    sizehints->flags = PMinSize | PMaxSize;
1676                    sizehints->min_width = sizehints->max_width = g_width;
1677                    sizehints->min_height = sizehints->max_height = g_height;
1678                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1679                    XFree(sizehints);
1680            }
1681    
1682            if (!(g_fullscreen || g_embed_wnd))
1683            {
1684                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1685            }
1686    
1687            /* create new backstore pixmap */
1688            if (g_backstore != 0)
1689            {
1690                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1691                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1692                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1693                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1694                    XFreePixmap(g_display, g_backstore);
1695                    g_backstore = bs;
1696            }
1697    }
1698    
1699    void
1700  ui_destroy_window(void)  ui_destroy_window(void)
1701  {  {
1702          if (IC != NULL)          if (g_IC != NULL)
1703                  XDestroyIC(IC);                  XDestroyIC(g_IC);
1704    
1705          XDestroyWindow(display, wnd);          XDestroyWindow(g_display, g_wnd);
1706  }  }
1707    
1708  void  void
# Line 734  xwin_toggle_fullscreen(void) Line 1710  xwin_toggle_fullscreen(void)
1710  {  {
1711          Pixmap contents = 0;          Pixmap contents = 0;
1712    
1713          if (!ownbackstore)          if (g_seamless_active)
1714                    /* Turn off SeamlessRDP mode */
1715                    ui_seamless_toggle();
1716    
1717            if (!g_ownbackstore)
1718          {          {
1719                  /* need to save contents of window */                  /* need to save contents of window */
1720                  contents = XCreatePixmap(display, wnd, width, height, depth);                  contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1721                  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);
1722          }          }
1723    
1724          ui_destroy_window();          ui_destroy_window();
1725          fullscreen = !fullscreen;          g_fullscreen = !g_fullscreen;
1726          ui_create_window();          ui_create_window();
1727    
1728          XDefineCursor(display, wnd, current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
1729    
1730            if (!g_ownbackstore)
1731            {
1732                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1733                    XFreePixmap(g_display, contents);
1734            }
1735    }
1736    
1737    static void
1738    handle_button_event(XEvent xevent, BOOL down)
1739    {
1740            uint16 button, flags = 0;
1741            g_last_gesturetime = xevent.xbutton.time;
1742            button = xkeymap_translate_button(xevent.xbutton.button);
1743            if (button == 0)
1744                    return;
1745    
1746            if (down)
1747                    flags = MOUSE_FLAG_DOWN;
1748    
1749            /* Stop moving window when button is released, regardless of cursor position */
1750            if (g_moving_wnd && (xevent.type == ButtonRelease))
1751                    g_moving_wnd = False;
1752    
1753            /* If win_button_size is nonzero, enable single app mode */
1754            if (xevent.xbutton.y < g_win_button_size)
1755            {
1756                    /*  Check from right to left: */
1757                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1758                    {
1759                            /* The close button, continue */
1760                            ;
1761                    }
1762                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1763                    {
1764                            /* The maximize/restore button. Do not send to
1765                               server.  It might be a good idea to change the
1766                               cursor or give some other visible indication
1767                               that rdesktop inhibited this click */
1768                            if (xevent.type == ButtonPress)
1769                                    return;
1770                    }
1771                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1772                    {
1773                            /* The minimize button. Iconify window. */
1774                            if (xevent.type == ButtonRelease)
1775                            {
1776                                    /* Release the mouse button outside the minimize button, to prevent the
1777                                       actual minimazation to happen */
1778                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1779                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1780                                    return;
1781                            }
1782                    }
1783                    else if (xevent.xbutton.x <= g_win_button_size)
1784                    {
1785                            /* The system menu. Ignore. */
1786                            if (xevent.type == ButtonPress)
1787                                    return;
1788                    }
1789                    else
1790                    {
1791                            /* The title bar. */
1792                            if (xevent.type == ButtonPress)
1793                            {
1794                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1795                                    {
1796                                            g_moving_wnd = True;
1797                                            g_move_x_offset = xevent.xbutton.x;
1798                                            g_move_y_offset = xevent.xbutton.y;
1799                                    }
1800                                    return;
1801                            }
1802                    }
1803            }
1804    
1805          if (!ownbackstore)          if (xevent.xmotion.window == g_wnd)
1806          {          {
1807                  XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1808                  XFreePixmap(display, contents);                                 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1809            }
1810            else
1811            {
1812                    /* SeamlessRDP */
1813                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1814                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1815          }          }
1816  }  }
1817    
1818  /* Process all events in Xlib queue  static void
1819    ui_seamless_handle_restack(seamless_window * sw)
1820    {
1821            Status status;
1822            Window root, parent, *children;
1823            unsigned int nchildren, i;
1824            seamless_window *sw_below;
1825    
1826            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
1827                                &root, &parent, &children, &nchildren);
1828            if (!status || !nchildren)
1829                    return;
1830    
1831            sw_below = NULL;
1832    
1833            i = 0;
1834            while (children[i] != sw->wnd)
1835            {
1836                    i++;
1837                    if (i >= nchildren)
1838                            return;
1839            }
1840    
1841            for (i++; i < nchildren; i++)
1842            {
1843                    sw_below = seamless_get_window_by_wnd(children[i]);
1844                    if (sw_below)
1845                            break;
1846            }
1847    
1848            if (!sw_below && !sw->behind)
1849                    return;
1850            if (sw_below && (sw_below->id == sw->behind))
1851                    return;
1852    
1853            if (sw_below)
1854            {
1855                    seamless_send_zchange(sw->id, sw_below->id, 0);
1856                    seamless_restack_window(sw, sw_below->id);
1857            }
1858            else
1859            {
1860                    seamless_send_zchange(sw->id, 0, 0);
1861                    seamless_restack_window(sw, 0);
1862            }
1863    }
1864    
1865    /* Process events in Xlib queue
1866     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1867  static int  static int
1868  xwin_process_events(void)  xwin_process_events(void)
1869  {  {
1870          XEvent xevent;          XEvent xevent;
1871          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1872          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1873          char str[256];          char str[256];
1874          Status status;          Status status;
1875          unsigned int state;          int events = 0;
1876          Window wdummy;          seamless_window *sw;
         int dummy;  
1877    
1878          while (XPending(display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1879          {          {
1880                  XNextEvent(display, &xevent);                  XNextEvent(g_display, &xevent);
1881    
1882                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1883                  {                  {
1884                          DEBUG_KBD(("Filtering event\n"));                          DEBUG_KBD(("Filtering event\n"));
1885                          continue;                          continue;
1886                  }                  }
1887    
                 flags = 0;  
   
1888                  switch (xevent.type)                  switch (xevent.type)
1889                  {                  {
1890                            case VisibilityNotify:
1891                                    if (xevent.xvisibility.window == g_wnd)
1892                                            g_Unobscured =
1893                                                    xevent.xvisibility.state == VisibilityUnobscured;
1894    
1895                                    break;
1896                          case ClientMessage:                          case ClientMessage:
1897                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1898                                  if ((xevent.xclient.message_type == protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
1899                                      && ((Atom)xevent.xclient.data.l[0] == kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1900                                          /* Quit */                                          /* Quit */
1901                                          return 0;                                          return 0;
1902                                  break;                                  break;
1903    
1904                          case KeyPress:                          case KeyPress:
1905                                  if (IC != NULL)                                  g_last_gesturetime = xevent.xkey.time;
1906                                    if (g_IC != NULL)
1907                                          /* Multi_key compatible version */                                          /* Multi_key compatible version */
1908                                  {                                  {
1909                                          XmbLookupString(IC,                                          XmbLookupString(g_IC,
1910                                                          (XKeyPressedEvent *) &                                                          &xevent.xkey, str, sizeof(str), &keysym,
1911                                                          xevent, str, sizeof(str), &keysym, &status);                                                          &status);
1912                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1913                                          {                                          {
1914                                                  error("XmbLookupString failed with status 0x%x\n",                                                  error("XmbLookupString failed with status 0x%x\n",
# Line 814  xwin_process_events(void) Line 1924  xwin_process_events(void)
1924                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1925                                  }                                  }
1926    
1927                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1928                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1929    
1930                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1931                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1932                                          break;                                          break;
1933    
1934                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1935                                                             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);  
1936                                  break;                                  break;
1937    
1938                          case KeyRelease:                          case KeyRelease:
1939                                    g_last_gesturetime = xevent.xkey.time;
1940                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1941                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1942    
1943                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1944                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1945    
1946                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1947                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1948                                          break;                                          break;
1949    
1950                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1951                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1952                                  break;                                  break;
1953    
1954                          case ButtonPress:                          case ButtonPress:
1955                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1956                                  /* fall through */                                  break;
1957    
1958                          case ButtonRelease:                          case ButtonRelease:
1959                                  button = xkeymap_translate_button(xevent.xbutton.button);                                  handle_button_event(xevent, False);
                                 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);  
1960                                  break;                                  break;
1961    
1962                          case MotionNotify:                          case MotionNotify:
1963                                  if (moving_wnd)                                  if (g_moving_wnd)
1964                                  {                                  {
1965                                          XMoveWindow(display, wnd,                                          XMoveWindow(g_display, g_wnd,
1966                                                      xevent.xmotion.x_root - move_x_offset,                                                      xevent.xmotion.x_root - g_move_x_offset,
1967                                                      xevent.xmotion.y_root - move_y_offset);                                                      xevent.xmotion.y_root - g_move_y_offset);
1968                                          break;                                          break;
1969                                  }                                  }
1970    
1971                                  if (fullscreen && !focused)                                  if (g_fullscreen && !g_focused)
1972                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1973                                                         CurrentTime);                                                         CurrentTime);
1974                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1975                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1976                                    {
1977                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1978                                                           xevent.xmotion.x, xevent.xmotion.y);
1979                                    }
1980                                    else
1981                                    {
1982                                            /* SeamlessRDP */
1983                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1984                                                           xevent.xmotion.x_root,
1985                                                           xevent.xmotion.y_root);
1986                                    }
1987                                  break;                                  break;
1988    
1989                          case FocusIn:                          case FocusIn:
1990                                  if (xevent.xfocus.mode == NotifyGrab)                                  if (xevent.xfocus.mode == NotifyGrab)
1991                                          break;                                          break;
1992                                  focused = True;                                  g_focused = True;
1993                                  XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,                                  reset_modifier_keys();
1994                                                &dummy, &dummy, &state);                                  if (g_grab_keyboard && g_mouse_in_wnd)
1995                                  reset_modifier_keys(state);                                          XGrabKeyboard(g_display, g_wnd, True,
                                 if (grab_keyboard && mouse_in_wnd)  
                                         XGrabKeyboard(display, wnd, True,  
1996                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1997    
1998                                    sw = seamless_get_window_by_wnd(xevent.xfocus.window);
1999                                    if (!sw)
2000                                            break;
2001    
2002                                    if (sw->id != g_seamless_focused)
2003                                    {
2004                                            seamless_send_focus(sw->id, 0);
2005                                            g_seamless_focused = sw->id;
2006                                    }
2007                                  break;                                  break;
2008    
2009                          case FocusOut:                          case FocusOut:
2010                                  if (xevent.xfocus.mode == NotifyUngrab)                                  if (xevent.xfocus.mode == NotifyUngrab)
2011                                          break;                                          break;
2012                                  focused = False;                                  g_focused = False;
2013                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)
2014                                          XUngrabKeyboard(display, CurrentTime);                                          XUngrabKeyboard(g_display, CurrentTime);
2015                                  break;                                  break;
2016    
2017                          case EnterNotify:                          case EnterNotify:
2018                                  /* we only register for this event when in fullscreen mode */                                  /* we only register for this event when in fullscreen mode */
2019                                  /* or grab_keyboard */                                  /* or grab_keyboard */
2020                                  mouse_in_wnd = True;                                  g_mouse_in_wnd = True;
2021                                  if (fullscreen)                                  if (g_fullscreen)
2022                                  {                                  {
2023                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2024                                                         CurrentTime);                                                         CurrentTime);
2025                                          break;                                          break;
2026                                  }                                  }
2027                                  if (focused)                                  if (g_focused)
2028                                          XGrabKeyboard(display, wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2029                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2030                                  break;                                  break;
2031    
2032                          case LeaveNotify:                          case LeaveNotify:
2033                                  /* we only register for this event when grab_keyboard */                                  /* we only register for this event when grab_keyboard */
2034                                  mouse_in_wnd = False;                                  g_mouse_in_wnd = False;
2035                                  XUngrabKeyboard(display, CurrentTime);                                  XUngrabKeyboard(g_display, CurrentTime);
2036                                  break;                                  break;
2037    
2038                          case Expose:                          case Expose:
2039                                  XCopyArea(display, backstore, wnd, gc,                                  if (xevent.xexpose.window == g_wnd)
2040                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2041                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2042                                            xevent.xexpose.height,                                                    g_gc,
2043                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2044                                                      xevent.xexpose.width, xevent.xexpose.height,
2045                                                      xevent.xexpose.x, xevent.xexpose.y);
2046                                    }
2047                                    else
2048                                    {
2049                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
2050                                            if (sw)
2051                                                    XCopyArea(g_display, g_backstore,
2052                                                              xevent.xexpose.window, g_gc,
2053                                                              xevent.xexpose.x + sw->xoffset,
2054                                                              xevent.xexpose.y + sw->yoffset,
2055                                                              xevent.xexpose.width,
2056                                                              xevent.xexpose.height, xevent.xexpose.x,
2057                                                              xevent.xexpose.y);
2058                                            else
2059                                            {
2060                                                    error("Expose for unknown window 0x%lx\n",
2061                                                          xevent.xexpose.window);
2062                                            }
2063                                    }
2064    
2065                                  break;                                  break;
2066    
2067                          case MappingNotify:                          case MappingNotify:
# Line 988  xwin_process_events(void) Line 2073  xwin_process_events(void)
2073    
2074                                  if (xevent.xmapping.request == MappingModifier)                                  if (xevent.xmapping.request == MappingModifier)
2075                                  {                                  {
2076                                          XFreeModifiermap(mod_map);                                          XFreeModifiermap(g_mod_map);
2077                                          mod_map = XGetModifierMapping(display);                                          g_mod_map = XGetModifierMapping(g_display);
2078                                  }                                  }
2079                                  break;                                  break;
2080    
2081                                    /* clipboard stuff */
2082                            case SelectionNotify:
2083                                    xclip_handle_SelectionNotify(&xevent.xselection);
2084                                    break;
2085                            case SelectionRequest:
2086                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
2087                                    break;
2088                            case SelectionClear:
2089                                    xclip_handle_SelectionClear();
2090                                    break;
2091                            case PropertyNotify:
2092                                    xclip_handle_PropertyNotify(&xevent.xproperty);
2093                                    if (xevent.xproperty.window == g_wnd)
2094                                            break;
2095                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2096                                            break;
2097    
2098                                    /* seamless */
2099                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
2100                                    if (!sw)
2101                                            break;
2102    
2103                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2104                                        && (xevent.xproperty.state == PropertyNewValue))
2105                                    {
2106                                            sw->state = ewmh_get_window_state(sw->wnd);
2107                                            seamless_send_state(sw->id, sw->state, 0);
2108                                    }
2109    
2110                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2111                                        && (xevent.xproperty.state == PropertyNewValue))
2112                                    {
2113                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2114                                            seamless_all_to_desktop(sw->wnd, sw->desktop);
2115                                    }
2116    
2117                                    break;
2118                            case MapNotify:
2119                                    if (!g_seamless_active)
2120                                            rdp_send_client_window_status(1);
2121                                    break;
2122                            case UnmapNotify:
2123                                    if (!g_seamless_active)
2124                                            rdp_send_client_window_status(0);
2125                                    break;
2126                            case ConfigureNotify:
2127                                    if (!g_seamless_active)
2128                                            break;
2129    
2130                                    sw = seamless_get_window_by_wnd(xevent.xconfigure.window);
2131                                    if (!sw)
2132                                    {
2133                                            error("ConfigureNotify for unknown window 0x%lx\n",
2134                                                  xevent.xconfigure.window);
2135                                    }
2136    
2137                                    gettimeofday(sw->position_timer, NULL);
2138                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2139                                        1000000)
2140                                    {
2141                                            sw->position_timer->tv_usec +=
2142                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2143                                            sw->position_timer->tv_sec += 1;
2144                                    }
2145                                    else
2146                                    {
2147                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2148                                    }
2149    
2150                                    ui_seamless_handle_restack(sw);
2151                                    break;
2152                  }                  }
2153          }          }
2154          /* Keep going */          /* Keep going */
# Line 1003  xwin_process_events(void) Line 2159  xwin_process_events(void)
2159  int  int
2160  ui_select(int rdp_socket)  ui_select(int rdp_socket)
2161  {  {
2162          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;          int n;
2163          fd_set rfds;          fd_set rfds, wfds;
2164            struct timeval tv;
2165          FD_ZERO(&rfds);          BOOL s_timeout = False;
2166    
2167          while (True)          while (True)
2168          {          {
2169                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
2170                  /* Process any events already waiting */                  /* Process any events already waiting */
2171                  if (!xwin_process_events())                  if (!xwin_process_events())
2172                          /* User quit */                          /* User quit */
2173                          return 0;                          return 0;
2174    
2175                    if (g_seamless_active)
2176                            seamless_check_timers();
2177    
2178                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2179                    FD_ZERO(&wfds);
2180                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
2181                  FD_SET(x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
2182    
2183                  switch (select(n, &rfds, NULL, NULL, NULL))  #ifdef WITH_RDPSND
2184                    /* FIXME: there should be an API for registering fds */
2185                    if (g_dsp_busy)
2186                    {
2187                            FD_SET(g_dsp_fd, &wfds);
2188                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
2189                    }
2190    #endif
2191                    /* default timeout */
2192                    tv.tv_sec = 60;
2193                    tv.tv_usec = 0;
2194    
2195                    /* add redirection handles */
2196                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2197                    seamless_select_timeout(&tv);
2198    
2199                    n++;
2200    
2201                    switch (select(n, &rfds, &wfds, NULL, &tv))
2202                  {                  {
2203                          case -1:                          case -1:
2204                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2205    
2206                          case 0:                          case 0:
2207                                    /* Abort serial read calls */
2208                                    if (s_timeout)
2209                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
2210                                  continue;                                  continue;
2211                  }                  }
2212    
2213                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
2214    
2215                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2216                          return 1;                          return 1;
2217    
2218    #ifdef WITH_RDPSND
2219                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
2220                            wave_out_play();
2221    #endif
2222          }          }
2223  }  }
2224    
2225  void  void
2226  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
2227  {  {
2228          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
2229  }  }
2230    
2231  HBITMAP  HBITMAP
# Line 1045  ui_create_bitmap(int width, int height, Line 2234  ui_create_bitmap(int width, int height,
2234          XImage *image;          XImage *image;
2235          Pixmap bitmap;          Pixmap bitmap;
2236          uint8 *tdata;          uint8 *tdata;
2237            int bitmap_pad;
2238    
2239            if (g_server_depth == 8)
2240            {
2241                    bitmap_pad = 8;
2242            }
2243            else
2244            {
2245                    bitmap_pad = g_bpp;
2246    
2247          tdata = (owncolmap ? data : translate_image(width, height, data));                  if (g_bpp == 24)
2248          bitmap = XCreatePixmap(display, wnd, width, height, depth);                          bitmap_pad = 32;
2249          image = XCreateImage(display, visual, depth, ZPixmap, 0,          }
2250                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);  
2251            tdata = (g_owncolmap ? data : translate_image(width, height, data));
2252            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
2253            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2254                                 (char *) tdata, width, height, bitmap_pad, 0);
2255    
2256          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);
2257    
2258          XFree(image);          XFree(image);
2259          if (!owncolmap)          if (tdata != data)
2260                  xfree(tdata);                  xfree(tdata);
2261          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
2262  }  }
# Line 1064  ui_paint_bitmap(int x, int y, int cx, in Line 2266  ui_paint_bitmap(int x, int y, int cx, in
2266  {  {
2267          XImage *image;          XImage *image;
2268          uint8 *tdata;          uint8 *tdata;
2269          tdata = (owncolmap ? data : translate_image(width, height, data));          int bitmap_pad;
2270          image = XCreateImage(display, visual, depth, ZPixmap, 0,  
2271                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);          if (g_server_depth == 8)
2272            {
2273                    bitmap_pad = 8;
2274            }
2275            else
2276            {
2277                    bitmap_pad = g_bpp;
2278    
2279                    if (g_bpp == 24)
2280                            bitmap_pad = 32;
2281            }
2282    
2283            tdata = (g_owncolmap ? data : translate_image(width, height, data));
2284            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2285                                 (char *) tdata, width, height, bitmap_pad, 0);
2286    
2287          if (ownbackstore)          if (g_ownbackstore)
2288          {          {
2289                  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);
2290                  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);
2291                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2292                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2293                                             x - sw->xoffset, y - sw->yoffset));
2294          }          }
2295          else          else
2296          {          {
2297                  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);
2298                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2299                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2300                                             x - sw->xoffset, y - sw->yoffset));
2301          }          }
2302    
2303          XFree(image);          XFree(image);
2304          if (!owncolmap)          if (tdata != data)
2305                  xfree(tdata);                  xfree(tdata);
2306  }  }
2307    
2308  void  void
2309  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
2310  {  {
2311          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2312  }  }
2313    
2314  HGLYPH  HGLYPH
# Line 1095  ui_create_glyph(int width, int height, u Line 2317  ui_create_glyph(int width, int height, u
2317          XImage *image;          XImage *image;
2318          Pixmap bitmap;          Pixmap bitmap;
2319          int scanline;          int scanline;
         GC gc;  
2320    
2321          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
2322    
2323          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
2324          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
2325                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
2326    
2327          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
2328                               width, height, 8, scanline);                               width, height, 8, scanline);
2329          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
2330          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
2331          XInitImage(image);          XInitImage(image);
2332    
2333          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);
2334    
2335          XFree(image);          XFree(image);
         XFreeGC(display, gc);  
2336          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
2337  }  }
2338    
2339  void  void
2340  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
2341  {  {
2342          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2343  }  }
2344    
2345  HCURSOR  HCURSOR
# Line 1137  ui_create_cursor(unsigned int x, unsigne Line 2358  ui_create_cursor(unsigned int x, unsigne
2358          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
2359          offset = scanline * height;          offset = scanline * height;
2360    
2361          cursor = (uint8*)xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
2362          memset(cursor, 0, offset);          memset(cursor, 0, offset);
2363    
2364          mask = (uint8*)xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
2365          memset(mask, 0, offset);          memset(mask, 0, offset);
2366    
2367          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 1182  ui_create_cursor(unsigned int x, unsigne Line 2403  ui_create_cursor(unsigned int x, unsigne
2403          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
2404    
2405          xcursor =          xcursor =
2406                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
2407                                      (Pixmap) maskglyph, &fg, &bg, x, y);                                      (Pixmap) maskglyph, &fg, &bg, x, y);
2408    
2409          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
# Line 1195  ui_create_cursor(unsigned int x, unsigne Line 2416  ui_create_cursor(unsigned int x, unsigne
2416  void  void
2417  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
2418  {  {
2419          current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2420          XDefineCursor(display, wnd, current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2421            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2422  }  }
2423    
2424  void  void
2425  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
2426  {  {
2427          XFreeCursor(display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2428    }
2429    
2430    void
2431    ui_set_null_cursor(void)
2432    {
2433            ui_set_cursor(g_null_cursor);
2434  }  }
2435    
2436  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 1217  ui_create_colourmap(COLOURMAP * colours) Line 2445  ui_create_colourmap(COLOURMAP * colours)
2445  {  {
2446          COLOURENTRY *entry;          COLOURENTRY *entry;
2447          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
2448          if (!owncolmap)          if (!g_owncolmap)
2449          {          {
2450                  uint32 *map = (uint32*)xmalloc(sizeof(*colmap) * ncolours);                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
2451                  XColor xentry;                  XColor xentry;
2452                  XColor xc_cache[256];                  XColor xc_cache[256];
2453                  uint32 colour;                  uint32 colour;
# Line 1229  ui_create_colourmap(COLOURMAP * colours) Line 2457  ui_create_colourmap(COLOURMAP * colours)
2457                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2458                          MAKE_XCOLOR(&xentry, entry);                          MAKE_XCOLOR(&xentry, entry);
2459    
2460                          if (XAllocColor(display, xcolmap, &xentry) == 0)                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
2461                          {                          {
2462                                  /* Allocation failed, find closest match. */                                  /* Allocation failed, find closest match. */
2463                                  int j = 256;                                  int j = 256;
# Line 1243  ui_create_colourmap(COLOURMAP * colours) Line 2471  ui_create_colourmap(COLOURMAP * colours)
2471                                          xc_cache[colLookup].red = xc_cache[colLookup].green =                                          xc_cache[colLookup].red = xc_cache[colLookup].green =
2472                                                  xc_cache[colLookup].blue = 0;                                                  xc_cache[colLookup].blue = 0;
2473                                          xc_cache[colLookup].flags = 0;                                          xc_cache[colLookup].flags = 0;
2474                                          XQueryColor(display,                                          XQueryColor(g_display,
2475                                                      DefaultColormap(display,                                                      DefaultColormap(g_display,
2476                                                                      DefaultScreen(display)),                                                                      DefaultScreen(g_display)),
2477                                                      &xc_cache[colLookup]);                                                      &xc_cache[colLookup]);
2478                                  }                                  }
2479                                  colLookup = 0;                                  colLookup = 0;
# Line 1286  ui_create_colourmap(COLOURMAP * colours) Line 2514  ui_create_colourmap(COLOURMAP * colours)
2514    
2515                          }                          }
2516    
2517                            map[i] = colour;
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
2518                  }                  }
2519                  return map;                  return map;
2520          }          }
# Line 1297  ui_create_colourmap(COLOURMAP * colours) Line 2523  ui_create_colourmap(COLOURMAP * colours)
2523                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
2524                  Colormap map;                  Colormap map;
2525    
2526                  xcolours = (XColor*)xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
2527                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
2528                  {                  {
2529                          entry = &colours->colours[i];                          entry = &colours->colours[i];
# Line 1306  ui_create_colourmap(COLOURMAP * colours) Line 2532  ui_create_colourmap(COLOURMAP * colours)
2532                          MAKE_XCOLOR(xentry, entry);                          MAKE_XCOLOR(xentry, entry);
2533                  }                  }
2534    
2535                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
2536                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2537    
2538                  xfree(xcolours);                  xfree(xcolours);
2539                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
# Line 1317  ui_create_colourmap(COLOURMAP * colours) Line 2543  ui_create_colourmap(COLOURMAP * colours)
2543  void  void
2544  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
2545  {  {
2546          if (!owncolmap)          if (!g_owncolmap)
2547                  xfree(map);                  xfree(map);
2548          else          else
2549                  XFreeColormap(display, (Colormap) map);                  XFreeColormap(g_display, (Colormap) map);
2550  }  }
2551    
2552  void  void
2553  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
2554  {  {
2555          if (!owncolmap)          if (!g_owncolmap)
2556                  colmap = (uint32*)map;          {
2557                    if (g_colmap)
2558                            xfree(g_colmap);
2559    
2560                    g_colmap = (uint32 *) map;
2561            }
2562          else          else
2563                  XSetWindowColormap(display, wnd, (Colormap) map);          {
2564                    XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2565                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2566            }
2567  }  }
2568    
2569  void  void
2570  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2571  {  {
2572          XRectangle rect;          g_clip_rectangle.x = x;
2573            g_clip_rectangle.y = y;
2574          rect.x = x;          g_clip_rectangle.width = cx;
2575          rect.y = y;          g_clip_rectangle.height = cy;
2576          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);  
2577  }  }
2578    
2579  void  void
2580  ui_reset_clip(void)  ui_reset_clip(void)
2581  {  {
2582          XRectangle rect;          g_clip_rectangle.x = 0;
2583            g_clip_rectangle.y = 0;
2584          rect.x = 0;          g_clip_rectangle.width = g_width;
2585          rect.y = 0;          g_clip_rectangle.height = g_height;
2586          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);  
2587  }  }
2588    
2589  void  void
2590  ui_bell(void)  ui_bell(void)
2591  {  {
2592          XBell(display, 0);          XBell(g_display, 0);
2593  }  }
2594    
2595  void  void
# Line 1372  ui_destblt(uint8 opcode, Line 2602  ui_destblt(uint8 opcode,
2602  }  }
2603    
2604  static uint8 hatch_patterns[] = {  static uint8 hatch_patterns[] = {
2605          0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */          0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2606          0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */          0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2607          0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */          0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2608          0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */          0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2609          0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */          0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2610          0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */          0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
2611  };  };
2612    
2613  void  void
# Line 1394  ui_patblt(uint8 opcode, Line 2624  ui_patblt(uint8 opcode,
2624          {          {
2625                  case 0: /* Solid */                  case 0: /* Solid */
2626                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2627                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2628                          break;                          break;
2629    
2630                  case 2: /* Hatch */                  case 2: /* Hatch */
2631                          fill = (Pixmap) ui_create_glyph(8, 8, hatch_patterns + brush->pattern[0] * 8);                          fill = (Pixmap) ui_create_glyph(8, 8,
2632                          SET_FOREGROUND(bgcolour);                                                          hatch_patterns + brush->pattern[0] * 8);
2633                          SET_BACKGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2634                          XSetFillStyle(display, gc, FillOpaqueStippled);                          SET_BACKGROUND(bgcolour);
2635                          XSetStipple(display, gc, fill);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2636                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetStipple(g_display, g_gc, fill);
2637                          FILL_RECTANGLE(x, y, cx, cy);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2638                          XSetFillStyle(display, gc, FillSolid);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2639                          XSetTSOrigin(display, gc, 0, 0);                          XSetFillStyle(g_display, g_gc, FillSolid);
2640                            XSetTSOrigin(g_display, g_gc, 0, 0);
2641                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
2642                          break;                          break;
2643    
# Line 1414  ui_patblt(uint8 opcode, Line 2645  ui_patblt(uint8 opcode,
2645                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2646                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2647                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
2648                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2649                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2650                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2651                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
2652                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2653                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2654                          FILL_RECTANGLE(x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
2655                            XSetTSOrigin(g_display, g_gc, 0, 0);
                         XSetFillStyle(display, gc, FillSolid);  
                         XSetTSOrigin(display, gc, 0, 0);  
2656                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
2657                          break;                          break;
2658    
# Line 1433  ui_patblt(uint8 opcode, Line 2661  ui_patblt(uint8 opcode,
2661          }          }
2662    
2663          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2664    
2665            if (g_ownbackstore)
2666                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2667            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2668                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2669                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2670  }  }
2671    
2672  void  void
# Line 1441  ui_screenblt(uint8 opcode, Line 2675  ui_screenblt(uint8 opcode,
2675               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2676  {  {
2677          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2678          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
2679          if (ownbackstore)          {
2680                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2681                              g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2682                    XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2683            }
2684            else
2685            {
2686                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2687            }
2688    
2689            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2690                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2691                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2692    
2693          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2694  }  }
2695    
# Line 1453  ui_memblt(uint8 opcode, Line 2699  ui_memblt(uint8 opcode,
2699            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
2700  {  {
2701          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2702          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);
2703          if (ownbackstore)          ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2704                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);                                  (g_display, (Pixmap) src, sw->wnd, g_gc,
2705                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2706            if (g_ownbackstore)
2707                    XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2708          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2709  }  }
2710    
# Line 1499  ui_line(uint8 opcode, Line 2748  ui_line(uint8 opcode,
2748  {  {
2749          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2750          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2751          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2752          if (ownbackstore)          ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2753                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                                              startx - sw->xoffset, starty - sw->yoffset,
2754                                                endx - sw->xoffset, endy - sw->yoffset));
2755            if (g_ownbackstore)
2756                    XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2757          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2758  }  }
2759    
# Line 1514  ui_rect( Line 2766  ui_rect(
2766          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2767  }  }
2768    
2769    void
2770    ui_polygon(uint8 opcode,
2771               /* mode */ uint8 fillmode,
2772               /* dest */ POINT * point, int npoints,
2773               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2774    {
2775            uint8 style, i, ipattern[8];
2776            Pixmap fill;
2777    
2778            SET_FUNCTION(opcode);
2779    
2780            switch (fillmode)
2781            {
2782                    case ALTERNATE:
2783                            XSetFillRule(g_display, g_gc, EvenOddRule);
2784                            break;
2785                    case WINDING:
2786                            XSetFillRule(g_display, g_gc, WindingRule);
2787                            break;
2788                    default:
2789                            unimpl("fill mode %d\n", fillmode);
2790            }
2791    
2792            if (brush)
2793                    style = brush->style;
2794            else
2795                    style = 0;
2796    
2797            switch (style)
2798            {
2799                    case 0: /* Solid */
2800                            SET_FOREGROUND(fgcolour);
2801                            FILL_POLYGON((XPoint *) point, npoints);
2802                            break;
2803    
2804                    case 2: /* Hatch */
2805                            fill = (Pixmap) ui_create_glyph(8, 8,
2806                                                            hatch_patterns + brush->pattern[0] * 8);
2807                            SET_FOREGROUND(fgcolour);
2808                            SET_BACKGROUND(bgcolour);
2809                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2810                            XSetStipple(g_display, g_gc, fill);
2811                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2812                            FILL_POLYGON((XPoint *) point, npoints);
2813                            XSetFillStyle(g_display, g_gc, FillSolid);
2814                            XSetTSOrigin(g_display, g_gc, 0, 0);
2815                            ui_destroy_glyph((HGLYPH) fill);
2816                            break;
2817    
2818                    case 3: /* Pattern */
2819                            for (i = 0; i != 8; i++)
2820                                    ipattern[7 - i] = brush->pattern[i];
2821                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2822                            SET_FOREGROUND(bgcolour);
2823                            SET_BACKGROUND(fgcolour);
2824                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2825                            XSetStipple(g_display, g_gc, fill);
2826                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2827                            FILL_POLYGON((XPoint *) point, npoints);
2828                            XSetFillStyle(g_display, g_gc, FillSolid);
2829                            XSetTSOrigin(g_display, g_gc, 0, 0);
2830                            ui_destroy_glyph((HGLYPH) fill);
2831                            break;
2832    
2833                    default:
2834                            unimpl("brush %d\n", brush->style);
2835            }
2836    
2837            RESET_FUNCTION(opcode);
2838    }
2839    
2840    void
2841    ui_polyline(uint8 opcode,
2842                /* dest */ POINT * points, int npoints,
2843                /* pen */ PEN * pen)
2844    {
2845            /* TODO: set join style */
2846            SET_FUNCTION(opcode);
2847            SET_FOREGROUND(pen->colour);
2848            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2849            if (g_ownbackstore)
2850                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2851                               CoordModePrevious);
2852    
2853            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2854                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2855    
2856            RESET_FUNCTION(opcode);
2857    }
2858    
2859    void
2860    ui_ellipse(uint8 opcode,
2861               /* mode */ uint8 fillmode,
2862               /* dest */ int x, int y, int cx, int cy,
2863               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2864    {
2865            uint8 style, i, ipattern[8];
2866            Pixmap fill;
2867    
2868            SET_FUNCTION(opcode);
2869    
2870            if (brush)
2871                    style = brush->style;
2872            else
2873                    style = 0;
2874    
2875            switch (style)
2876            {
2877                    case 0: /* Solid */
2878                            SET_FOREGROUND(fgcolour);
2879                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2880                            break;
2881    
2882                    case 2: /* Hatch */
2883                            fill = (Pixmap) ui_create_glyph(8, 8,
2884                                                            hatch_patterns + brush->pattern[0] * 8);
2885                            SET_FOREGROUND(fgcolour);
2886                            SET_BACKGROUND(bgcolour);
2887                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2888                            XSetStipple(g_display, g_gc, fill);
2889                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2890                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2891                            XSetFillStyle(g_display, g_gc, FillSolid);
2892                            XSetTSOrigin(g_display, g_gc, 0, 0);
2893                            ui_destroy_glyph((HGLYPH) fill);
2894                            break;
2895    
2896                    case 3: /* Pattern */
2897                            for (i = 0; i != 8; i++)
2898                                    ipattern[7 - i] = brush->pattern[i];
2899                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2900                            SET_FOREGROUND(bgcolour);
2901                            SET_BACKGROUND(fgcolour);
2902                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2903                            XSetStipple(g_display, g_gc, fill);
2904                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2905                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2906                            XSetFillStyle(g_display, g_gc, FillSolid);
2907                            XSetTSOrigin(g_display, g_gc, 0, 0);
2908                            ui_destroy_glyph((HGLYPH) fill);
2909                            break;
2910    
2911                    default:
2912                            unimpl("brush %d\n", brush->style);
2913            }
2914    
2915            RESET_FUNCTION(opcode);
2916    }
2917    
2918  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2919  void  void
2920  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1524  ui_draw_glyph(int mixmode, Line 2925  ui_draw_glyph(int mixmode,
2925          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
2926          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2927    
2928          XSetFillStyle(display, gc,          XSetFillStyle(g_display, g_gc,
2929                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2930          XSetStipple(display, gc, (Pixmap) glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2931          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
2932    
2933          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2934    
2935          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
2936  }  }
2937    
2938  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
2939  {\  {\
2940    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
2941    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
2942      {\
2943        xyoffset = ttext[++idx];\
2944        if ((xyoffset & 0x80))\
2945      {\      {\
2946        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
2947        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;\  
         }\  
2948        else\        else\
2949          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
2950            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
2951      }\      }\
2952    if (glyph != NULL)\      else\
2953      {\      {\
2954        ui_draw_glyph (mixmode, x + glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2955                       y + glyph->baseline,\          y += xyoffset;\
2956                       glyph->width, glyph->height,\        else\
2957                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
2958      }\      }\
2959      }\
2960      if (glyph != NULL)\
2961      {\
2962        x1 = x + glyph->offset;\
2963        y1 = y + glyph->baseline;\
2964        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2965        XSetTSOrigin(g_display, g_gc, x1, y1);\
2966        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2967        if (flags & TEXT2_IMPLICIT_X)\
2968          x += glyph->width;\
2969      }\
2970  }  }
2971    
2972  void  void
2973  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,
2974               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2975               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2976               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2977  {  {
2978            /* TODO: use brush appropriately */
2979    
2980          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2981          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2982          DATABLOB *entry;          DATABLOB *entry;
2983    
2984          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2985    
2986            /* Sometimes, the boxcx value is something really large, like
2987               32691. This makes XCopyArea fail with Xvnc. The code below
2988               is a quick fix. */
2989            if (boxx + boxcx > g_width)
2990                    boxcx = g_width - boxx;
2991    
2992          if (boxcx > 1)          if (boxcx > 1)
2993          {          {
2994                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
# Line 1588  ui_draw_text(uint8 font, uint8 flags, in Line 2998  ui_draw_text(uint8 font, uint8 flags, in
2998                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2999          }          }
3000    
3001            SET_FOREGROUND(fgcolour);
3002            SET_BACKGROUND(bgcolour);
3003            XSetFillStyle(g_display, g_gc, FillStippled);
3004    
3005          /* Paint text, character by character */          /* Paint text, character by character */
3006          for (i = 0; i < length;)          for (i = 0; i < length;)
3007          {          {
3008                  switch (text[i])                  switch (text[i])
3009                  {                  {
3010                          case 0xff:                          case 0xff:
3011                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
3012                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
3013                                  {                                  {
3014                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
3015                                          exit(1);                                          for (j = 0; j < length; j++)
3016                                                    fprintf(stderr, "%02x ", text[j]);
3017                                            fprintf(stderr, "\n");
3018                                            i = length = 0;
3019                                            break;
3020                                  }                                  }
3021                                    cache_put_text(text[i + 1], text, text[i + 2]);
3022                                    i += 3;
3023                                    length -= i;
3024                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
3025                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
3026                                  i = 0;                                  i = 0;
3027                                  break;                                  break;
3028    
3029                          case 0xfe:                          case 0xfe:
3030                                    /* At least one byte needs to follow */
3031                                    if (i + 2 > length)
3032                                    {
3033                                            warning("Skipping short 0xfe command:");
3034                                            for (j = 0; j < length; j++)
3035                                                    fprintf(stderr, "%02x ", text[j]);
3036                                            fprintf(stderr, "\n");
3037                                            i = length = 0;
3038                                            break;
3039                                    }
3040                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
3041                                  if (entry != NULL)                                  if (entry->data != NULL)
3042                                  {                                  {
3043                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
3044                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
3045                                          {                                          {
3046                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
3047                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 1638  ui_draw_text(uint8 font, uint8 flags, in Line 3067  ui_draw_text(uint8 font, uint8 flags, in
3067                                  break;                                  break;
3068                  }                  }
3069          }          }
3070          if (ownbackstore)  
3071            XSetFillStyle(g_display, g_gc, FillSolid);
3072    
3073            if (g_ownbackstore)
3074          {          {
3075                  if (boxcx > 1)                  if (boxcx > 1)
3076                          XCopyArea(display, backstore, wnd, gc, boxx,                  {
3077                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3078                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3079                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3080                                                    (g_display, g_backstore, sw->wnd, g_gc,
3081                                                     boxx, boxy,
3082                                                     boxcx, boxcy,
3083                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3084                    }
3085                  else                  else
3086                          XCopyArea(display, backstore, wnd, gc, clipx,                  {
3087                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3088                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3089                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3090                                                    (g_display, g_backstore, sw->wnd, g_gc,
3091                                                     clipx, clipy,
3092                                                     clipcx, clipcy, clipx - sw->xoffset,
3093                                                     clipy - sw->yoffset));
3094                    }
3095          }          }
3096  }  }
3097    
# Line 1655  ui_desktop_save(uint32 offset, int x, in Line 3101  ui_desktop_save(uint32 offset, int x, in
3101          Pixmap pix;          Pixmap pix;
3102          XImage *image;          XImage *image;
3103    
3104          if (ownbackstore)          if (g_ownbackstore)
3105          {          {
3106                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3107          }          }
3108          else          else
3109          {          {
3110                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3111                  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);
3112                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3113                  XFreePixmap(display, pix);                  XFreePixmap(g_display, pix);
3114          }          }
3115    
3116          offset *= bpp / 8;          offset *= g_bpp / 8;
3117          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);
3118    
3119          XDestroyImage(image);          XDestroyImage(image);
3120  }  }
# Line 1679  ui_desktop_restore(uint32 offset, int x, Line 3125  ui_desktop_restore(uint32 offset, int x,
3125          XImage *image;          XImage *image;
3126          uint8 *data;          uint8 *data;
3127    
3128          offset *= bpp / 8;          offset *= g_bpp / 8;
3129          data = cache_get_desktop(offset, cx, cy, bpp / 8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
3130          if (data == NULL)          if (data == NULL)
3131                  return;                  return;
3132    
3133          image = XCreateImage(display, visual, depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3134                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
3135    
3136          if (ownbackstore)          if (g_ownbackstore)
3137          {          {
3138                  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);
3139                  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);
3140                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3141                                            (g_display, g_backstore, sw->wnd, g_gc,
3142                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3143          }          }
3144          else          else
3145          {          {
3146                  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);
3147                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3148                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3149                                             x - sw->xoffset, y - sw->yoffset));
3150          }          }
3151    
3152          XFree(image);          XFree(image);
3153  }  }
3154    
3155    /* these do nothing here but are used in uiports */
3156    void
3157    ui_begin_update(void)
3158    {
3159    }
3160    
3161    void
3162    ui_end_update(void)
3163    {
3164    }
3165    
3166    void
3167    ui_seamless_begin()
3168    {
3169            if (!g_seamless_rdp)
3170                    return;
3171    
3172            if (g_seamless_started)
3173                    return;
3174    
3175            g_seamless_started = True;
3176    
3177            ui_seamless_toggle();
3178    }
3179    
3180    void
3181    ui_seamless_toggle()
3182    {
3183            if (!g_seamless_rdp)
3184                    return;
3185    
3186            if (!g_seamless_started)
3187                    return;
3188    
3189            if (g_seamless_active)
3190            {
3191                    /* Deactivate */
3192                    while (g_seamless_windows)
3193                    {
3194                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3195                            seamless_remove_window(g_seamless_windows);
3196                    }
3197                    XMapWindow(g_display, g_wnd);
3198            }
3199            else
3200            {
3201                    /* Activate */
3202                    XUnmapWindow(g_display, g_wnd);
3203                    seamless_send_sync();
3204            }
3205    
3206            g_seamless_active = !g_seamless_active;
3207    }
3208    
3209    void
3210    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3211    {
3212            Window wnd;
3213            XSetWindowAttributes attribs;
3214            XClassHint *classhints;
3215            XSizeHints *sizehints;
3216            long input_mask;
3217            seamless_window *sw, *sw_parent;
3218    
3219            if (!g_seamless_active)
3220                    return;
3221    
3222            /* Ignore CREATEs for existing windows */
3223            sw = seamless_get_window_by_id(id);
3224            if (sw)
3225                    return;
3226    
3227            get_window_attribs(&attribs);
3228            attribs.override_redirect = False;
3229    
3230            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3231                                InputOutput, g_visual,
3232                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3233                                CWBorderPixel, &attribs);
3234    
3235            XStoreName(g_display, wnd, "SeamlessRDP");
3236            ewmh_set_wm_name(wnd, "SeamlessRDP");
3237    
3238            mwm_hide_decorations(wnd);
3239    
3240            classhints = XAllocClassHint();
3241            if (classhints != NULL)
3242            {
3243                    classhints->res_name = "rdesktop";
3244                    classhints->res_class = "SeamlessRDP";
3245                    XSetClassHint(g_display, wnd, classhints);
3246                    XFree(classhints);
3247            }
3248    
3249            /* WM_NORMAL_HINTS */
3250            sizehints = XAllocSizeHints();
3251            if (sizehints != NULL)
3252            {
3253                    sizehints->flags = USPosition;
3254                    XSetWMNormalHints(g_display, wnd, sizehints);
3255                    XFree(sizehints);
3256            }
3257    
3258            /* Handle popups without parents through some ewm hints */
3259            if (parent == 0xFFFFFFFF)
3260                    ewmh_set_window_popup(wnd);
3261            /* Set WM_TRANSIENT_FOR, if necessary */
3262            else if (parent != 0x00000000)
3263            {
3264                    sw_parent = seamless_get_window_by_id(parent);
3265                    if (sw_parent)
3266                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3267                    else
3268                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3269            }
3270    
3271    
3272            /* FIXME: Support for Input Context:s */
3273    
3274            get_input_mask(&input_mask);
3275            input_mask |= PropertyChangeMask;
3276    
3277            XSelectInput(g_display, wnd, input_mask);
3278    
3279            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3280               seamless window, we could try to close the window on the
3281               serverside, instead of terminating rdesktop */
3282            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3283    
3284            sw = xmalloc(sizeof(seamless_window));
3285            sw->wnd = wnd;
3286            sw->id = id;
3287            sw->behind = 0;
3288            sw->xoffset = 0;
3289            sw->yoffset = 0;
3290            sw->width = 0;
3291            sw->height = 0;
3292            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3293            sw->desktop = 0;
3294            sw->position_timer = xmalloc(sizeof(struct timeval));
3295            timerclear(sw->position_timer);
3296            sw->next = g_seamless_windows;
3297            g_seamless_windows = sw;
3298    }
3299    
3300    
3301    void
3302    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3303    {
3304            seamless_window *sw;
3305    
3306            if (!g_seamless_active)
3307                    return;
3308    
3309            sw = seamless_get_window_by_id(id);
3310            if (!sw)
3311            {
3312                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3313                    return;
3314            }
3315    
3316            XDestroyWindow(g_display, sw->wnd);
3317            seamless_remove_window(sw);
3318    }
3319    
3320    
3321    void
3322    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3323    {
3324            seamless_window *sw;
3325    
3326            if (!g_seamless_active)
3327                    return;
3328    
3329            sw = seamless_get_window_by_id(id);
3330            if (!sw)
3331            {
3332                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3333                    return;
3334            }
3335    
3336            if (!width || !height)
3337                    /* X11 windows must be at least 1x1 */
3338                    return;
3339    
3340            sw->xoffset = x;
3341            sw->yoffset = y;
3342            sw->width = width;
3343            sw->height = height;
3344    
3345            /* If we move the window in a maximized state, then KDE won't
3346               accept restoration */
3347            switch (sw->state)
3348            {
3349                    case SEAMLESSRDP_MINIMIZED:
3350                    case SEAMLESSRDP_MAXIMIZED:
3351                            return;
3352            }
3353    
3354            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3355            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3356    }
3357    
3358    void
3359    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3360    {
3361            seamless_window *sw;
3362    
3363            if (!g_seamless_active)
3364                    return;
3365    
3366            sw = seamless_get_window_by_id(id);
3367            if (!sw)
3368            {
3369                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3370                    return;
3371            }
3372    
3373            if (behind)
3374            {
3375                    seamless_window *sw_behind;
3376                    Window wnds[2];
3377    
3378                    sw_behind = seamless_get_window_by_id(behind);
3379                    if (!sw_behind)
3380                    {
3381                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3382                                    behind);
3383                            return;
3384                    }
3385    
3386                    wnds[1] = sw_behind->wnd;
3387                    wnds[0] = sw->wnd;
3388    
3389                    XRestackWindows(g_display, wnds, 2);
3390            }
3391            else
3392            {
3393                    XRaiseWindow(g_display, sw->wnd);
3394            }
3395    
3396            seamless_restack_window(sw, behind);
3397    }
3398    
3399    void
3400    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3401    {
3402            seamless_window *sw;
3403    
3404            if (!g_seamless_active)
3405                    return;
3406    
3407            sw = seamless_get_window_by_id(id);
3408            if (!sw)
3409            {
3410                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3411                    return;
3412            }
3413    
3414            /* FIXME: Might want to convert the name for non-EWMH WMs */
3415            XStoreName(g_display, sw->wnd, title);
3416            ewmh_set_wm_name(sw->wnd, title);
3417    }
3418    
3419    
3420    void
3421    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3422    {
3423            seamless_window *sw;
3424    
3425            if (!g_seamless_active)
3426                    return;
3427    
3428            sw = seamless_get_window_by_id(id);
3429            if (!sw)
3430            {
3431                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3432                    return;
3433            }
3434    
3435            switch (state)
3436            {
3437                    case SEAMLESSRDP_NORMAL:
3438                    case SEAMLESSRDP_MAXIMIZED:
3439                            ewmh_change_state(sw->wnd, state);
3440                            XMapWindow(g_display, sw->wnd);
3441                            break;
3442                    case SEAMLESSRDP_MINIMIZED:
3443                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3444                               the Window Manager should probably just ignore the request, since
3445                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3446                               such as minimization, rather than an independent state." Besides,
3447                               XIconifyWindow is easier. */
3448                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3449                            {
3450                                    XWMHints *hints;
3451                                    hints = XAllocWMHints();
3452                                    hints->flags = StateHint;
3453                                    hints->initial_state = IconicState;
3454                                    XSetWMHints(g_display, sw->wnd, hints);
3455                                    XFree(hints);
3456                                    XMapWindow(g_display, sw->wnd);
3457                            }
3458                            else
3459                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3460                            break;
3461                    default:
3462                            warning("SeamlessRDP: Invalid state %d\n", state);
3463                            break;
3464            }
3465    
3466            sw->state = state;
3467    }
3468    
3469    
3470    void
3471    ui_seamless_syncbegin(unsigned long flags)
3472    {
3473            if (!g_seamless_active)
3474                    return;
3475    
3476            /* Destroy all seamless windows */
3477            while (g_seamless_windows)
3478            {
3479                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3480                    seamless_remove_window(g_seamless_windows);
3481            }
3482    }

Legend:
Removed from v.376  
changed lines
  Added in v.1159

  ViewVC Help
Powered by ViewVC 1.1.26