/[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 311 by jsorg71, Wed Feb 5 14:16:33 2003 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 BOOL hide_decorations;  extern BOOL g_sendmotion;
37  extern char title[];  extern BOOL g_fullscreen;
38  extern int server_bpp;  extern BOOL g_grab_keyboard;
39  BOOL enable_compose = False;  extern BOOL g_hide_decorations;
40  BOOL focused;  extern char g_title[];
41  BOOL mouse_in_wnd;  /* Color depth of the RDP session.
42       As of RDP 5.1, it may be 8, 15, 16 or 24. */
43  Display *display;  extern int g_server_depth;
44  static int x_socket;  extern int g_win_button_size;
45  static Screen *screen;  
46  static Window wnd;  Display *g_display;
47  static GC gc;  Time g_last_gesturetime;
48  static Visual *visual;  static int g_x_socket;
49  static int depth;  static Screen *g_screen;
50  static int bpp;  Window g_wnd;
51  static XIM IM;  
52  static XIC IC;  /* SeamlessRDP support */
53  static XModifierKeymap *mod_map;  typedef struct _seamless_window
54  static Cursor current_cursor;  {
55  static Atom protocol_atom, kill_atom;          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 */  /* MWM decorations */
145  #define MWM_HINTS_DECORATIONS   (1L << 1)  #define MWM_HINTS_DECORATIONS   (1L << 1)
146  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
147  typedef struct  typedef struct
148  {  {
149          uint32 flags;          unsigned long flags;
150          uint32 functions;          unsigned long functions;
151          uint32 decorations;          unsigned long decorations;
152          sint32 inputMode;          long inputMode;
153          uint32 status;          unsigned long status;
154  }  }
155  PropMotifWmHints;  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  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
209  { \  { \
210          XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
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 DRAW_ELLIPSE(x,y,cx,cy,m)\
222    { \
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 */  /* colour maps */
242  BOOL owncolmap = False;  extern BOOL g_owncolmap;
243  static Colormap xcolmap;  static Colormap g_xcolmap;
244  static uint32 *colmap;  static uint32 *g_colmap = NULL;
245    
246  #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
247  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
248  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #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 112  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  void  static seamless_window *
273  mwm_hide_decorations(void)  sw_get_window_by_id(unsigned long id)
274    {
275            seamless_window *sw;
276            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    
285    static seamless_window *
286    sw_get_window_by_wnd(Window wnd)
287    {
288            seamless_window *sw;
289            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    
298    static void
299    sw_remove_window(seamless_window * win)
300    {
301            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    
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                    if (sw->wnd == wnd)
324                            continue;
325                    if (sw->desktop != desktop)
326                    {
327                            ewmh_move_to_desktop(sw->wnd, desktop);
328                            sw->desktop = desktop;
329                    }
330            }
331    }
332    
333    
334    /* Send our position */
335    static void
336    sw_update_position(seamless_window * sw)
337    {
338            XWindowAttributes wa;
339            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    
359    /* Check if it's time to send our position */
360    static void
361    sw_check_timers()
362    {
363            seamless_window *sw;
364            struct timeval now;
365    
366            gettimeofday(&now, NULL);
367            for (sw = g_seamless_windows; sw; sw = sw->next)
368            {
369                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
370                    {
371                            timerclear(sw->position_timer);
372                            sw_update_position(sw);
373                    }
374            }
375    }
376    
377    
378    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;
388            }
389    
390            if (sw_above)
391                    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;
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            for (i++; i < nchildren; i++)
432            {
433                    sw_below = sw_get_window_by_wnd(children[i]);
434                    if (sw_below)
435                            break;
436            }
437    
438            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;          PropMotifWmHints motif_hints;
460          Atom hintsatom;          Atom hintsatom;
# Line 126  mwm_hide_decorations(void) Line 464  mwm_hide_decorations(void)
464          motif_hints.decorations = 0;          motif_hints.decorations = 0;
465    
466          /* get the atom for the property */          /* get the atom for the property */
467          hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);          hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
468          if (!hintsatom)          if (!hintsatom)
469          {          {
470                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
471                  return;                  return;
472          }          }
473    
474          XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
475                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
 }  
476    
 uint32  
 colour16to24(uint32 colour)  
 {  
         int r;  
         int g;  
         int b;  
         r = (colour & 0xf800) >> 11;  
         r = (r * 0xff) / 0x1f;  
         g = (colour & 0x07e0) >> 5;  
         g = (g * 0xff) / 0x3f;  
         b = (colour & 0x001f);  
         b = (b * 0xff) / 0x1f;  
         return (r << 16) | (g << 8) | b;  
477  }  }
478    
479  uint32  #define SPLITCOLOUR15(colour, rv) \
480  colour16to32(uint32 colour)  { \
481  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
482          return colour16to24(colour);          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
483            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
484  }  }
485    
486  uint32  #define SPLITCOLOUR16(colour, rv) \
487  colour24to32(uint32 colour)  { \
488  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
489          return colour;          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 (server_bpp)          PixelColour pc;
524            switch (g_server_depth)
525          {          {
526                    case 15:
527                            SPLITCOLOUR15(colour, pc);
528                            break;
529                  case 16:                  case 16:
530                          switch (bpp)                          SPLITCOLOUR16(colour, pc);
                         {  
                                 case 16:  
                                         break;  
                                 case 24:  
                                         colour = colour16to24(colour);  
                                         break;  
                                 case 32:  
                                         colour = colour16to32(colour);  
                                         break;  
                         }  
531                          break;                          break;
532                  case 24:                  case 24:
533                          switch (bpp)                          SPLITCOLOUR24(colour, pc);
534                          {                          break;
535                                  case 24:                  default:
536                                          break;                          /* Avoid warning */
537                                  case 32:                          pc.red = 0;
538                                          colour = colour24to32(colour);                          pc.green = 0;
539                                          break;                          pc.blue = 0;
                         }  
540                          break;                          break;
541          }          }
542          switch (bpp)          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                  case 16:                  /* *INDENT-OFF* */
595                          if (host_be != xserver_be)                  REPEAT2
596                                  BSWAP16(colour);                  (
597                          break;                          *((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                  case 24:  /* little endian - conversion happens when colourmap is built */
621                          if (xserver_be)  static void
622                                  BSWAP24(colour);  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
623                          break;  {
624            uint32 value;
625    
626                  case 32:          if (g_compatible_arch)
627                          if (host_be != xserver_be)          {
628                                  BSWAP32(colour);                  while (out < end)
629                          break;                  {
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  static void
678  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
679  {  {
680          while (out < end)          uint16 pixel;
681                  *(out++) = (uint8) colmap[*(data++)];          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  static void
715  translate8to16(uint8 * data, uint16 * out, uint16 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
716  {  {
717          while (out < end)          uint32 value;
718                  *(out++) = (uint16) colmap[*(data++)];          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  static void
765  translate16to16(uint16 * data, uint16 * out, uint16 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
766  {  {
767          while (out < end)          uint16 pixel;
768                  *(out++) = (uint16) translate_colour(*(data++));          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    
 /* little endian - conversion happens when colourmap is built */  
815  static void  static void
816  translate8to24(uint8 * data, uint8 * out, uint8 * end)  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;          uint32 value;
876            uint16 pixel;
877            PixelColour pc;
878    
879          while (out < end)          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                  value = colmap[*(data++)];                  if (g_host_be)
919                  *(out++) = value;                  {
920                  *(out++) = value >> 8;                          while (out < end)
921                  *(out++) = value >> 16;                          {
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  static void
943  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
944  {  {
945            uint16 pixel;
946          uint32 value;          uint32 value;
947            PixelColour pc;
948    
949          while (out < end)          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                  value = translate_colour(*(data++));                  if (g_host_be)
966                  *(out++) = value;                  {
967                  *(out++) = value >> 8;                          while (out < end)
968                  *(out++) = value >> 16;                          {
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  static void
1014  translate8to32(uint8 * data, uint32 * out, uint32 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
1015  {  {
1016            uint32 pixel = 0;
1017            uint16 value;
1018            PixelColour pc;
1019    
1020          while (out < end)          while (out < end)
1021                  *(out++) = colmap[*(data++)];          {
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  static void
1039  translate16to32(uint16 * data, uint32 * out, uint32 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
1040  {  {
1041          while (out < end)          uint32 pixel;
1042                  *(out++) = translate_colour(*(data++));          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 *  static uint8 *
1127  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
1128  {  {
1129          int size = width * height * bpp / 8;          int size;
1130          uint8 *out = xmalloc(size);          uint8 *out;
1131          uint8 *end = out + size;          uint8 *end;
1132    
1133          if (server_bpp == 16)          /*
1134          {             If RDP depth and X Visual depths match,
1135                  if (bpp == 16)             and arch(endian) matches, no need to translate:
1136                          translate16to16((uint16 *) data, (uint16 *) out, (uint16 *) end);             just return data.
1137                  else if (bpp == 24)             Note: select_visual should've already ensured g_no_translate
1138                          translate16to24((uint16 *) data, out, end); /* todo, check this one */             is only set for compatible depths, but the RDP depth might've
1139                  else if (bpp == 32)             changed during connection negotiations.
1140                          translate16to32((uint16 *) data, (uint32 *) out, (uint32 *) end);           */
1141                  return out;          if (g_no_translate_image)
1142          }          {
1143          /* todo needs server_bpp == 24 */                  if ((g_depth == 15 && g_server_depth == 15) ||
1144          switch (bpp)                      (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 8:                  case 24:
1156                          translate8to8(data, out, end);                          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;                          break;
   
1169                  case 16:                  case 16:
1170                          translate8to16(data, (uint16 *) out, (uint16 *) end);                          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;                          break;
1183                    case 15:
1184                  case 24:                          switch (g_bpp)
1185                          translate8to24(data, out, end);                          {
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;                          break;
1197                    case 8:
1198                  case 32:                          switch (g_bpp)
1199                          translate8to32(data, (uint32 *) out, (uint32 *) end);                          {
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;                          break;
1214          }          }
   
1215          return out;          return out;
1216  }  }
1217    
# Line 329  get_key_state(unsigned int state, uint32 Line 1221  get_key_state(unsigned int state, uint32
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 348  get_key_state(unsigned int state, uint32 Line 1240  get_key_state(unsigned int state, uint32
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            red_weight = blue_weight = green_weight = 0;
1277    
1278          display = XOpenDisplay(NULL);          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1279          if (display == NULL)          if (pfm == NULL)
1280          {          {
1281                  error("Failed to open display: %s\n", XDisplayName(NULL));                  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          pfm = XListPixmapFormats(display, &i);                  /* we use a colourmap, so the default visual should do */
1407          if (pfm != NULL)                  g_owncolmap = True;
1408                    g_visual = vmatches[0].visual;
1409                    g_depth = vmatches[0].depth;
1410            }
1411    
1412            g_bpp = 0;
1413            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                  }                  }
1447                  XFree(pfm);          }
1448            XFree(pfm);
1449            pfm = NULL;
1450            return True;
1451    }
1452    
1453    BOOL
1454    ui_init(void)
1455    {
1456            int screen_num;
1457    
1458            g_display = XOpenDisplay(NULL);
1459            if (g_display == NULL)
1460            {
1461                    error("Failed to open display: %s\n", XDisplayName(NULL));
1462                    return False;
1463          }          }
1464    
         if (bpp < 8)  
1465          {          {
1466                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1467                  XCloseDisplay(display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1468            }
1469    
1470            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1471            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            if (!select_visual())
1477                  return False;                  return False;
1478    
1479            if (g_no_translate_image)
1480            {
1481                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1482          }          }
1483    
1484          if (owncolmap != True)          if (g_server_depth > g_bpp)
1485          {          {
1486                  xcolmap = DefaultColormapOfScreen(screen);                  warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1487                  if (depth <= 8)                          g_server_depth, g_bpp);
                         warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");  
1488          }          }
1489    
1490          gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);          DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1491                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1492    
1493          if (DoesBackingStore(screen) != Always)          if (!g_owncolmap)
1494                  ownbackstore = True;          {
1495                    g_xcolmap =
1496                            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          test = 1;          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1503          host_be = !(BOOL) (*(uint8 *) (&test));          {
1504          xserver_be = (ImageByteOrder(display) == MSBFirst);                  warning("External BackingStore not available. Using internal.\n");
1505                    g_ownbackstore = True;
1506            }
1507    
1508          if ((width == 0) || (height == 0))          /*
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 */                  /* Fetch geometry from _NET_WORKAREA */
1528                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1529                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1530                  {                  {
1531                          width = cx;                          g_width = cx;
1532                          height = cy;                          g_height = cy;
1533                            g_using_full_workarea = True;
1534                  }                  }
1535                  else                  else
1536                  {                  {
1537                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1538                          width = 800;                          g_width = WidthOfScreen(g_screen);
1539                          height = 600;                          g_height = HeightOfScreen(g_screen);
1540                  }                  }
1541          }          }
1542    
         if (fullscreen)  
         {  
                 width = WidthOfScreen(screen);  
                 height = HeightOfScreen(screen);  
         }  
   
1543          /* make sure width is a multiple of 4 */          /* make sure width is a multiple of 4 */
1544          width = (width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1545    
1546          if (ownbackstore)          g_mod_map = XGetModifierMapping(g_display);
         {  
                 backstore =  
                         XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);  
1547    
1548                  /* clear to prevent rubbish being exposed at startup */          xkeymap_init();
                 XSetForeground(display, gc, BlackPixelOfScreen(screen));  
                 XFillRectangle(display, backstore, gc, 0, 0, width, height);  
         }  
1549    
1550          mod_map = XGetModifierMapping(display);          if (g_enable_compose)
1551                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1552    
1553          if (enable_compose)          xclip_init();
1554                  IM = XOpenIM(display, NULL, NULL, NULL);          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    
         xkeymap_init();  
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            if (g_null_cursor != NULL)
1570                    ui_destroy_cursor(g_null_cursor);
1571    
1572          XFreeModifiermap(mod_map);          XFreeModifiermap(g_mod_map);
1573    
1574          if (ownbackstore)          if (g_ownbackstore)
1575                  XFreePixmap(display, backstore);                  XFreePixmap(g_display, g_backstore);
1576    
1577          XFreeGC(display, gc);          XFreeGC(g_display, g_gc);
1578          XCloseDisplay(display);          XCloseDisplay(g_display);
1579          display = NULL;          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    static void
1595    get_input_mask(long *input_mask)
1596    {
1597            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1598                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1599    
1600            if (g_sendmotion)
1601                    *input_mask |= PointerMotionMask;
1602            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 477  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          attribs.background_pixel = BlackPixelOfScreen(screen);          get_window_attribs(&attribs);
         attribs.backing_store = ownbackstore ? NotUseful : Always;  
         attribs.override_redirect = fullscreen;  
1633    
1634          wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1635                              0, CopyFromParent, InputOutput, CopyFromParent,                                wndheight, 0, g_depth, InputOutput, g_visual,
1636                              CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1637                                  CWBorderPixel, &attribs);
1638    
1639          XStoreName(display, wnd, title);          if (g_gc == NULL)
1640            {
1641                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1642                    ui_reset_clip();
1643            }
1644    
1645          if (hide_decorations)          if (g_create_bitmap_gc == NULL)
1646                  mwm_hide_decorations();                  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            XStoreName(g_display, g_wnd, g_title);
1658    
1659            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 505  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;  
         if (fullscreen || grab_keyboard)  
                 input_mask |= EnterWindowMask;  
         if (grab_keyboard)  
                 input_mask |= LeaveWindowMask;  
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          focused = False;          g_focused = False;
1711          mouse_in_wnd = False;          g_mouse_in_wnd = False;
1712    
1713          /* handle the WM_DELETE_WINDOW protocol */          /* handle the WM_DELETE_WINDOW protocol */
1714          protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);          g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1715          kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);          g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1716          XSetWMProtocols(display, wnd, &kill_atom, 1);          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 568  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 (!g_ownbackstore)
1790            {
1791                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1792                    XFreePixmap(g_display, contents);
1793            }
1794    }
1795    
1796    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          if (!ownbackstore)          /* 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                  XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);                  /*  Check from right to left: */
1816                  XFreePixmap(display, contents);                  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  /* Process all events in Xlib queue  
1878    /* Process events in Xlib queue
1879     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1880  static int  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:                          case ClientMessage:
1910                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1911                                  if ((xevent.xclient.message_type == protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
1912                                      && (xevent.xclient.data.l[0] == kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1913                                          /* Quit */                                          /* Quit */
1914                                          return 0;                                          return 0;
1915                                  break;                                  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 648  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,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1941                                             get_ksname(keysym)));                                             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                                  if (fullscreen && !focused)                                  if (g_moving_wnd)
1977                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                  {
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);                                                         CurrentTime);
1987                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1988                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  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                                  if (xevent.xfocus.mode == NotifyGrab)                                  if (xevent.xfocus.mode == NotifyGrab)
2004                                          break;                                          break;
2005                                  focused = True;                                  g_focused = True;
2006                                  XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,                                  reset_modifier_keys();
2007                                                &dummy, &dummy, &state);                                  if (g_grab_keyboard && g_mouse_in_wnd)
2008                                  reset_modifier_keys(state);                                          XGrabKeyboard(g_display, g_wnd, True,
                                 if (grab_keyboard && mouse_in_wnd)  
                                         XGrabKeyboard(display, 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)                                  if (xevent.xfocus.mode == NotifyUngrab)
2024                                          break;                                          break;
2025                                  focused = False;                                  g_focused = False;
2026                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)                                  if (xevent.xfocus.mode == NotifyWhileGrabbed)
2027                                          XUngrabKeyboard(display, CurrentTime);                                          XUngrabKeyboard(g_display, CurrentTime);
2028                                  break;                                  break;
2029    
2030                          case EnterNotify:                          case EnterNotify:
2031                                  /* we only register for this event when in fullscreen mode */                                  /* we only register for this event when in fullscreen mode */
2032                                  /* or grab_keyboard */                                  /* or grab_keyboard */
2033                                  mouse_in_wnd = True;                                  g_mouse_in_wnd = True;
2034                                  if (fullscreen)                                  if (g_fullscreen)
2035                                  {                                  {
2036                                          XSetInputFocus(display, wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
2037                                                         CurrentTime);                                                         CurrentTime);
2038                                          break;                                          break;
2039                                  }                                  }
2040                                  if (focused)                                  if (g_focused)
2041                                          XGrabKeyboard(display, wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2042                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2043                                  break;                                  break;
2044    
2045                          case LeaveNotify:                          case LeaveNotify:
2046                                  /* we only register for this event when grab_keyboard */                                  /* we only register for this event when grab_keyboard */
2047                                  mouse_in_wnd = False;                                  g_mouse_in_wnd = False;
2048                                  XUngrabKeyboard(display, CurrentTime);                                  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 765  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;                                  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;
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 */          /* Keep going */
# Line 780  xwin_process_events(void) Line 2172  xwin_process_events(void)
2172  int  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                  if (!xwin_process_events())                  if (!xwin_process_events())
2185                          /* User quit */                          /* User quit */
2186                          return 0;                          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 1;                          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 822  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          tdata = (owncolmap ? data : translate_image(width, height, data));                  if (g_bpp == 24)
2261          bitmap = XCreatePixmap(display, wnd, width, height, depth);                          bitmap_pad = 32;
2262          image = XCreateImage(display, visual, depth, ZPixmap, 0,          }
2263                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);  
2264            tdata = (g_owncolmap ? data : translate_image(width, height, data));
2265            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
2266            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2267                                 (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          if (!owncolmap)          if (tdata != data)
2273                  xfree(tdata);                  xfree(tdata);
2274          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
2275  }  }
# Line 841  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          tdata = (owncolmap ? data : translate_image(width, height, data));          int bitmap_pad;
         image = XCreateImage(display, visual, depth, ZPixmap, 0,  
                              (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);  
2283    
2284          if (ownbackstore)          if (g_server_depth == 8)
2285          {          {
2286                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  bitmap_pad = 8;
                 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);  
2287          }          }
2288          else          else
2289          {          {
2290                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  bitmap_pad = g_bpp;
2291    
2292                    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(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2303                    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
2309            {
2310                    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          if (!owncolmap)          if (tdata != data)
2318                  xfree(tdata);                  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 872  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 914  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 959  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 972  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 994  ui_create_colourmap(COLOURMAP * colours) Line 2458  ui_create_colourmap(COLOURMAP * colours)
2458  {  {
2459          COLOURENTRY *entry;          COLOURENTRY *entry;
2460          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
2461          if (!owncolmap)          if (!g_owncolmap)
2462          {          {
2463                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
2464                  XColor xentry;                  XColor xentry;
2465                  XColor xc_cache[256];                  XColor xc_cache[256];
2466                  uint32 colour;                  uint32 colour;
# Line 1006  ui_create_colourmap(COLOURMAP * colours) Line 2470  ui_create_colourmap(COLOURMAP * colours)
2470                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2471                          MAKE_XCOLOR(&xentry, entry);                          MAKE_XCOLOR(&xentry, entry);
2472    
2473                          if (XAllocColor(display, xcolmap, &xentry) == 0)                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
2474                          {                          {
2475                                  /* Allocation failed, find closest match. */                                  /* Allocation failed, find closest match. */
2476                                  int j = 256;                                  int j = 256;
# Line 1020  ui_create_colourmap(COLOURMAP * colours) Line 2484  ui_create_colourmap(COLOURMAP * colours)
2484                                          xc_cache[colLookup].red = xc_cache[colLookup].green =                                          xc_cache[colLookup].red = xc_cache[colLookup].green =
2485                                                  xc_cache[colLookup].blue = 0;                                                  xc_cache[colLookup].blue = 0;
2486                                          xc_cache[colLookup].flags = 0;                                          xc_cache[colLookup].flags = 0;
2487                                          XQueryColor(display,                                          XQueryColor(g_display,
2488                                                      DefaultColormap(display,                                                      DefaultColormap(g_display,
2489                                                                      DefaultScreen(display)),                                                                      DefaultScreen(g_display)),
2490                                                      &xc_cache[colLookup]);                                                      &xc_cache[colLookup]);
2491                                  }                                  }
2492                                  colLookup = 0;                                  colLookup = 0;
# Line 1063  ui_create_colourmap(COLOURMAP * colours) Line 2527  ui_create_colourmap(COLOURMAP * colours)
2527    
2528                          }                          }
2529    
2530                            map[i] = colour;
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
2531                  }                  }
2532                  return map;                  return map;
2533          }          }
# Line 1074  ui_create_colourmap(COLOURMAP * colours) Line 2536  ui_create_colourmap(COLOURMAP * colours)
2536                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
2537                  Colormap map;                  Colormap map;
2538    
2539                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
2540                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
2541                  {                  {
2542                          entry = &colours->colours[i];                          entry = &colours->colours[i];
# Line 1083  ui_create_colourmap(COLOURMAP * colours) Line 2545  ui_create_colourmap(COLOURMAP * colours)
2545                          MAKE_XCOLOR(xentry, entry);                          MAKE_XCOLOR(xentry, entry);
2546                  }                  }
2547    
2548                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
2549                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2550    
2551                  xfree(xcolours);                  xfree(xcolours);
2552                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
# Line 1094  ui_create_colourmap(COLOURMAP * colours) Line 2556  ui_create_colourmap(COLOURMAP * colours)
2556  void  void
2557  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
2558  {  {
2559          if (!owncolmap)          if (!g_owncolmap)
2560                  xfree(map);                  xfree(map);
2561          else          else
2562                  XFreeColormap(display, (Colormap) map);                  XFreeColormap(g_display, (Colormap) map);
2563  }  }
2564    
2565  void  void
2566  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
2567  {  {
2568          if (!owncolmap)          if (!g_owncolmap)
2569                  colmap = map;          {
2570                    if (g_colmap)
2571                            xfree(g_colmap);
2572    
2573                    g_colmap = (uint32 *) map;
2574            }
2575          else          else
2576                  XSetWindowColormap(display, wnd, (Colormap) map);          {
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 1148  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 1162  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 1188  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 1196  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 1208  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 1254  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 1269  ui_rect( Line 2779  ui_rect(
2779          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2780  }  }
2781    
2782    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 */  /* warning, this function only draws on wnd or backstore, not both */
2932  void  void
2933  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1279  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_BACKSTORE(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 + glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2968                       y + 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_BACKSTORE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
# Line 1343  ui_draw_text(uint8 font, uint8 flags, in Line 3011  ui_draw_text(uint8 font, uint8 flags, in
3011                  FILL_RECTANGLE_BACKSTORE(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                                          exit(1);                                          for (j = 0; j < length; j++)
3029                                                    fprintf(stderr, "%02x ", text[j]);
3030                                            fprintf(stderr, "\n");
3031                                            i = length = 0;
3032                                            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];
# Line 1393  ui_draw_text(uint8 font, uint8 flags, in Line 3080  ui_draw_text(uint8 font, uint8 flags, in
3080                                  break;                                  break;
3081                  }                  }
3082          }          }
3083          if (ownbackstore)  
3084            XSetFillStyle(g_display, g_gc, FillSolid);
3085    
3086            if (g_ownbackstore)
3087          {          {
3088                  if (boxcx > 1)                  if (boxcx > 1)
3089                          XCopyArea(display, backstore, wnd, gc, boxx,                  {
3090                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3091                                    boxy, boxcx, boxcy, boxx, boxy);                                    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                  else
3099                          XCopyArea(display, backstore, wnd, gc, clipx,                  {
3100                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3101                                    clipy, clipcx, clipcy, clipx, clipy);                                    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    
# Line 1410  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 1434  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.311  
changed lines
  Added in v.1170

  ViewVC Help
Powered by ViewVC 1.1.26