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

Legend:
Removed from v.263  
changed lines
  Added in v.1157

  ViewVC Help
Powered by ViewVC 1.1.26