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

Legend:
Removed from v.194  
changed lines
  Added in v.1181

  ViewVC Help
Powered by ViewVC 1.1.26