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

Legend:
Removed from v.84  
changed lines
  Added in v.1168

  ViewVC Help
Powered by ViewVC 1.1.26