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

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

  ViewVC Help
Powered by ViewVC 1.1.26