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

Legend:
Removed from v.208  
changed lines
  Added in v.1170

  ViewVC Help
Powered by ViewVC 1.1.26