/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC 1.1.26