/[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 35 by matty, Sat Sep 15 14:01:45 2001 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 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2001     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
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26  #include <errno.h>  #include <errno.h>
27    #include <strings.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29    #include "xproto.h"
30    
31  extern int width;  extern int g_width;
32  extern int height;  extern int g_height;
33  extern BOOL sendmotion;  extern int g_xpos;
34  extern BOOL fullscreen;  extern int g_ypos;
35    extern int g_pos;
36  static Display *display;  extern BOOL g_sendmotion;
37  static int x_socket;  extern BOOL g_fullscreen;
38  static Window wnd;  extern BOOL g_grab_keyboard;
39  static GC gc;  extern BOOL g_hide_decorations;
40  static Visual *visual;  extern char g_title[];
41  static int depth;  /* Color depth of the RDP session.
42  static int bpp;     As of RDP 5.1, it may be 8, 15, 16 or 24. */
43    extern int g_server_depth;
44    extern int g_win_button_size;
45    
46    Display *g_display;
47    Time g_last_gesturetime;
48    static int g_x_socket;
49    static Screen *g_screen;
50    Window g_wnd;
51    
52    /* SeamlessRDP support */
53    typedef struct _seamless_window
54    {
55            Window wnd;
56            unsigned long id;
57            unsigned long parent;
58            unsigned long behind;
59            int xoffset, yoffset;
60            int width, height;
61            int state;              /* normal/minimized/maximized. */
62            unsigned int desktop;
63            struct timeval *position_timer;
64            struct _seamless_window *next;
65    } seamless_window;
66    static seamless_window *g_seamless_windows = NULL;
67    static unsigned long g_seamless_focused = 0;
68    static BOOL g_seamless_started = False; /* Server end is up and running */
69    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
70    extern BOOL g_seamless_rdp;
71    
72    extern uint32 g_embed_wnd;
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 */
128    static BOOL g_moving_wnd;
129    static int g_move_x_offset = 0;
130    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 */
140    #define MWM_HINTS_DECORATIONS   (1L << 1)
141    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
142    typedef struct
143    {
144            unsigned long flags;
145            unsigned long functions;
146            unsigned long decorations;
147            long inputMode;
148            unsigned long status;
149    }
150    PropMotifWmHints;
151    
152    typedef struct
153    {
154            uint32 red;
155            uint32 green;
156            uint32 blue;
157    }
158    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)\
204    { \
205            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  static BOOL owncolmap;  extern BOOL g_owncolmap;
238  static Colormap xcolmap;  static Colormap g_xcolmap;
239  static uint32 white;  static uint32 *g_colmap = NULL;
240  static uint32 *colmap;  
241    #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
242  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
243  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
 #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  
244    
245  static int rop2_map[] = {  static int rop2_map[] = {
246          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 81  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 void  static seamless_window *
268  translate8(uint8 *data, uint8 *out, uint8 *end)  seamless_get_window_by_id(unsigned long id)
269  {  {
270          while (out < end)          seamless_window *sw;
271                  *(out++) = (uint8)colmap[*(data++)];          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  static void  
280  translate16(uint8 *data, uint16 *out, uint16 *end)  static seamless_window *
281    seamless_get_window_by_wnd(Window wnd)
282  {  {
283          while (out < end)          seamless_window *sw;
284                  *(out++) = (uint16)colmap[*(data++)];          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  /* little endian - conversion happens when colourmap is built */  
293  static void  static void
294  translate24(uint8 *data, uint8 *out, uint8 *end)  seamless_remove_window(seamless_window * win)
295  {  {
296          uint32 value;          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          while (out < end)  
311    /* Move all windows except wnd to new desktop */
312    static void
313    seamless_all_to_desktop(Window wnd, unsigned int desktop)
314    {
315            seamless_window *sw;
316            for (sw = g_seamless_windows; sw; sw = sw->next)
317          {          {
318                  value = colmap[*(data++)];                  if (sw->wnd == wnd)
319                  *(out++) = value;                          continue;
320                  *(out++) = value >> 8;                  if (sw->desktop != desktop)
321                  *(out++) = value >> 16;                  {
322                            ewmh_move_to_desktop(sw->wnd, desktop);
323                            sw->desktop = desktop;
324                    }
325          }          }
326  }  }
327    
328    
329    /* Send our position */
330  static void  static void
331  translate32(uint8 *data, uint32 *out, uint32 *end)  seamless_update_position(seamless_window * sw)
332  {  {
333          while (out < end)          XWindowAttributes wa;
334                  *(out++) = colmap[*(data++)];          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  static uint8 *  
349  translate_image(int width, int height, uint8 *data)  /* Check if it's time to send our position */
350    static void
351    seamless_check_timers()
352  {  {
353          int size = width * height * bpp/8;          seamless_window *sw;
354          uint8 *out = xmalloc(size);          struct timeval now;
         uint8 *end = out + size;  
355    
356          switch (bpp)          gettimeofday(&now, NULL);
357            for (sw = g_seamless_windows; sw; sw = sw->next)
358          {          {
359                  case 8:                  if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
360                          translate8(data, out, end);                  {
361                          break;                          timerclear(sw->position_timer);
362                            seamless_update_position(sw);
363                    }
364            }
365    }
366    
                 case 16:  
                         translate16(data, (uint16 *)out, (uint16 *)end);  
                         break;  
367    
368                  case 24:  static void
369                          translate24(data, out, end);  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;                          break;
378            }
379    
380            if (sw_above)
381                    sw_above->behind = sw->behind;
382    
383                  case 32:          /* And then add it at the new position */
384                          translate32(data, (uint32 *)out, (uint32 *)end);  
385            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
386            {
387                    if (sw_above->behind == behind)
388                          break;                          break;
389          }          }
390    
391          return out;          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;
402            Atom hintsatom;
403    
404            /* setup the property */
405            motif_hints.flags = MWM_HINTS_DECORATIONS;
406            motif_hints.decorations = 0;
407    
408            /* get the atom for the property */
409            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
410            if (!hintsatom)
411            {
412                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
413                    return;
414            }
415    
416            XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
417                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
418    
419  }  }
420    
421    #define SPLITCOLOUR15(colour, rv) \
422    { \
423            rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
424            rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
425            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
426    }
427    
428    #define SPLITCOLOUR16(colour, rv) \
429    { \
430            rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
431            rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
432            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
433    } \
434    
435    #define SPLITCOLOUR24(colour, rv) \
436    { \
437            rv.blue = (colour & 0xff0000) >> 16; \
438            rv.green = (colour & 0x00ff00) >> 8; \
439            rv.red = (colour & 0x0000ff); \
440    }
441    
442    #define MAKECOLOUR(pc) \
443            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
444                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
445                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
446    
447  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
448  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 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 (bpp)          PixelColour pc;
466            switch (g_server_depth)
467          {          {
468                    case 15:
469                            SPLITCOLOUR15(colour, pc);
470                            break;
471                  case 16:                  case 16:
472                          if (host_be != xserver_be)                          SPLITCOLOUR16(colour, pc);
                                 BSWAP16(colour);  
473                          break;                          break;
   
474                  case 24:                  case 24:
475                          if (xserver_be)                          SPLITCOLOUR24(colour, pc);
                                 BSWAP24(colour);  
476                          break;                          break;
477                    default:
478                  case 32:                          /* Avoid warning */
479                          if (host_be != xserver_be)                          pc.red = 0;
480                                  BSWAP32(colour);                          pc.green = 0;
481                            pc.blue = 0;
482                          break;                          break;
483          }          }
484            return MAKECOLOUR(pc);
485    }
486    
487    /* indent is confused by UNROLL8 */
488    /* *INDENT-OFF* */
489    
490    /* repeat and unroll, similar to bitmap.c */
491    /* potentialy any of the following translate */
492    /* functions can use repeat but just doing */
493    /* the most common ones */
494    
495    #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
523    translate8to8(const uint8 * data, uint8 * out, uint8 * end)
524    {
525            while (out < end)
526                    *(out++) = (uint8) g_colmap[*(data++)];
527    }
528    
529    static void
530    translate8to16(const uint8 * data, uint8 * out, uint8 * end)
531    {
532            uint16 value;
533    
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 */
563    static void
564    translate8to24(const uint8 * data, uint8 * out, uint8 * end)
565    {
566            uint32 value;
567    
568            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                    while (out < end)
579                    {
580                            value = g_colmap[*(data++)];
581                            LOUT24(out, value);
582                    }
583            }
584    }
585    
586    static void
587    translate8to32(const uint8 * data, uint8 * out, uint8 * end)
588    {
589            uint32 value;
590    
591            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
620    translate15to16(const uint16 * data, uint8 * out, uint8 * end)
621    {
622            uint16 pixel;
623            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
657    translate15to24(const uint16 * data, uint8 * out, uint8 * end)
658    {
659            uint32 value;
660            uint16 pixel;
661            PixelColour pc;
662    
663            if (g_compatible_arch)
664            {
665                    /* *INDENT-OFF* */
666                    REPEAT3
667                    (
668                            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
707    translate15to32(const uint16 * data, uint8 * out, uint8 * end)
708    {
709            uint16 pixel;
710            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
758    translate16to16(const uint16 * data, uint8 * out, uint8 * end)
759    {
760            uint16 pixel;
761            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
815    translate16to24(const uint16 * data, uint8 * out, uint8 * end)
816    {
817            uint32 value;
818            uint16 pixel;
819            PixelColour pc;
820    
821            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                    if (g_host_be)
861                    {
862                            while (out < end)
863                            {
864                                    pixel = *(data++);
865                                    BSWAP16(pixel);
866                                    SPLITCOLOUR16(pixel, pc);
867                                    value = MAKECOLOUR(pc);
868                                    LOUT24(out, value);
869                            }
870                    }
871                    else
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
885    translate16to32(const uint16 * data, uint8 * out, uint8 * end)
886    {
887            uint16 pixel;
888            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
956    translate24to16(const uint8 * data, uint8 * out, uint8 * end)
957    {
958            uint32 pixel = 0;
959            uint16 value;
960            PixelColour pc;
961    
962            while (out < end)
963            {
964                    pixel = *(data++) << 16;
965                    pixel |= *(data++) << 8;
966                    pixel |= *(data++);
967                    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
981    translate24to24(const uint8 * data, uint8 * out, uint8 * end)
982    {
983            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                    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          return colour;  static void
1014    translate24to32(const uint8 * data, uint8 * out, uint8 * end)
1015    {
1016            uint32 pixel;
1017            uint32 value;
1018            PixelColour pc;
1019    
1020            if (g_compatible_arch)
1021            {
1022                    /* *INDENT-OFF* */
1023    #ifdef NEED_ALIGN
1024                    REPEAT4
1025                    (
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 *
1069    translate_image(int width, int height, uint8 * data)
1070    {
1071            int size;
1072            uint8 *out;
1073            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_depth)
1096            {
1097                    case 24:
1098                            switch (g_bpp)
1099                            {
1100                                    case 32:
1101                                            translate24to32(data, out, end);
1102                                            break;
1103                                    case 24:
1104                                            translate24to24(data, out, end);
1105                                            break;
1106                                    case 16:
1107                                            translate24to16(data, out, end);
1108                                            break;
1109                            }
1110                            break;
1111                    case 16:
1112                            switch (g_bpp)
1113                            {
1114                                    case 32:
1115                                            translate16to32((uint16 *) data, out, end);
1116                                            break;
1117                                    case 24:
1118                                            translate16to24((uint16 *) data, out, end);
1119                                            break;
1120                                    case 16:
1121                                            translate16to16((uint16 *) data, out, end);
1122                                            break;
1123                            }
1124                            break;
1125                    case 15:
1126                            switch (g_bpp)
1127                            {
1128                                    case 32:
1129                                            translate15to32((uint16 *) data, out, end);
1130                                            break;
1131                                    case 24:
1132                                            translate15to24((uint16 *) data, out, end);
1133                                            break;
1134                                    case 16:
1135                                            translate15to16((uint16 *) data, out, end);
1136                                            break;
1137                            }
1138                            break;
1139                    case 8:
1140                            switch (g_bpp)
1141                            {
1142                                    case 8:
1143                                            translate8to8(data, out, end);
1144                                            break;
1145                                    case 16:
1146                                            translate8to16(data, out, end);
1147                                            break;
1148                                    case 24:
1149                                            translate8to24(data, out, end);
1150                                            break;
1151                                    case 32:
1152                                            translate8to32(data, out, end);
1153                                            break;
1154                            }
1155                            break;
1156            }
1157            return out;
1158  }  }
1159    
1160  BOOL  BOOL
1161  ui_create_window(char *title)  get_key_state(unsigned int state, uint32 keysym)
1162    {
1163            int modifierpos, key, keysymMask = 0;
1164            int offset;
1165    
1166            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
1167    
1168            if (keycode == NoSymbol)
1169                    return False;
1170    
1171            for (modifierpos = 0; modifierpos < 8; modifierpos++)
1172            {
1173                    offset = g_mod_map->max_keypermod * modifierpos;
1174    
1175                    for (key = 0; key < g_mod_map->max_keypermod; key++)
1176                    {
1177                            if (g_mod_map->modifiermap[offset + key] == keycode)
1178                                    keysymMask |= 1 << modifierpos;
1179                    }
1180            }
1181    
1182            return (state & keysymMask) ? True : False;
1183    }
1184    
1185    static void
1186    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  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
1211          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1212          Screen *screen;          int pixmap_formats_count, visuals_count;
1213          uint16 test;          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\n");                  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                            /* Try to find a no-translation visual that'll
1241                               allow us to use RDP bitmaps directly as ZPixmaps. */
1242                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1243                                                   /* R5G5B5 */
1244                                                   (visual_info->red_mask == 0x7c00) &&
1245                                                   (visual_info->green_mask == 0x3e0) &&
1246                                                   (visual_info->blue_mask == 0x1f)) ||
1247                                                  ((visual_info->depth == 16) &&
1248                                                   /* R5G6B5 */
1249                                                   (visual_info->red_mask == 0xf800) &&
1250                                                   (visual_info->green_mask == 0x7e0) &&
1251                                                   (visual_info->blue_mask == 0x1f)) ||
1252                                                  ((visual_info->depth == 24) &&
1253                                                   /* R8G8B8 */
1254                                                   (visual_info->red_mask == 0xff0000) &&
1255                                                   (visual_info->green_mask == 0xff00) &&
1256                                                   (visual_info->blue_mask == 0xff))))
1257                            {
1258                                    g_visual = visual_info->visual;
1259                                    g_depth = visual_info->depth;
1260                                    g_compatible_arch = !g_host_be;
1261                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1262                                    if (g_no_translate_image)
1263                                            /* We found the best visual */
1264                                            break;
1265                            }
1266                            else
1267                            {
1268                                    g_compatible_arch = False;
1269                            }
1270    
1271          pfm = XListPixmapFormats(display, &i);                          if (visual_info->depth > 24)
1272          if (pfm != NULL)                          {
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                    g_owncolmap = False;
1327                    calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1328                    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                  /* Use maximum bpp for this depth - this is generally                  template.class = PseudoColor;
1334                     desirable, e.g. 24 bits->32 bits. */                  template.depth = 8;
1335                  while (i--)                  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)                          error("No usable TrueColor or PseudoColor visuals on this display.\n");
1343                              && (pfm[i].bits_per_pixel > bpp))                          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                  }                  }
                 XFree(pfm);  
1389          }          }
1390            XFree(pfm);
1391            pfm = NULL;
1392            return True;
1393    }
1394    
1395    BOOL
1396    ui_init(void)
1397    {
1398            int screen_num;
1399    
1400          if (bpp < 8)          g_display = XOpenDisplay(NULL);
1401            if (g_display == NULL)
1402          {          {
1403                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
                 XCloseDisplay(display);  
1404                  return False;                  return False;
1405          }          }
1406    
1407          if (depth <= 8)          {
1408                  owncolmap = True;                  uint16 endianess_test = 1;
1409          else                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1410                  xcolmap = DefaultColormapOfScreen(screen);          }
1411    
1412          test = 1;          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1413          host_be = !(BOOL)(*(uint8 *)(&test));          screen_num = DefaultScreen(g_display);
1414          xserver_be = (ImageByteOrder(display) == MSBFirst);          g_x_socket = ConnectionNumber(g_display);
1415            g_screen = ScreenOfDisplay(g_display, screen_num);
1416            g_depth = DefaultDepthOfScreen(g_screen);
1417    
1418          white = WhitePixelOfScreen(screen);          if (!select_visual())
1419          attribs.background_pixel = BlackPixelOfScreen(screen);                  return False;
         attribs.backing_store = DoesBackingStore(screen);  
1420    
1421          if (attribs.backing_store == NotUseful)          if (g_no_translate_image)
1422                  ownbackstore = True;          {
1423                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1424            }
1425    
1426          if (fullscreen)          if (g_server_depth > g_bpp)
1427          {          {
1428                  attribs.override_redirect = True;                  warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1429                  width = WidthOfScreen(screen);                          g_server_depth, g_bpp);
                 height = HeightOfScreen(screen);  
1430          }          }
1431          else  
1432            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1433                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1434    
1435            if (!g_owncolmap)
1436            {
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            if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1445            {
1446                    warning("External BackingStore not available. Using internal.\n");
1447                    g_ownbackstore = True;
1448            }
1449    
1450            /*
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 */
1470                    uint32 x, y, cx, cy;
1471                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1472                    {
1473                            g_width = cx;
1474                            g_height = cy;
1475                            g_using_full_workarea = True;
1476                    }
1477                    else
1478                    {
1479                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1480                            g_width = WidthOfScreen(g_screen);
1481                            g_height = HeightOfScreen(g_screen);
1482                    }
1483            }
1484    
1485            /* make sure width is a multiple of 4 */
1486            g_width = (g_width + 3) & ~3;
1487    
1488            g_mod_map = XGetModifierMapping(g_display);
1489    
1490            xkeymap_init();
1491    
1492            if (g_enable_compose)
1493                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1494    
1495            xclip_init();
1496            ewmh_init();
1497            if (g_seamless_rdp)
1498                    seamless_init();
1499    
1500            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1501    
1502            return True;
1503    }
1504    
1505    void
1506    ui_deinit(void)
1507    {
1508            if (g_IM != NULL)
1509                    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    static void
1526    get_window_attribs(XSetWindowAttributes * attribs)
1527    {
1528            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1529            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1530            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1531            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1532            attribs->override_redirect = g_fullscreen;
1533            attribs->colormap = g_xcolmap;
1534    }
1535    
1536    static void
1537    get_input_mask(long *input_mask)
1538    {
1539            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1540                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1541    
1542            if (g_sendmotion)
1543                    *input_mask |= PointerMotionMask;
1544            if (g_ownbackstore)
1545                    *input_mask |= ExposureMask;
1546            if (g_fullscreen || g_grab_keyboard)
1547                    *input_mask |= EnterWindowMask;
1548            if (g_grab_keyboard)
1549                    *input_mask |= LeaveWindowMask;
1550    }
1551    
1552    BOOL
1553    ui_create_window(void)
1554    {
1555            uint8 null_pointer_mask[1] = { 0x80 };
1556            uint8 null_pointer_data[24] = { 0x00 };
1557    
1558            XSetWindowAttributes attribs;
1559            XClassHint *classhints;
1560            XSizeHints *sizehints;
1561            int wndwidth, wndheight;
1562            long input_mask, ic_input_mask;
1563            XEvent xevent;
1564    
1565            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1566            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1567    
1568            /* Handle -x-y portion of geometry string */
1569            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1570                    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            get_window_attribs(&attribs);
1575    
1576            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 (g_gc == NULL)
1582          {          {
1583                  attribs.override_redirect = False;                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1584                    ui_reset_clip();
1585          }          }
1586    
1587          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          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          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          XStoreName(g_display, g_wnd, g_title);
                             0, 0, width, height, 0, CopyFromParent,  
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
1600    
1601          XStoreName(display, wnd, title);          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 274  ui_create_window(char *title) Line 1613  ui_create_window(char *title)
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          if (g_embed_wnd)
1625                          | ButtonPressMask | ButtonReleaseMask          {
1626                          | EnterWindowMask | LeaveWindowMask;                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1627            }
1628    
1629            get_input_mask(&input_mask);
1630    
1631            if (g_IM != NULL)
1632            {
1633                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1634                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1635    
1636                    if ((g_IC != NULL)
1637                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1638                            input_mask |= ic_input_mask;
1639            }
1640    
1641            XSelectInput(g_display, g_wnd, input_mask);
1642    
1643          if (sendmotion)          XMapWindow(g_display, g_wnd);
1644                  input_mask |= PointerMotionMask;          /* wait for VisibilityNotify */
1645            do
1646            {
1647                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1648            }
1649            while (xevent.type != VisibilityNotify);
1650            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1651    
1652          if (ownbackstore)          g_focused = False;
1653                  input_mask |= ExposureMask;          g_mouse_in_wnd = False;
1654    
1655          XSelectInput(display, wnd, input_mask);          /* handle the WM_DELETE_WINDOW protocol */
1656          gc = XCreateGC(display, wnd, 0, NULL);          g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1657            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1658            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1659    
1660          if (ownbackstore)          /* create invisible 1x1 cursor to be used as null cursor */
1661                  backstore = XCreatePixmap(display, wnd, width, height, depth);          if (g_null_cursor == NULL)
1662                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1663    
         XMapWindow(display, wnd);  
1664          return True;          return True;
1665  }  }
1666    
1667  void  void
1668  ui_destroy_window()  ui_resize_window()
1669  {  {
1670          if (ownbackstore)          XSizeHints *sizehints;
1671                  XFreePixmap(display, backstore);          Pixmap bs;
1672    
1673          XFreeGC(display, gc);          sizehints = XAllocSizeHints();
1674          XDestroyWindow(display, wnd);          if (sizehints)
1675          XCloseDisplay(display);          {
1676          display = NULL;                  sizehints->flags = PMinSize | PMaxSize;
1677  }                  sizehints->min_width = sizehints->max_width = g_width;
1678                    sizehints->min_height = sizehints->max_height = g_height;
1679  static uint8                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1680  xwin_translate_key(unsigned long key)                  XFree(sizehints);
1681  {          }
1682          DEBUG(("KEY(code=0x%lx)\n", key));  
1683            if (!(g_fullscreen || g_embed_wnd))
1684          if ((key > 8) && (key <= 0x60))          {
1685                  return (key - 8);                  XResizeWindow(g_display, g_wnd, g_width, g_height);
1686            }
1687          switch (key)  
1688          {          /* create new backstore pixmap */
1689                  case 0x61:      /* home */          if (g_backstore != 0)
1690                          return 0x47 | 0x80;          {
1691                  case 0x62:      /* up arrow */                  bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1692                          return 0x48 | 0x80;                  XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1693                  case 0x63:      /* page up */                  XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1694                          return 0x49 | 0x80;                  XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1695                  case 0x64:      /* left arrow */                  XFreePixmap(g_display, g_backstore);
1696                          return 0x4b | 0x80;                  g_backstore = bs;
1697                  case 0x66:      /* right arrow */          }
1698                          return 0x4d | 0x80;  }
1699                  case 0x67:      /* end */  
1700                          return 0x4f | 0x80;  void
1701                  case 0x68:      /* down arrow */  ui_destroy_window(void)
1702                          return 0x50 | 0x80;  {
1703                  case 0x69:      /* page down */          if (g_IC != NULL)
1704                          return 0x51 | 0x80;                  XDestroyIC(g_IC);
1705                  case 0x6a:      /* insert */  
1706                          return 0x52 | 0x80;          XDestroyWindow(g_display, g_wnd);
1707                  case 0x6b:      /* delete */  }
1708                          return 0x53 | 0x80;  
1709                  case 0x6c:      /* keypad enter */  void
1710                          return 0x1c | 0x80;  xwin_toggle_fullscreen(void)
1711                  case 0x6d:      /* right ctrl */  {
1712                          return 0x1d | 0x80;          Pixmap contents = 0;
1713                  case 0x6f:      /* ctrl - print screen */  
1714                          return 0x37 | 0x80;          if (g_seamless_active)
1715                  case 0x70:      /* keypad '/' */                  /* Turn off SeamlessRDP mode */
1716                          return 0x35 | 0x80;                  ui_seamless_toggle();
1717                  case 0x71:      /* right alt */  
1718                          return 0x38 | 0x80;          if (!g_ownbackstore)
1719                  case 0x72:      /* ctrl break */          {
1720                          return 0x46 | 0x80;                  /* need to save contents of window */
1721                  case 0x73:      /* left window key */                  contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1722                          return 0xff;    /* real scancode is 5b */                  XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1723                  case 0x74:      /* right window key */          }
1724                          return 0xff;    /* real scancode is 5c */  
1725                  case 0x75:      /* menu key */          ui_destroy_window();
1726                          return 0x5d | 0x80;          g_fullscreen = !g_fullscreen;
1727          }          ui_create_window();
1728    
1729          return 0;          XDefineCursor(g_display, g_wnd, g_current_cursor);
1730  }  
1731            if (!g_ownbackstore)
1732  static uint16          {
1733  xwin_translate_mouse(unsigned long button)                  XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1734  {                  XFreePixmap(g_display, contents);
1735          switch (button)          }
1736          {  }
1737                  case Button1:   /* left */  
1738                          return MOUSE_FLAG_BUTTON1;  static void
1739                  case Button2:   /* middle */  handle_button_event(XEvent xevent, BOOL down)
1740                          return MOUSE_FLAG_BUTTON3;  {
1741                  case Button3:   /* right */          uint16 button, flags = 0;
1742                          return MOUSE_FLAG_BUTTON2;          g_last_gesturetime = xevent.xbutton.time;
1743          }          button = xkeymap_translate_button(xevent.xbutton.button);
1744            if (button == 0)
1745          return 0;                  return;
1746  }  
1747            if (down)
1748  static void                  flags = MOUSE_FLAG_DOWN;
1749  xwin_process_events()  
1750  {          /* Stop moving window when button is released, regardless of cursor position */
1751          XEvent event;          if (g_moving_wnd && (xevent.type == ButtonRelease))
1752          uint8 scancode;                  g_moving_wnd = False;
1753          uint16 button;  
1754          uint32 ev_time;          /* 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          if (display == NULL)  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;                  return;
1831    
1832          while (XCheckWindowEvent(display, wnd, ~0, &event))          sw_below = NULL;
1833    
1834            i = 0;
1835            while (children[i] != sw->wnd)
1836            {
1837                    i++;
1838                    if (i >= nchildren)
1839                            return;
1840            }
1841    
1842            for (i++; i < nchildren; i++)
1843            {
1844                    sw_below = seamless_get_window_by_wnd(children[i]);
1845                    if (sw_below)
1846                            break;
1847            }
1848    
1849            if (!sw_below && !sw->behind)
1850                    return;
1851            if (sw_below && (sw_below->id == sw->behind))
1852                    return;
1853    
1854            if (sw_below)
1855            {
1856                    seamless_send_zchange(sw->id, sw_below->id, 0);
1857                    seamless_restack_window(sw, sw_below->id);
1858            }
1859            else
1860            {
1861                    seamless_send_zchange(sw->id, 0, 0);
1862                    seamless_restack_window(sw, 0);
1863            }
1864    }
1865    
1866    /* Process events in Xlib queue
1867       Returns 0 after user quit, 1 otherwise */
1868    static int
1869    xwin_process_events(void)
1870    {
1871            XEvent xevent;
1872            KeySym keysym;
1873            uint32 ev_time;
1874            char str[256];
1875            Status status;
1876            int events = 0;
1877            seamless_window *sw;
1878    
1879            while ((XPending(g_display) > 0) && events++ < 20)
1880          {          {
1881                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
1882    
1883                  switch (event.type)                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1884                  {                  {
1885                            DEBUG_KBD(("Filtering event\n"));
1886                            continue;
1887                    }
1888    
1889                    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:
1898                                    /* the window manager told us to quit */
1899                                    if ((xevent.xclient.message_type == g_protocol_atom)
1900                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1901                                            /* Quit */
1902                                            return 0;
1903                                    break;
1904    
1905                          case KeyPress:                          case KeyPress:
1906                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1907                                  if (scancode == 0)                                  if (g_IC != NULL)
1908                                            /* Multi_key compatible version */
1909                                    {
1910                                            XmbLookupString(g_IC,
1911                                                            &xevent.xkey, str, sizeof(str), &keysym,
1912                                                            &status);
1913                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1914                                            {
1915                                                    error("XmbLookupString failed with status 0x%x\n",
1916                                                          status);
1917                                                    break;
1918                                            }
1919                                    }
1920                                    else
1921                                    {
1922                                            /* Plain old XLookupString */
1923                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1924                                            XLookupString((XKeyEvent *) & xevent,
1925                                                          str, sizeof(str), &keysym, NULL);
1926                                    }
1927    
1928                                    DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1929                                               get_ksname(keysym)));
1930    
1931                                    ev_time = time(NULL);
1932                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1933                                          break;                                          break;
1934    
1935                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1936                                                 scancode, 0);                                                    ev_time, True, 0);
1937                                  break;                                  break;
1938    
1939                          case KeyRelease:                          case KeyRelease:
1940                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1941                                  if (scancode == 0)                                  XLookupString((XKeyEvent *) & xevent, str,
1942                                                  sizeof(str), &keysym, NULL);
1943    
1944                                    DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1945                                               get_ksname(keysym)));
1946    
1947                                    ev_time = time(NULL);
1948                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1949                                          break;                                          break;
1950    
1951                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1952                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                    ev_time, False, 0);
                                                scancode, 0);  
1953                                  break;                                  break;
1954    
1955                          case ButtonPress:                          case ButtonPress:
1956                                  button = xwin_translate_mouse(event.xbutton.button);                                  handle_button_event(xevent, True);
1957                                  if (button == 0)                                  break;
1958    
1959                            case ButtonRelease:
1960                                    handle_button_event(xevent, False);
1961                                    break;
1962    
1963                            case MotionNotify:
1964                                    if (g_moving_wnd)
1965                                    {
1966                                            XMoveWindow(g_display, g_wnd,
1967                                                        xevent.xmotion.x_root - g_move_x_offset,
1968                                                        xevent.xmotion.y_root - g_move_y_offset);
1969                                          break;                                          break;
1970                                    }
1971    
1972                                    if (g_fullscreen && !g_focused)
1973                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1974                                                           CurrentTime);
1975    
1976                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (xevent.xmotion.window == g_wnd)
1977                                                 button | MOUSE_FLAG_DOWN,                                  {
1978                                                 event.xbutton.x,                                          rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1979                                                 event.xbutton.y);                                                         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 ButtonRelease:                          case FocusIn:
1991                                  button = xwin_translate_mouse(event.xbutton.button);                                  if (xevent.xfocus.mode == NotifyGrab)
1992                                  if (button == 0)                                          break;
1993                                    g_focused = True;
1994                                    reset_modifier_keys();
1995                                    if (g_grab_keyboard && g_mouse_in_wnd)
1996                                            XGrabKeyboard(g_display, g_wnd, True,
1997                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1998    
1999                                    sw = seamless_get_window_by_wnd(xevent.xfocus.window);
2000                                    if (!sw)
2001                                          break;                                          break;
2002    
2003                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (sw->id != g_seamless_focused)
2004                                                 button,                                  {
2005                                                 event.xbutton.x,                                          seamless_send_focus(sw->id, 0);
2006                                                 event.xbutton.y);                                          g_seamless_focused = sw->id;
2007                                    }
2008                                  break;                                  break;
2009    
2010                          case MotionNotify:                          case FocusOut:
2011                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (xevent.xfocus.mode == NotifyUngrab)
2012                                                 MOUSE_FLAG_MOVE,                                          break;
2013                                                 event.xmotion.x,                                  g_focused = False;
2014                                                 event.xmotion.y);                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)
2015                                            XUngrabKeyboard(g_display, CurrentTime);
2016                                  break;                                  break;
2017    
2018                          case EnterNotify:                          case EnterNotify:
2019                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
2020                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
2021                                    g_mouse_in_wnd = True;
2022                                    if (g_fullscreen)
2023                                    {
2024                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2025                                                           CurrentTime);
2026                                            break;
2027                                    }
2028                                    if (g_focused)
2029                                            XGrabKeyboard(g_display, g_wnd, True,
2030                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
2031                                  break;                                  break;
2032    
2033                          case LeaveNotify:                          case LeaveNotify:
2034                                  XUngrabKeyboard(display, CurrentTime);                                  /* we only register for this event when grab_keyboard */
2035                                    g_mouse_in_wnd = False;
2036                                    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                                            event.xexpose.x, event.xexpose.y,                                  {
2042                                            event.xexpose.width, event.xexpose.height,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2043                                            event.xexpose.x, event.xexpose.y);                                                    g_gc,
2044                                                      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;
2067    
2068                            case MappingNotify:
2069                                    /* Refresh keyboard mapping if it has changed. This is important for
2070                                       Xvnc, since it allocates keycodes dynamically */
2071                                    if (xevent.xmapping.request == MappingKeyboard
2072                                        || xevent.xmapping.request == MappingModifier)
2073                                            XRefreshKeyboardMapping(&xevent.xmapping);
2074    
2075                                    if (xevent.xmapping.request == MappingModifier)
2076                                    {
2077                                            XFreeModifiermap(g_mod_map);
2078                                            g_mod_map = XGetModifierMapping(g_display);
2079                                    }
2080                                    break;
2081    
2082                                    /* clipboard stuff */
2083                            case SelectionNotify:
2084                                    xclip_handle_SelectionNotify(&xevent.xselection);
2085                                    break;
2086                            case SelectionRequest:
2087                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
2088                                    break;
2089                            case SelectionClear:
2090                                    xclip_handle_SelectionClear();
2091                                    break;
2092                            case PropertyNotify:
2093                                    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          }          }
2155            /* Keep going */
2156            return 1;
2157  }  }
2158    
2159  void  /* Returns 0 after user quit, 1 otherwise */
2160    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          XFlush(display);          BOOL s_timeout = False;
   
         FD_ZERO(&rfds);  
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 */
2172                    if (!xwin_process_events())
2173                            /* User quit */
2174                            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    #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, NULL, NULL, NULL))                  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                  if (FD_ISSET(x_socket, &rfds))                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
                         xwin_process_events();  
2215    
2216                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2217                          return;                          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
2233  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
2234  {  {
2235          XImage *image;          XImage *image;
2236          Pixmap bitmap;          Pixmap bitmap;
2237          uint8 *tdata;          uint8 *tdata;
2238            int bitmap_pad;
2239    
2240          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_server_depth == 8)
2241          bitmap = XCreatePixmap(display, wnd, width, height, depth);          {
2242          image = XCreateImage(display, visual, depth, ZPixmap,                  bitmap_pad = 8;
2243                               0, tdata, width, height, 8, 0);          }
2244            else
2245            {
2246                    bitmap_pad = g_bpp;
2247    
2248          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);                  if (g_bpp == 24)
2249                            bitmap_pad = 32;
2250            }
2251    
2252            tdata = (g_owncolmap ? data : translate_image(width, height, data));
2253            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
2254            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2255                                 (char *) tdata, width, height, bitmap_pad, 0);
2256    
2257            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  }  }
2264    
2265  void  void
2266  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 int width, int height, uint8 *data)  
2267  {  {
2268          XImage *image;          XImage *image;
2269          uint8 *tdata;          uint8 *tdata;
2270            int bitmap_pad;
2271    
2272            if (g_server_depth == 8)
2273            {
2274                    bitmap_pad = 8;
2275            }
2276            else
2277            {
2278                    bitmap_pad = g_bpp;
2279    
2280          tdata = (owncolmap ? data : translate_image(width, height, data));                  if (g_bpp == 24)
2281          image = XCreateImage(display, visual, depth, ZPixmap,                          bitmap_pad = 32;
2282                               0, tdata, width, height, 8, 0);          }
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
2316  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
2317  {  {
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,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
2329                               data, 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);
2337          XFreeGC(display, gc);          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
2347  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
2348                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
2349  {  {
2350          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
2351          XColor bg, fg;          XColor bg, fg;
# Line 604  ui_create_cursor(unsigned int x, unsigne Line 2359  ui_create_cursor(unsigned int x, unsigne
2359          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
2360          offset = scanline * height;          offset = scanline * height;
2361    
2362          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
2363          memset(cursor, 0, offset);          memset(cursor, 0, offset);
2364    
2365          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
2366          memset(mask, 0, offset);          memset(mask, 0, offset);
2367    
2368          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 647  ui_create_cursor(unsigned int x, unsigne Line 2402  ui_create_cursor(unsigned int x, unsigne
2402    
2403          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
2404          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
2405            
2406          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
2407                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
2408                                        (Pixmap) maskglyph, &fg, &bg, x, y);
2409    
2410          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
2411          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2412          xfree(mask);          xfree(mask);
2413          xfree(cursor);          xfree(cursor);
2414          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
2415  }  }
2416    
2417  void  void
2418  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
2419  {  {
2420          XDefineCursor(display, wnd, (Cursor)cursor);          g_current_cursor = (Cursor) cursor;
2421            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 676  ui_destroy_cursor(HCURSOR cursor) Line 2440  ui_destroy_cursor(HCURSOR cursor)
2440                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
2441                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2442    
2443    
2444  HCOLOURMAP  HCOLOURMAP
2445  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
2446  {  {
2447          COLOURENTRY *entry;          COLOURENTRY *entry;
2448          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
2449            if (!g_owncolmap)
         if (owncolmap)  
2450          {          {
2451                  XColor *xcolours, *xentry;                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
2452                  Colormap map;                  XColor xentry;
2453                    XColor xc_cache[256];
2454                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  uint32 colour;
2455                    int colLookup = 256;
2456                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
2457                  {                  {
2458                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2459                          xentry = &xcolours[i];                          MAKE_XCOLOR(&xentry, entry);
                         xentry->pixel = i;  
                         MAKE_XCOLOR(xentry, entry);  
                 }  
2460    
2461                  map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
2462                  XStoreColors(display, map, xcolours, ncolours);                          {
2463                                    /* Allocation failed, find closest match. */
2464                                    int j = 256;
2465                                    int nMinDist = 3 * 256 * 256;
2466                                    long nDist = nMinDist;
2467    
2468                  xfree(xcolours);                                  /* only get the colors once */
2469                  return (HCOLOURMAP)map;                                  while (colLookup--)
2470                                    {
2471                                            xc_cache[colLookup].pixel = colLookup;
2472                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
2473                                                    xc_cache[colLookup].blue = 0;
2474                                            xc_cache[colLookup].flags = 0;
2475                                            XQueryColor(g_display,
2476                                                        DefaultColormap(g_display,
2477                                                                        DefaultScreen(g_display)),
2478                                                        &xc_cache[colLookup]);
2479                                    }
2480                                    colLookup = 0;
2481    
2482                                    /* approximate the pixel */
2483                                    while (j--)
2484                                    {
2485                                            if (xc_cache[j].flags)
2486                                            {
2487                                                    nDist = ((long) (xc_cache[j].red >> 8) -
2488                                                             (long) (xentry.red >> 8)) *
2489                                                            ((long) (xc_cache[j].red >> 8) -
2490                                                             (long) (xentry.red >> 8)) +
2491                                                            ((long) (xc_cache[j].green >> 8) -
2492                                                             (long) (xentry.green >> 8)) *
2493                                                            ((long) (xc_cache[j].green >> 8) -
2494                                                             (long) (xentry.green >> 8)) +
2495                                                            ((long) (xc_cache[j].blue >> 8) -
2496                                                             (long) (xentry.blue >> 8)) *
2497                                                            ((long) (xc_cache[j].blue >> 8) -
2498                                                             (long) (xentry.blue >> 8));
2499                                            }
2500                                            if (nDist < nMinDist)
2501                                            {
2502                                                    nMinDist = nDist;
2503                                                    xentry.pixel = j;
2504                                            }
2505                                    }
2506                            }
2507                            colour = xentry.pixel;
2508    
2509                            /* update our cache */
2510                            if (xentry.pixel < 256)
2511                            {
2512                                    xc_cache[xentry.pixel].red = xentry.red;
2513                                    xc_cache[xentry.pixel].green = xentry.green;
2514                                    xc_cache[xentry.pixel].blue = xentry.blue;
2515    
2516                            }
2517    
2518                            map[i] = colour;
2519                    }
2520                    return map;
2521          }          }
2522          else          else
2523          {          {
2524                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  XColor *xcolours, *xentry;
2525                  XColor xentry;                  Colormap map;
                 uint32 colour;  
2526    
2527                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
2528                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
2529                  {                  {
2530                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2531                          MAKE_XCOLOR(&xentry, entry);                          xentry = &xcolours[i];
2532                            xentry->pixel = i;
2533                          if (XAllocColor(display, xcolmap, &xentry) != 0)                          MAKE_XCOLOR(xentry, entry);
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
2534                  }                  }
2535    
2536                  return map;                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
2537                    XStoreColors(g_display, map, xcolours, ncolours);
2538    
2539                    xfree(xcolours);
2540                    return (HCOLOURMAP) map;
2541          }          }
2542  }  }
2543    
2544  void  void
2545  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
2546  {  {
2547          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
2548                  xfree(map);                  xfree(map);
2549            else
2550                    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                  XSetWindowColormap(display, wnd, (Colormap)map);          {
2558                    if (g_colmap)
2559                            xfree(g_colmap);
2560    
2561                    g_colmap = (uint32 *) map;
2562            }
2563          else          else
2564                  colmap = 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()  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()  ui_bell(void)
2592  {  {
2593          XBell(display, 0);          XBell(g_display, 0);
2594  }  }
2595    
2596  void  void
# Line 783  ui_destblt(uint8 opcode, Line 2602  ui_destblt(uint8 opcode,
2602          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2603  }  }
2604    
2605    static uint8 hatch_patterns[] = {
2606            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2607            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2608            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2609            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2610            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2611            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
2612    };
2613    
2614  void  void
2615  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
2616            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2617            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2618  {  {
2619          Pixmap fill;          Pixmap fill;
2620            uint8 i, ipattern[8];
2621    
2622          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2623    
# Line 796  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 3: /* Pattern */                  case 2: /* Hatch */
2632                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          fill = (Pixmap) ui_create_glyph(8, 8,
2633                                                            hatch_patterns + brush->pattern[0] * 8);
2634                            SET_FOREGROUND(fgcolour);
2635                            SET_BACKGROUND(bgcolour);
2636                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2637                            XSetStipple(g_display, g_gc, fill);
2638                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2639                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2640                            XSetFillStyle(g_display, g_gc, FillSolid);
2641                            XSetTSOrigin(g_display, g_gc, 0, 0);
2642                            ui_destroy_glyph((HGLYPH) fill);
2643                            break;
2644    
2645                    case 3: /* Pattern */
2646                            for (i = 0; i != 8; i++)
2647                                    ipattern[7 - i] = brush->pattern[i];
2648                            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);
2657                          XSetFillStyle(display, gc, FillSolid);                          ui_destroy_glyph((HGLYPH) fill);
                         ui_destroy_glyph((HGLYPH)fill);  
2658                          break;                          break;
2659    
2660                  default:                  default:
# Line 819  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 827  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,                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2682                            cx, cy, x, y);                            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 840  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,                                  (g_display, (Pixmap) src, sw->wnd, g_gc,
2706                            cx, cy, x, y);                                   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 851  void Line 2713  void
2713  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2714            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2715            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
2716            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2717  {  {
2718          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
2719             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 860  ui_triblt(uint8 opcode, Line 2722  ui_triblt(uint8 opcode,
2722          {          {
2723                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
2724                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2725                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2726                          break;                          break;
2727    
2728                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
2729                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2730                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2731                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2732                          break;                          break;
2733    
2734                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
2735                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2736                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
2737                          break;                          break;
2738    
2739                  default:                  default:
# Line 887  ui_triblt(uint8 opcode, Line 2745  ui_triblt(uint8 opcode,
2745  void  void
2746  ui_line(uint8 opcode,  ui_line(uint8 opcode,
2747          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
2748          /* pen */ PEN *pen)          /* pen */ PEN * pen)
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 907  ui_rect( Line 2768  ui_rect(
2768  }  }
2769    
2770  void  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 */
2920    void
2921  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
2922                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
2923                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
2924                int fgcolour)                int bgcolour, int fgcolour)
2925  {  {
2926          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
2927          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2928    
2929          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
2930                        ? 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(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) \
2940    {\
2941      glyph = cache_get_font (font, ttext[idx]);\
2942      if (!(flags & TEXT2_IMPLICIT_X))\
2943      {\
2944        xyoffset = ttext[++idx];\
2945        if ((xyoffset & 0x80))\
2946        {\
2947          if (flags & TEXT2_VERTICAL)\
2948            y += ttext[idx+1] | (ttext[idx+2] << 8);\
2949          else\
2950            x += ttext[idx+1] | (ttext[idx+2] << 8);\
2951          idx += 2;\
2952        }\
2953        else\
2954        {\
2955          if (flags & TEXT2_VERTICAL)\
2956            y += xyoffset;\
2957          else\
2958            x += xyoffset;\
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 boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2977               int bgcolour, 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, offset;          int i, j, xyoffset, x1, y1;
2983            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(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2996          }          }
2997          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
2998          {          {
2999                  FILL_RECTANGLE(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; i++)          for (i = 0; i < length;)
3008          {          {
3009                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
3010                  {                  {
3011                          offset = text[++i];                          case 0xff:
3012                          if (offset & 0x80)                                  /* At least two bytes needs to follow */
3013                                  offset = ((offset & 0x7f) << 8) | text[++i];                                  if (i + 3 > length)
3014                                    {
3015                                            warning("Skipping short 0xff command:");
3016                                            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 */
3026                                    text = &(text[i]);
3027                                    i = 0;
3028                                    break;
3029    
3030                          if (flags & TEXT2_VERTICAL)                          case 0xfe:
3031                                  y += offset;                                  /* At least one byte needs to follow */
3032                          else                                  if (i + 2 > length)
3033                                  x += offset;                                  {
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]);
3042                                    if (entry->data != NULL)
3043                                    {
3044                                            if ((((uint8 *) (entry->data))[1] == 0)
3045                                                && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
3046                                            {
3047                                                    if (flags & TEXT2_VERTICAL)
3048                                                            y += text[i + 2];
3049                                                    else
3050                                                            x += text[i + 2];
3051                                            }
3052                                            for (j = 0; j < entry->size; j++)
3053                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
3054                                    }
3055                                    if (i + 2 < length)
3056                                            i += 3;
3057                                    else
3058                                            i += 2;
3059                                    length -= i;
3060                                    /* this will move pointer from start to first character after FE command */
3061                                    text = &(text[i]);
3062                                    i = 0;
3063                                    break;
3064    
3065                            default:
3066                                    DO_GLYPH(text, i);
3067                                    i++;
3068                                    break;
3069                  }                  }
3070            }
3071    
3072                  if (glyph != NULL)          XSetFillStyle(g_display, g_gc, FillSolid);
                 {  
                         ui_draw_glyph(mixmode, x + (short) glyph->offset,  
                                       y + (short) glyph->baseline,  
                                       glyph->width, glyph->height,  
                                       glyph->pixmap, 0, 0,  
                                       bgcolour, fgcolour);  
3073    
3074                          if (flags & TEXT2_IMPLICIT_X)          if (g_ownbackstore)
3075                                  x += glyph->width;          {
3076                    if (boxcx > 1)
3077                    {
3078                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3079                                      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
3087                    {
3088                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3089                                      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  }  }
# Line 982  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,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   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,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3114                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
3115          }          }
3116    
3117          offset *= bpp/8;          offset *= g_bpp / 8;
3118          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
                           bpp/8, image->data);  
3119    
3120          XDestroyImage(image);          XDestroyImage(image);
3121  }  }
# Line 1009  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,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3135                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * 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.35  
changed lines
  Added in v.1157

  ViewVC Help
Powered by ViewVC 1.1.26