/[rdesktop]/sourceforge.net/trunk/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/trunk/rdesktop/xwin.c

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

revision 64 by astrand, Thu Jul 18 16:38:31 2002 UTC revision 332 by astrand, Tue Feb 18 13:51:43 2003 UTC
# Line 1  Line 1 
1  /*  /*
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-2002
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>
 #include <X11/XKBlib.h>  
23  #include <time.h>  #include <time.h>
24  #include <errno.h>  #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    
 extern char keymapname[16];  
 extern int keylayout;  
27  extern int width;  extern int width;
28  extern int height;  extern int height;
29  extern BOOL sendmotion;  extern BOOL sendmotion;
30  extern BOOL fullscreen;  extern BOOL fullscreen;
31    extern BOOL grab_keyboard;
32    extern BOOL hide_decorations;
33    extern char title[];
34    extern int server_bpp;
35    extern int win_button_size;
36    BOOL enable_compose = False;
37    BOOL focused;
38    BOOL mouse_in_wnd;
39    
40  Display *display;  Display *display;
 XkbDescPtr xkb;  
41  static int x_socket;  static int x_socket;
42    static Screen *screen;
43  static Window wnd;  static Window wnd;
44  static GC gc;  static GC gc;
45  static Visual *visual;  static Visual *visual;
46  static int depth;  static int depth;
47  static int bpp;  static int bpp;
48    static XIM IM;
49    static XIC IC;
50    static XModifierKeymap *mod_map;
51    static Cursor current_cursor;
52    static Atom protocol_atom, kill_atom;
53    
54  /* endianness */  /* endianness */
55  static BOOL host_be;  static BOOL host_be;
# Line 49  static BOOL xserver_be; Line 59  static BOOL xserver_be;
59  static BOOL ownbackstore;  static BOOL ownbackstore;
60  static Pixmap backstore;  static Pixmap backstore;
61    
62  /* needed to keep track of the modifiers */  /* MWM decorations */
63  static unsigned int numlock_modifier_mask = 0;  #define MWM_HINTS_DECORATIONS   (1L << 1)
64  static unsigned int key_down_state = 0;  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
65    typedef struct
66    {
67  #define DShift1Mask   (1<<0)          uint32 flags;
68  #define DLockMask     (1<<1)          uint32 functions;
69  #define DControl1Mask (1<<2)          uint32 decorations;
70  #define DMod1Mask     (1<<3)          sint32 inputMode;
71  #define DMod2Mask     (1<<4)          uint32 status;
72  #define DMod3Mask     (1<<5)  }
73  #define DMod4Mask     (1<<6)  PropMotifWmHints;
74  #define DMod5Mask     (1<<7)  
75  #define DShift2Mask   (1<<8)  typedef struct
76  #define DControl2Mask (1<<9)  {
77  #define DNumLockMask  (1<<10)          uint32 red;
78            uint32 green;
79            uint32 blue;
80    }
81    PixelColour;
82    
83  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
84  { \  { \
# Line 73  static unsigned int key_down_state = 0; Line 87  static unsigned int key_down_state = 0;
87                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \
88  }  }
89    
90    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
91    { \
92            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
93    }
94    
95  /* colour maps */  /* colour maps */
96  static BOOL owncolmap;  BOOL owncolmap = False;
97  static Colormap xcolmap;  static Colormap xcolmap;
 static uint32 white;  
98  static uint32 *colmap;  static uint32 *colmap;
99    
100  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
101  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
102  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
103    
# Line 105  static int rop2_map[] = { Line 123  static int rop2_map[] = {
123  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
124  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
125    
126  void xwin_get_numlock_mask();  static void
127  void xwin_mod_update(uint32 state, uint32 ev_time);  mwm_hide_decorations(void)
128  void xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode);  {
129  void xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode);          PropMotifWmHints motif_hints;
130            Atom hintsatom;
131    
132            /* setup the property */
133            motif_hints.flags = MWM_HINTS_DECORATIONS;
134            motif_hints.decorations = 0;
135    
136            /* get the atom for the property */
137            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
138            if (!hintsatom)
139            {
140                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
141                    return;
142            }
143    
144            XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
145                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
146    }
147    
148    static PixelColour
149    split_colour15(uint32 colour)
150    {
151            PixelColour rv;
152            rv.red = (colour & 0x7c00) >> 10;
153            rv.red = (rv.red * 0xff) / 0x1f;
154            rv.green = (colour & 0x03e0) >> 5;
155            rv.green = (rv.green * 0xff) / 0x1f;
156            rv.blue = (colour & 0x1f);
157            rv.blue = (rv.blue * 0xff) / 0x1f;
158            return rv;
159    }
160    
161    static PixelColour
162    split_colour16(uint32 colour)
163    {
164            PixelColour rv;
165            rv.red = (colour & 0xf800) >> 11;
166            rv.red = (rv.red * 0xff) / 0x1f;
167            rv.green = (colour & 0x07e0) >> 5;
168            rv.green = (rv.green * 0xff) / 0x3f;
169            rv.blue = (colour & 0x001f);
170            rv.blue = (rv.blue * 0xff) / 0x1f;
171            return rv;
172    }
173    
174    static PixelColour
175    split_colour24(uint32 colour)
176    {
177            PixelColour rv;
178            rv.blue = (colour & 0xff0000) >> 16;
179            rv.green = (colour & 0xff00) >> 8;
180            rv.red = (colour & 0xff);
181            return rv;
182    }
183    
184    static uint32
185    make_colour16(PixelColour pc)
186    {
187            pc.red = (pc.red * 0x1f) / 0xff;
188            pc.green = (pc.green * 0x3f) / 0xff;
189            pc.blue = (pc.blue * 0x1f) / 0xff;
190            return (pc.red << 11) | (pc.green << 5) | pc.blue;
191    }
192    
193    static uint32
194    make_colour24(PixelColour pc)
195    {
196            return (pc.red << 16) | (pc.green << 8) | pc.blue;
197    }
198    
199    static uint32
200    make_colour32(PixelColour pc)
201    {
202            return (pc.red << 16) | (pc.green << 8) | pc.blue;
203    }
204    
205    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
206    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
207    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
208                            x = (x << 16) | (x >> 16); }
209    
210    static uint32
211    translate_colour(uint32 colour)
212    {
213            switch (server_bpp)
214            {
215                    case 15:
216                            switch (bpp)
217                            {
218                                    case 16:
219                                            colour = make_colour16(split_colour15(colour));
220                                            break;
221                                    case 24:
222                                            colour = make_colour24(split_colour15(colour));
223                                            break;
224                                    case 32:
225                                            colour = make_colour32(split_colour15(colour));
226                                            break;
227                            }
228                            break;
229                    case 16:
230                            switch (bpp)
231                            {
232                                    case 16:
233                                            break;
234                                    case 24:
235                                            colour = make_colour24(split_colour16(colour));
236                                            break;
237                                    case 32:
238                                            colour = make_colour32(split_colour16(colour));
239                                            break;
240                            }
241                            break;
242                    case 24:
243                            switch (bpp)
244                            {
245                                    case 16:
246                                            colour = make_colour16(split_colour24(colour));
247                                            break;
248                                    case 24:
249                                            break;
250                                    case 32:
251                                            colour = make_colour32(split_colour24(colour));
252                                            break;
253                            }
254                            break;
255            }
256            switch (bpp)
257            {
258                    case 16:
259                            if (host_be != xserver_be)
260                                    BSWAP16(colour);
261                            break;
262    
263                    case 24:
264                            if (xserver_be)
265                                    BSWAP24(colour);
266                            break;
267    
268                    case 32:
269                            if (host_be != xserver_be)
270                                    BSWAP32(colour);
271                            break;
272            }
273    
274            return colour;
275    }
276    
277  static void  static void
278  translate8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(uint8 * data, uint8 * out, uint8 * end)
279  {  {
280          while (out < end)          while (out < end)
281                  *(out++) = (uint8) colmap[*(data++)];                  *(out++) = (uint8) colmap[*(data++)];
282  }  }
283    
284  static void  static void
285  translate16(uint8 * data, uint16 * out, uint16 * end)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
286  {  {
287          while (out < end)          while (out < end)
288                  *(out++) = (uint16) colmap[*(data++)];                  *(out++) = (uint16) colmap[*(data++)];
# Line 126  translate16(uint8 * data, uint16 * out, Line 290  translate16(uint8 * data, uint16 * out,
290    
291  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
292  static void  static void
293  translate24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
294  {  {
295          uint32 value;          uint32 value;
296    
# Line 140  translate24(uint8 * data, uint8 * out, u Line 304  translate24(uint8 * data, uint8 * out, u
304  }  }
305    
306  static void  static void
307  translate32(uint8 * data, uint32 * out, uint32 * end)  translate8to32(uint8 * data, uint32 * out, uint32 * end)
308  {  {
309          while (out < end)          while (out < end)
310                  *(out++) = colmap[*(data++)];                  *(out++) = colmap[*(data++)];
311  }  }
312    
313    /* todo the remaining translate function might need some big endian check ?? */
314    
315    static void
316    translate15to16(uint16 * data, uint16 * out, uint16 * end)
317    {
318            while (out < end)
319                    *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
320    }
321    
322    static void
323    translate15to24(uint16 * data, uint8 * out, uint8 * end)
324    {
325            uint32 value;
326    
327            while (out < end)
328            {
329                    value = make_colour24(split_colour15(*(data++)));
330                    *(out++) = value;
331                    *(out++) = value >> 8;
332                    *(out++) = value >> 16;
333            }
334    }
335    
336    static void
337    translate15to32(uint16 * data, uint32 * out, uint32 * end)
338    {
339            while (out < end)
340                    *(out++) = make_colour32(split_colour15(*(data++)));
341    }
342    
343    static void
344    translate16to16(uint16 * data, uint16 * out, uint16 * end)
345    {
346            while (out < end)
347                    *(out++) = (uint16) (*(data++));
348    }
349    
350    
351    static void
352    translate16to24(uint16 * data, uint8 * out, uint8 * end)
353    {
354            uint32 value;
355    
356            while (out < end)
357            {
358                    value = make_colour24(split_colour16(*(data++)));
359                    *(out++) = value;
360                    *(out++) = value >> 8;
361                    *(out++) = value >> 16;
362            }
363    }
364    
365    static void
366    translate16to32(uint16 * data, uint32 * out, uint32 * end)
367    {
368            while (out < end)
369                    *(out++) = make_colour32(split_colour16(*(data++)));
370    }
371    
372    static void
373    translate24to16(uint8 * data, uint16 * out, uint16 * end)
374    {
375            uint32 pixel = 0;
376            while (out < end)
377            {
378                    pixel = *(data++) << 16;
379                    pixel |= *(data++) << 8;
380                    pixel |= *(data++);
381                    *(out++) = (uint16) make_colour16(split_colour24(pixel));
382            }
383    }
384    
385    static void
386    translate24to24(uint8 * data, uint8 * out, uint8 * end)
387    {
388            while (out < end)
389            {
390                    *(out++) = (*(data++));
391            }
392    }
393    
394    static void
395    translate24to32(uint8 * data, uint32 * out, uint32 * end)
396    {
397            uint32 pixel = 0;
398            while (out < end)
399            {
400                    memcpy(&pixel, data, 3);
401                    data += 3;
402                    *(out++) = pixel;
403            }
404    }
405    
406  static uint8 *  static uint8 *
407  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
408  {  {
# Line 153  translate_image(int width, int height, u Line 410  translate_image(int width, int height, u
410          uint8 *out = xmalloc(size);          uint8 *out = xmalloc(size);
411          uint8 *end = out + size;          uint8 *end = out + size;
412    
413          switch (bpp)          switch (server_bpp)
414          {          {
415                  case 8:                  case 24:
416                          translate8(data, out, end);                          switch (bpp)
417                            {
418                                    case 32:
419                                            translate24to32(data, (uint32 *) out, (uint32 *) end);
420                                            break;
421                                    case 24:
422                                            translate24to24(data, out, end);
423                                            break;
424                                    case 16:
425                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
426                                            break;
427                            }
428                          break;                          break;
   
429                  case 16:                  case 16:
430                          translate16(data, (uint16 *) out, (uint16 *) end);                          switch (bpp)
431                            {
432                                    case 32:
433                                            translate16to32((uint16 *) data, (uint32 *) out,
434                                                            (uint32 *) end);
435                                            break;
436                                    case 24:
437                                            translate16to24((uint16 *) data, out, end);
438                                            break;
439                                    case 16:
440                                            translate16to16((uint16 *) data, (uint16 *) out,
441                                                            (uint16 *) end);
442                                            break;
443                            }
444                          break;                          break;
445                    case 15:
446                  case 24:                          switch (bpp)
447                          translate24(data, out, end);                          {
448                                    case 32:
449                                            translate15to32((uint16 *) data, (uint32 *) out,
450                                                            (uint32 *) end);
451                                            break;
452                                    case 24:
453                                            translate15to24((uint16 *) data, out, end);
454                                            break;
455                                    case 16:
456                                            translate15to16((uint16 *) data, (uint16 *) out,
457                                                            (uint16 *) end);
458                                            break;
459                            }
460                          break;                          break;
461                    case 8:
462                  case 32:                          switch (bpp)
463                          translate32(data, (uint32 *) out, (uint32 *) end);                          {
464                                    case 8:
465                                            translate8to8(data, out, end);
466                                            break;
467                                    case 16:
468                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
469                                            break;
470                                    case 24:
471                                            translate8to24(data, out, end);
472                                            break;
473                                    case 32:
474                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
475                                            break;
476                            }
477                          break;                          break;
478          }          }
   
479          return out;          return out;
480  }  }
481    
482  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  BOOL
483  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  get_key_state(unsigned int state, uint32 keysym)
 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  
                         x = (x << 16) | (x >> 16); }  
   
 static uint32  
 translate_colour(uint32 colour)  
484  {  {
485          switch (bpp)          int modifierpos, key, keysymMask = 0;
486          {          int offset;
                 case 16:  
                         if (host_be != xserver_be)  
                                 BSWAP16(colour);  
                         break;  
487    
488                  case 24:          KeyCode keycode = XKeysymToKeycode(display, keysym);
                         if (xserver_be)  
                                 BSWAP24(colour);  
                         break;  
489    
490                  case 32:          if (keycode == NoSymbol)
491                          if (host_be != xserver_be)                  return False;
492                                  BSWAP32(colour);  
493                          break;          for (modifierpos = 0; modifierpos < 8; modifierpos++)
494            {
495                    offset = mod_map->max_keypermod * modifierpos;
496    
497                    for (key = 0; key < mod_map->max_keypermod; key++)
498                    {
499                            if (mod_map->modifiermap[offset + key] == keycode)
500                                    keysymMask |= 1 << modifierpos;
501                    }
502          }          }
503    
504          return colour;          return (state & keysymMask) ? True : False;
505  }  }
506    
507  BOOL  BOOL
508  ui_create_window(char *title)  ui_init(void)
509  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
510          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
         Screen *screen;  
511          uint16 test;          uint16 test;
512          int i;          int i;
513    
514          int xkb_minor, xkb_major;          display = XOpenDisplay(NULL);
         int xkb_event, xkb_error, xkb_reason;  
   
         /* compare compiletime libs with runtime libs. */  
         xkb_major = XkbMajorVersion;  
         xkb_minor = XkbMinorVersion;  
         if (XkbLibraryVersion(&xkb_major, &xkb_minor) == False)  
         {  
                 error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");  
                 return False;  
         }  
   
   
         display =  
                 XkbOpenDisplay(NULL, &xkb_event, &xkb_error, &xkb_major,  
                                &xkb_minor, &xkb_reason);  
         switch (xkb_reason)  
         {  
                 case XkbOD_BadLibraryVersion:  
                         error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");  
                         break;  
                 case XkbOD_ConnectionRefused:  
                         error("XkbOD_ConnectionRefused\n");  
                         break;  
                 case XkbOD_BadServerVersion:  
                         error("XkbOD_BadServerVersion\n");  
                         break;  
                 case XkbOD_NonXkbServer:  
                         error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");  
                         break;  
                 case XkbOD_Success:  
                         DEBUG("XkbOD_Success: Connection established with display\n");  
                         break;  
         }  
   
515          if (display == NULL)          if (display == NULL)
516          {          {
517                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
518                  return False;                  return False;
519          }          }
520    
# Line 269  ui_create_window(char *title) Line 530  ui_create_window(char *title)
530                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
531                  while (i--)                  while (i--)
532                  {                  {
533                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
534                          {                          {
535                                  bpp = pfm[i].bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
536                          }                          }
# Line 285  ui_create_window(char *title) Line 545  ui_create_window(char *title)
545                  return False;                  return False;
546          }          }
547    
548          if (depth <= 8)          if (owncolmap != True)
549                  owncolmap = True;          {
         else  
550                  xcolmap = DefaultColormapOfScreen(screen);                  xcolmap = DefaultColormapOfScreen(screen);
551                    if (depth <= 8)
552                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
553            }
554    
555            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
556    
557            if (DoesBackingStore(screen) != Always)
558                    ownbackstore = True;
559    
560          test = 1;          test = 1;
561          host_be = !(BOOL) (*(uint8 *) (&test));          host_be = !(BOOL) (*(uint8 *) (&test));
562          xserver_be = (ImageByteOrder(display) == MSBFirst);          xserver_be = (ImageByteOrder(display) == MSBFirst);
563    
564          white = WhitePixelOfScreen(screen);          if ((width == 0) || (height == 0))
565          attribs.background_pixel = BlackPixelOfScreen(screen);          {
566          attribs.backing_store = DoesBackingStore(screen);                  /* Fetch geometry from _NET_WORKAREA */
567                    uint32 x, y, cx, cy;
568    
569          if (attribs.backing_store == NotUseful)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
570                  ownbackstore = True;                  {
571                            width = cx;
572                            height = cy;
573                    }
574                    else
575                    {
576                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
577                            width = 800;
578                            height = 600;
579                    }
580            }
581    
582          if (fullscreen)          if (fullscreen)
583          {          {
                 attribs.override_redirect = True;  
584                  width = WidthOfScreen(screen);                  width = WidthOfScreen(screen);
585                  height = HeightOfScreen(screen);                  height = HeightOfScreen(screen);
586          }          }
587          else  
588            /* make sure width is a multiple of 4 */
589            width = (width + 3) & ~3;
590    
591            if (ownbackstore)
592          {          {
593                  attribs.override_redirect = False;                  backstore =
594                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
595    
596                    /* clear to prevent rubbish being exposed at startup */
597                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
598                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
599          }          }
600    
601          width = (width + 3) & ~3;       /* make width a multiple of 32 bits */          mod_map = XGetModifierMapping(display);
602    
603            if (enable_compose)
604                    IM = XOpenIM(display, NULL, NULL, NULL);
605    
606            xkeymap_init();
607    
608            /* todo take this out when high colour is done */
609            printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
610    
611          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          return True;
612                              0, 0, width, height, 0, CopyFromParent,  }
613                              InputOutput, CopyFromParent,  
614                              CWBackingStore | CWBackPixel | CWOverrideRedirect,  void
615                              &attribs);  ui_deinit(void)
616    {
617            if (IM != NULL)
618                    XCloseIM(IM);
619    
620            XFreeModifiermap(mod_map);
621    
622            if (ownbackstore)
623                    XFreePixmap(display, backstore);
624    
625            XFreeGC(display, gc);
626            XCloseDisplay(display);
627            display = NULL;
628    }
629    
630    BOOL
631    ui_create_window(void)
632    {
633            XSetWindowAttributes attribs;
634            XClassHint *classhints;
635            XSizeHints *sizehints;
636            int wndwidth, wndheight;
637            long input_mask, ic_input_mask;
638            XEvent xevent;
639    
640            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
641            wndheight = fullscreen ? HeightOfScreen(screen) : height;
642    
643            attribs.background_pixel = BlackPixelOfScreen(screen);
644            attribs.backing_store = ownbackstore ? NotUseful : Always;
645            attribs.override_redirect = fullscreen;
646    
647            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
648                                0, CopyFromParent, InputOutput, CopyFromParent,
649                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
650    
651          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
652    
653            if (hide_decorations)
654                    mwm_hide_decorations();
655    
656          classhints = XAllocClassHint();          classhints = XAllocClassHint();
657          if (classhints != NULL)          if (classhints != NULL)
658          {          {
# Line 340  ui_create_window(char *title) Line 671  ui_create_window(char *title)
671                  XFree(sizehints);                  XFree(sizehints);
672          }          }
673    
674          xkeymap_init();          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
675                    VisibilityChangeMask | FocusChangeMask;
676    
         input_mask = KeyPressMask | KeyReleaseMask |  
                 ButtonPressMask | ButtonReleaseMask |  
                 EnterWindowMask | LeaveWindowMask;  
677          if (sendmotion)          if (sendmotion)
678                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
   
679          if (ownbackstore)          if (ownbackstore)
680                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
681            if (fullscreen || grab_keyboard)
682                    input_mask |= EnterWindowMask;
683            if (grab_keyboard)
684                    input_mask |= LeaveWindowMask;
685    
686            if (IM != NULL)
687            {
688                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
689                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
690    
691                    if ((IC != NULL)
692                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
693                            input_mask |= ic_input_mask;
694            }
695    
696          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
         gc = XCreateGC(display, wnd, 0, NULL);  
   
         if (ownbackstore)  
                 backstore = XCreatePixmap(display, wnd, width, height, depth);  
   
697          XMapWindow(display, wnd);          XMapWindow(display, wnd);
698    
699          /* TODO: error texts... make them friendly. */          /* wait for VisibilityNotify */
700          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);          do
         if ((int) xkb == BadAlloc || xkb == NULL)  
701          {          {
702                  error("XkbGetKeyboard failed.\n");                  XMaskEvent(display, VisibilityChangeMask, &xevent);
                 exit(0);  
703          }          }
704            while (xevent.type != VisibilityNotify);
705    
706          /* TODO: error texts... make them friendly. */          focused = False;
707          if (XkbSelectEvents          mouse_in_wnd = False;
             (display, xkb->device_spec, XkbAllEventsMask,  
              XkbAllEventsMask) == False)  
         {  
                 error("XkbSelectEvents failed.\n");  
                 exit(0);  
         }  
708    
709          xwin_get_numlock_mask();          /* handle the WM_DELETE_WINDOW protocol */
710            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
711            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
712            XSetWMProtocols(display, wnd, &kill_atom, 1);
713    
714          return True;          return True;
715  }  }
716    
717  void  void
718  xwin_get_numlock_mask()  ui_destroy_window(void)
719  {  {
720          KeyCode numlockcode;          if (IC != NULL)
721          KeyCode *keycode;                  XDestroyIC(IC);
         XModifierKeymap *modmap;  
         int i, j;  
   
         /* Find out if numlock is already defined as a modifier key, and if so where */  
         numlockcode = XKeysymToKeycode(display, 0xFF7F);        /* XF_Num_Lock = 0xFF7F */  
         if (numlockcode)  
         {  
                 modmap = XGetModifierMapping(display);  
                 if (modmap)  
                 {  
                         keycode = modmap->modifiermap;  
                         for (i = 0; i < 8; i++)  
                                 for (j = modmap->max_keypermod; j--;)  
                                 {  
                                         if (*keycode == numlockcode)  
                                         {  
                                                 numlock_modifier_mask =  
                                                         (1 << i);  
                                                 i = 8;  
                                                 break;  
                                         }  
                                         keycode++;  
                                 }  
                         if (!numlock_modifier_mask)  
                         {  
                                 modmap->modifiermap[7 *  
                                                     modmap->max_keypermod] =  
                                         numlockcode;  
                                 if (XSetModifierMapping(display, modmap) ==  
                                     MappingSuccess)  
                                         numlock_modifier_mask = (1 << 7);  
                                 else  
                                         printf("XSetModifierMapping failed!\n");  
                         }  
                         XFreeModifiermap(modmap);  
                 }  
         }  
   
         if (!numlock_modifier_mask)  
                 printf("WARNING: Failed to get a numlock modifier mapping.\n");  
722    
723            XDestroyWindow(display, wnd);
724  }  }
725    
726  void  void
727  ui_destroy_window()  xwin_toggle_fullscreen(void)
728  {  {
729          if (xkb != NULL)          Pixmap contents = 0;
                 XkbFreeKeyboard(xkb, XkbAllControlsMask, True);  
730    
731          if (ownbackstore)          if (!ownbackstore)
732                  XFreePixmap(display, backstore);          {
733                    /* need to save contents of window */
734                    contents = XCreatePixmap(display, wnd, width, height, depth);
735                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
736            }
737    
738          XFreeGC(display, gc);          ui_destroy_window();
739          XDestroyWindow(display, wnd);          fullscreen = !fullscreen;
740          XCloseDisplay(display);          ui_create_window();
741          display = NULL;  
742            XDefineCursor(display, wnd, current_cursor);
743    
744            if (!ownbackstore)
745            {
746                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
747                    XFreePixmap(display, contents);
748            }
749  }  }
750    
751  static void  /* Process all events in Xlib queue
752  xwin_process_events()     Returns 0 after user quit, 1 otherwise */
753    static int
754    xwin_process_events(void)
755  {  {
756          XEvent xevent;          XEvent xevent;
   
757          KeySym keysym;          KeySym keysym;
         uint8 scancode;  
758          uint16 button, flags;          uint16 button, flags;
759          uint32 ev_time;          uint32 ev_time;
760          uint32 tmpmods;          key_translation tr;
761            char str[256];
762            Status status;
763            unsigned int state;
764            Window wdummy;
765            int dummy;
766    
767          while (XCheckMaskEvent(display, ~0, &xevent))          while (XPending(display) > 0)
768          {          {
769                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
770    
771                    if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
772                    {
773                            DEBUG_KBD(("Filtering event\n"));
774                            continue;
775                    }
776    
777                  flags = 0;                  flags = 0;
778    
779                  switch (xevent.type)                  switch (xevent.type)
780                  {                  {
781                          case KeyRelease:                          case ClientMessage:
782                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;                                  /* the window manager told us to quit */
783                                  /* fall through */                                  if ((xevent.xclient.message_type == protocol_atom)
784                                        && (xevent.xclient.data.l[0] == kill_atom))
785                                            /* Quit */
786                                            return 0;
787                                    break;
788    
789                          case KeyPress:                          case KeyPress:
790                                  if (XkbTranslateKeyCode                                  if (IC != NULL)
791                                      (xkb, xevent.xkey.keycode,                                          /* Multi_key compatible version */
792                                       xevent.xkey.state, &tmpmods,                                  {
793                                       &keysym) == False)                                          XmbLookupString(IC,
794                                          break;                                                          (XKeyPressedEvent *) &
795                                  scancode =                                                          xevent, str, sizeof(str), &keysym, &status);
796                                          xkeymap_translate_key(keysym,                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))
797                                                                xevent.xkey.                                          {
798                                                                keycode,                                                  error("XmbLookupString failed with status 0x%x\n",
799                                                                &flags);                                                        status);
800                                                    break;
801                                  if (scancode == 0)                                          }
802                                          break;                                  }
803                                    else
804                                  /* keep track of the modifiers -- needed for stickykeys... */                                  {
805                                  if (xevent.type == KeyPress)                                          /* Plain old XLookupString */
806                                          xwin_mod_press(xevent.xkey.state,                                          DEBUG_KBD(("\nNo input context, using XLookupString\n"));
807                                                         ev_time, scancode);                                          XLookupString((XKeyEvent *) & xevent,
808                                                          str, sizeof(str), &keysym, NULL);
809                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  }
810                                                 flags, scancode, 0);  
811                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
812                                  if (xevent.type == KeyRelease)                                             get_ksname(keysym)));
813                                          xwin_mod_release(xevent.xkey.state,  
814                                                           ev_time, scancode);                                  ev_time = time(NULL);
815                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
816                                            break;
817    
818                                    tr = xkeymap_translate_key(keysym,
819                                                               xevent.xkey.keycode, xevent.xkey.state);
820    
821                                    if (tr.scancode == 0)
822                                            break;
823    
824                                    ensure_remote_modifiers(ev_time, tr);
825    
826                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
827                                    break;
828    
829                            case KeyRelease:
830                                    XLookupString((XKeyEvent *) & xevent, str,
831                                                  sizeof(str), &keysym, NULL);
832    
833                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
834                                               get_ksname(keysym)));
835    
836                                    ev_time = time(NULL);
837                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
838                                            break;
839    
840                                    tr = xkeymap_translate_key(keysym,
841                                                               xevent.xkey.keycode, xevent.xkey.state);
842    
843                                    if (tr.scancode == 0)
844                                            break;
845    
846                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
847                                  break;                                  break;
848    
849                          case ButtonPress:                          case ButtonPress:
# Line 499  xwin_process_events() Line 851  xwin_process_events()
851                                  /* fall through */                                  /* fall through */
852    
853                          case ButtonRelease:                          case ButtonRelease:
854                                  button = xkeymap_translate_button(xevent.                                  button = xkeymap_translate_button(xevent.xbutton.button);
                                                                   xbutton.  
                                                                   button);  
855                                  if (button == 0)                                  if (button == 0)
856                                          break;                                          break;
857    
858                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
859                                                 flags | button,                                  if (xevent.xbutton.y < win_button_size)
860                                                 xevent.xbutton.x,                                  {
861                                                 xevent.xbutton.y);                                          /* Check from right to left: */
862    
863                                            if (xevent.xbutton.x >= width - win_button_size)
864                                            {
865                                                    /* The close button, continue */
866                                                    ;
867                                            }
868                                            else if (xevent.xbutton.x >= width - win_button_size * 2)
869                                            {
870                                                    /* The maximize/restore button. Do not send to
871                                                       server.  It might be a good idea to change the
872                                                       cursor or give some other visible indication
873                                                       that rdesktop inhibited this click */
874                                                    break;
875                                            }
876                                            else if (xevent.xbutton.x >= width - win_button_size * 3)
877                                            {
878                                                    /* The minimize button. Iconify window. */
879                                                    XIconifyWindow(display, wnd,
880                                                                   DefaultScreen(display));
881                                                    break;
882                                            }
883                                            else
884                                            {
885                                                    /* Ignore clicks to the rest of the border. This includes
886                                                       the system menu, but also inhibits double clicks on the
887                                                       border itself. */
888                                                    break;
889                                            }
890                                    }
891    
892                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
893                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
894                                  break;                                  break;
895    
896                          case MotionNotify:                          case MotionNotify:
897                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (fullscreen && !focused)
898                                                 MOUSE_FLAG_MOVE,                                          XSetInputFocus(display, wnd, RevertToPointerRoot,
899                                                 xevent.xmotion.x,                                                         CurrentTime);
900                                                 xevent.xmotion.y);                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
901                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
902                                  break;                                  break;
903    
904                          case EnterNotify:                          case FocusIn:
905                                  XGrabKeyboard(display, wnd, True,                                  if (xevent.xfocus.mode == NotifyGrab)
906                                                GrabModeAsync, GrabModeAsync,                                          break;
907                                                CurrentTime);                                  focused = True;
908                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
909                                                  &dummy, &dummy, &state);
910                                    reset_modifier_keys(state);
911                                    if (grab_keyboard && mouse_in_wnd)
912                                            XGrabKeyboard(display, wnd, True,
913                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
914                                    break;
915    
916                            case FocusOut:
917                                    if (xevent.xfocus.mode == NotifyUngrab)
918                                            break;
919                                    focused = False;
920                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
921                                            XUngrabKeyboard(display, CurrentTime);
922                                    break;
923    
924                                  xwin_mod_update(xevent.xcrossing.state,                          case EnterNotify:
925                                                  ev_time);                                  /* we only register for this event when in fullscreen mode */
926                                    /* or grab_keyboard */
927                                    mouse_in_wnd = True;
928                                    if (fullscreen)
929                                    {
930                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
931                                                           CurrentTime);
932                                            break;
933                                    }
934                                    if (focused)
935                                            XGrabKeyboard(display, wnd, True,
936                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
937                                  break;                                  break;
938    
939                          case LeaveNotify:                          case LeaveNotify:
940                                    /* we only register for this event when grab_keyboard */
941                                    mouse_in_wnd = False;
942                                  XUngrabKeyboard(display, CurrentTime);                                  XUngrabKeyboard(display, CurrentTime);
943                                  break;                                  break;
944    
# Line 538  xwin_process_events() Line 949  xwin_process_events()
949                                            xevent.xexpose.height,                                            xevent.xexpose.height,
950                                            xevent.xexpose.x, xevent.xexpose.y);                                            xevent.xexpose.x, xevent.xexpose.y);
951                                  break;                                  break;
                 }  
         }  
 }  
   
 void  
 xwin_mod_update(uint32 state, uint32 ev_time)  
 {  
         xwin_mod_press(state, ev_time, 0);  
         xwin_mod_release(state, ev_time, 0);  
 }  
   
 void  
 xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode)  
 {  
         switch (scancode)  
         {  
                 case 0x2a:  
                         key_down_state &= ~DShift1Mask;  
                         break;  
                 case 0x36:  
                         key_down_state &= ~DShift2Mask;  
                         break;  
                 case 0x1d:  
                         key_down_state &= ~DControl1Mask;  
                         break;  
                 case 0x9d:  
                         key_down_state &= ~DControl2Mask;  
                         break;  
                 case 0x38:  
                         key_down_state &= ~DMod1Mask;  
                         break;  
                 case 0xb8:  
                         key_down_state &= ~DMod2Mask;  
                         break;  
         }  
   
         if (!(numlock_modifier_mask & state)  
             && (key_down_state & DNumLockMask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);  
                 key_down_state &= ~DNumLockMask;  
         }  
   
         if (!(LockMask & state) && (key_down_state & DLockMask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);  
                 key_down_state &= ~DLockMask;  
   
         }  
   
   
         if (!(ShiftMask & state) && (key_down_state & DShift1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a,  
                                0);  
                 key_down_state &= ~DShift1Mask;  
952    
953          }                          case MappingNotify:
954                                    /* Refresh keyboard mapping if it has changed. This is important for
955          if (!(ControlMask & state) && (key_down_state & DControl1Mask))                                     Xvnc, since it allocates keycodes dynamically */
956          {                                  if (xevent.xmapping.request == MappingKeyboard
957                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d,                                      || xevent.xmapping.request == MappingModifier)
958                                 0);                                          XRefreshKeyboardMapping(&xevent.xmapping);
                 key_down_state &= ~DControl1Mask;  
   
         }  
   
         if (!(Mod1Mask & state) && (key_down_state & DMod1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38,  
                                0);  
                 key_down_state &= ~DMod1Mask;  
   
         }  
   
         if (!(Mod2Mask & state) && (key_down_state & DMod2Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8,  
                                0);  
                 key_down_state &= ~DMod2Mask;  
         }  
 }  
   
   
 void  
 xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode)  
 {  
   
         switch (scancode)  
         {  
                 case 0x2a:  
                         key_down_state |= DShift1Mask;  
                         break;  
                 case 0x36:  
                         key_down_state |= DShift2Mask;  
                         break;  
                 case 0x1d:  
                         key_down_state |= DControl1Mask;  
                         break;  
                 case 0x9d:  
                         key_down_state |= DControl2Mask;  
                         break;  
                 case 0x3a:  
                         key_down_state ^= DLockMask;  
                         break;  
                 case 0x45:  
                         key_down_state ^= DNumLockMask;  
                         break;  
                 case 0x38:  
                         key_down_state |= DMod1Mask;  
                         break;  
                 case 0xb8:  
                         key_down_state |= DMod2Mask;  
                         break;  
         }  
   
         if ((numlock_modifier_mask && state)  
             && !(key_down_state & DNumLockMask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);  
                 key_down_state |= DNumLockMask;  
         }  
   
         if ((LockMask & state) && !(key_down_state & DLockMask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);  
                 key_down_state |= DLockMask;  
959    
960          }                                  if (xevent.xmapping.request == MappingModifier)
961                                    {
962                                            XFreeModifiermap(mod_map);
963          if ((ShiftMask & state)                                          mod_map = XGetModifierMapping(display);
964              && !((key_down_state & DShift1Mask)                                  }
965                   || (key_down_state & DShift2Mask)))                                  break;
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,  
                                0x2a, 0);  
                 key_down_state |= DShift1Mask;  
   
         }  
   
         if ((ControlMask & state)  
             && !((key_down_state & DControl1Mask)  
                  || (key_down_state & DControl2Mask)))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,  
                                0x1d, 0);  
                 key_down_state |= DControl1Mask;  
   
         }  
   
         if ((Mod1Mask & state) && !(key_down_state & DMod1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,  
                                0x38, 0);  
                 key_down_state |= DMod1Mask;  
   
         }  
   
         if ((Mod2Mask & state) && !(key_down_state & DMod2Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,  
                                0xb8, 0);  
                 key_down_state |= DMod2Mask;  
966    
967                    }
968          }          }
969            /* Keep going */
970            return 1;
971  }  }
972    
973  void  /* Returns 0 after user quit, 1 otherwise */
974    int
975  ui_select(int rdp_socket)  ui_select(int rdp_socket)
976  {  {
977          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
# Line 724  ui_select(int rdp_socket) Line 981  ui_select(int rdp_socket)
981    
982          while (True)          while (True)
983          {          {
984                    /* Process any events already waiting */
985                    if (!xwin_process_events())
986                            /* User quit */
987                            return 0;
988    
989                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
990                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
991                  if (display != NULL)                  FD_SET(x_socket, &rfds);
                 {  
                         FD_SET(x_socket, &rfds);  
                         XFlush(display);  
                 }  
992    
993                  switch (select(n, &rfds, NULL, NULL, NULL))                  switch (select(n, &rfds, NULL, NULL, NULL))
994                  {                  {
# Line 741  ui_select(int rdp_socket) Line 999  ui_select(int rdp_socket)
999                                  continue;                                  continue;
1000                  }                  }
1001    
                 if (FD_ISSET(x_socket, &rfds))  
                         xwin_process_events();  
   
1002                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1003                          return;                          return 1;
1004          }          }
1005  }  }
1006    
# Line 764  ui_create_bitmap(int width, int height, Line 1019  ui_create_bitmap(int width, int height,
1019    
1020          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1021          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
1022          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1023                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1024    
1025          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1026    
# Line 776  ui_create_bitmap(int width, int height, Line 1031  ui_create_bitmap(int width, int height,
1031  }  }
1032    
1033  void  void
1034  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 int width, int height, uint8 * data)  
1035  {  {
1036          XImage *image;          XImage *image;
1037          uint8 *tdata;          uint8 *tdata;
   
1038          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1039          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1040                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1041    
1042          if (ownbackstore)          if (ownbackstore)
1043          {          {
# Line 820  ui_create_glyph(int width, int height, u Line 1073  ui_create_glyph(int width, int height, u
1073          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
1074          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
1075    
1076          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1077                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1078          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1079          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1080          XInitImage(image);          XInitImage(image);
# Line 840  ui_destroy_glyph(HGLYPH glyph) Line 1093  ui_destroy_glyph(HGLYPH glyph)
1093  }  }
1094    
1095  HCURSOR  HCURSOR
1096  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1097                   int height, uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
1098  {  {
1099          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1100          XColor bg, fg;          XColor bg, fg;
# Line 899  ui_create_cursor(unsigned int x, unsigne Line 1152  ui_create_cursor(unsigned int x, unsigne
1152          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1153          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1154    
1155          xcursor = XCreatePixmapCursor(display, (Pixmap) cursorglyph,          xcursor =
1156                                        (Pixmap) maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1157                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1158    
1159          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1160          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
# Line 912  ui_create_cursor(unsigned int x, unsigne Line 1166  ui_create_cursor(unsigned int x, unsigne
1166  void  void
1167  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1168  {  {
1169          XDefineCursor(display, wnd, (Cursor) cursor);          current_cursor = (Cursor) cursor;
1170            XDefineCursor(display, wnd, current_cursor);
1171  }  }
1172    
1173  void  void
# Line 927  ui_destroy_cursor(HCURSOR cursor) Line 1182  ui_destroy_cursor(HCURSOR cursor)
1182                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1183                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1184    
1185    
1186  HCOLOURMAP  HCOLOURMAP
1187  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
1188  {  {
1189          COLOURENTRY *entry;          COLOURENTRY *entry;
1190          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1191            if (!owncolmap)
1192            {
1193                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1194                    XColor xentry;
1195                    XColor xc_cache[256];
1196                    uint32 colour;
1197                    int colLookup = 256;
1198                    for (i = 0; i < ncolours; i++)
1199                    {
1200                            entry = &colours->colours[i];
1201                            MAKE_XCOLOR(&xentry, entry);
1202    
1203                            if (XAllocColor(display, xcolmap, &xentry) == 0)
1204                            {
1205                                    /* Allocation failed, find closest match. */
1206                                    int j = 256;
1207                                    int nMinDist = 3 * 256 * 256;
1208                                    long nDist = nMinDist;
1209    
1210          if (owncolmap)                                  /* only get the colors once */
1211                                    while (colLookup--)
1212                                    {
1213                                            xc_cache[colLookup].pixel = colLookup;
1214                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1215                                                    xc_cache[colLookup].blue = 0;
1216                                            xc_cache[colLookup].flags = 0;
1217                                            XQueryColor(display,
1218                                                        DefaultColormap(display,
1219                                                                        DefaultScreen(display)),
1220                                                        &xc_cache[colLookup]);
1221                                    }
1222                                    colLookup = 0;
1223    
1224                                    /* approximate the pixel */
1225                                    while (j--)
1226                                    {
1227                                            if (xc_cache[j].flags)
1228                                            {
1229                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1230                                                             (long) (xentry.red >> 8)) *
1231                                                            ((long) (xc_cache[j].red >> 8) -
1232                                                             (long) (xentry.red >> 8)) +
1233                                                            ((long) (xc_cache[j].green >> 8) -
1234                                                             (long) (xentry.green >> 8)) *
1235                                                            ((long) (xc_cache[j].green >> 8) -
1236                                                             (long) (xentry.green >> 8)) +
1237                                                            ((long) (xc_cache[j].blue >> 8) -
1238                                                             (long) (xentry.blue >> 8)) *
1239                                                            ((long) (xc_cache[j].blue >> 8) -
1240                                                             (long) (xentry.blue >> 8));
1241                                            }
1242                                            if (nDist < nMinDist)
1243                                            {
1244                                                    nMinDist = nDist;
1245                                                    xentry.pixel = j;
1246                                            }
1247                                    }
1248                            }
1249                            colour = xentry.pixel;
1250    
1251                            /* update our cache */
1252                            if (xentry.pixel < 256)
1253                            {
1254                                    xc_cache[xentry.pixel].red = xentry.red;
1255                                    xc_cache[xentry.pixel].green = xentry.green;
1256                                    xc_cache[xentry.pixel].blue = xentry.blue;
1257    
1258                            }
1259    
1260    
1261                            /* byte swap here to make translate_image faster */
1262                            map[i] = translate_colour(colour);
1263                    }
1264                    return map;
1265            }
1266            else
1267          {          {
1268                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1269                  Colormap map;                  Colormap map;
# Line 953  ui_create_colourmap(COLOURMAP * colours) Line 1283  ui_create_colourmap(COLOURMAP * colours)
1283                  xfree(xcolours);                  xfree(xcolours);
1284                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
1285          }          }
         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;  
         }  
1286  }  }
1287    
1288  void  void
1289  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1290  {  {
1291          if (owncolmap)          if (!owncolmap)
                 XFreeColormap(display, (Colormap) map);  
         else  
1292                  xfree(map);                  xfree(map);
1293            else
1294                    XFreeColormap(display, (Colormap) map);
1295  }  }
1296    
1297  void  void
1298  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1299  {  {
1300          if (owncolmap)          if (!owncolmap)
                 XSetWindowColormap(display, wnd, (Colormap) map);  
         else  
1301                  colmap = map;                  colmap = map;
1302            else
1303                    XSetWindowColormap(display, wnd, (Colormap) map);
1304  }  }
1305    
1306  void  void
# Line 1008  ui_set_clip(int x, int y, int cx, int cy Line 1316  ui_set_clip(int x, int y, int cx, int cy
1316  }  }
1317    
1318  void  void
1319  ui_reset_clip()  ui_reset_clip(void)
1320  {  {
1321          XRectangle rect;          XRectangle rect;
1322    
# Line 1020  ui_reset_clip() Line 1328  ui_reset_clip()
1328  }  }
1329    
1330  void  void
1331  ui_bell()  ui_bell(void)
1332  {  {
1333          XBell(display, 0);          XBell(display, 0);
1334  }  }
# Line 1060  ui_patblt(uint8 opcode, Line 1368  ui_patblt(uint8 opcode,
1368                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
1369                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
1370                          XSetStipple(display, gc, fill);                          XSetStipple(display, gc, fill);
1371                          XSetTSOrigin(display, gc, brush->xorigin,                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
                                      brush->yorigin);  
1372    
1373                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1374    
1375                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1376                            XSetTSOrigin(display, gc, 0, 0);
1377                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1378                          break;                          break;
1379    
# Line 1084  ui_screenblt(uint8 opcode, Line 1392  ui_screenblt(uint8 opcode,
1392          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1393          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1394          if (ownbackstore)          if (ownbackstore)
1395                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1396          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1397  }  }
1398    
# Line 1097  ui_memblt(uint8 opcode, Line 1404  ui_memblt(uint8 opcode,
1404          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1405          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1406          if (ownbackstore)          if (ownbackstore)
1407                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1408          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1409  }  }
1410    
# Line 1115  ui_triblt(uint8 opcode, Line 1421  ui_triblt(uint8 opcode,
1421          {          {
1422                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1423                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1424                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1425                          break;                          break;
1426    
1427                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1428                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1429                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1430                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1431                          break;                          break;
1432    
1433                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1434                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1435                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1436                          break;                          break;
1437    
1438                  default:                  default:
# Line 1161  ui_rect( Line 1463  ui_rect(
1463          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1464  }  }
1465    
1466    /* warning, this function only draws on wnd or backstore, not both */
1467  void  void
1468  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1469                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1470                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1471                int fgcolour)                int bgcolour, int fgcolour)
1472  {  {
1473          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1474          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1475    
1476          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(display, gc,
1477                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1478          XSetStipple(display, gc, (Pixmap) glyph);          XSetStipple(display, gc, (Pixmap) glyph);
1479          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(display, gc, x, y);
1480    
1481          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1482    
1483          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1484  }  }
# Line 1189  ui_draw_glyph(int mixmode, Line 1492  ui_draw_glyph(int mixmode,
1492        if ((xyoffset & 0x80))\        if ((xyoffset & 0x80))\
1493          {\          {\
1494            if (flags & TEXT2_VERTICAL) \            if (flags & TEXT2_VERTICAL) \
1495              y += ttext[++idx] | (ttext[++idx] << 8);\              y += ttext[idx+1] | (ttext[idx+2] << 8);\
1496            else\            else\
1497              x += ttext[++idx] | (ttext[++idx] << 8);\              x += ttext[idx+1] | (ttext[idx+2] << 8);\
1498              idx += 2;\
1499          }\          }\
1500        else\        else\
1501          {\          {\
# Line 1203  ui_draw_glyph(int mixmode, Line 1507  ui_draw_glyph(int mixmode,
1507      }\      }\
1508    if (glyph != NULL)\    if (glyph != NULL)\
1509      {\      {\
1510        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        ui_draw_glyph (mixmode, x + glyph->offset,\
1511                       y + (short) glyph->baseline,\                       y + glyph->baseline,\
1512                       glyph->width, glyph->height,\                       glyph->width, glyph->height,\
1513                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1514        if (flags & TEXT2_IMPLICIT_X)\        if (flags & TEXT2_IMPLICIT_X)\
# Line 1214  ui_draw_glyph(int mixmode, Line 1518  ui_draw_glyph(int mixmode,
1518    
1519  void  void
1520  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1521               int clipx, int clipy, int clipcx, int clipcy, int boxx,               int clipx, int clipy, int clipcx, int clipcy,
1522               int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1523               int fgcolour, uint8 * text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1524  {  {
1525          FONTGLYPH *glyph;          FONTGLYPH *glyph;
# Line 1226  ui_draw_text(uint8 font, uint8 flags, in Line 1530  ui_draw_text(uint8 font, uint8 flags, in
1530    
1531          if (boxcx > 1)          if (boxcx > 1)
1532          {          {
1533                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1534          }          }
1535          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1536          {          {
1537                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1538          }          }
1539    
1540          /* Paint text, character by character */          /* Paint text, character by character */
# Line 1240  ui_draw_text(uint8 font, uint8 flags, in Line 1544  ui_draw_text(uint8 font, uint8 flags, in
1544                  {                  {
1545                          case 0xff:                          case 0xff:
1546                                  if (i + 2 < length)                                  if (i + 2 < length)
1547                                          cache_put_text(text[i + 1], text,                                          cache_put_text(text[i + 1], text, text[i + 2]);
                                                        text[i + 2]);  
1548                                  else                                  else
1549                                  {                                  {
1550                                          error("this shouldn't be happening\n");                                          error("this shouldn't be happening\n");
1551                                          break;                                          exit(1);
1552                                  }                                  }
1553                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
1554                                  length -= i + 3;                                  length -= i + 3;
# Line 1258  ui_draw_text(uint8 font, uint8 flags, in Line 1561  ui_draw_text(uint8 font, uint8 flags, in
1561                                  if (entry != NULL)                                  if (entry != NULL)
1562                                  {                                  {
1563                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] ==
1564                                               0)                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
                                             && (!(flags & TEXT2_IMPLICIT_X)))  
1565                                          {                                          {
1566                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
1567                                                          y += text[i + 2];                                                          y += text[i + 2];
1568                                                  else                                                  else
1569                                                          x += text[i + 2];                                                          x += text[i + 2];
1570                                          }                                          }
                                         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;  
1571                                          for (j = 0; j < entry->size; j++)                                          for (j = 0; j < entry->size; j++)
1572                                                  DO_GLYPH(((uint8 *) (entry->                                                  DO_GLYPH(((uint8 *) (entry->data)), j);
                                                                      data)),  
                                                          j);  
1573                                  }                                  }
1574                                    if (i + 2 < length)
1575                                            i += 3;
1576                                    else
1577                                            i += 2;
1578                                    length -= i;
1579                                    /* this will move pointer from start to first character after FE command */
1580                                    text = &(text[i]);
1581                                    i = 0;
1582                                  break;                                  break;
1583    
1584                          default:                          default:
# Line 1287  ui_draw_text(uint8 font, uint8 flags, in Line 1587  ui_draw_text(uint8 font, uint8 flags, in
1587                                  break;                                  break;
1588                  }                  }
1589          }          }
1590            if (ownbackstore)
1591            {
1592                    if (boxcx > 1)
1593                            XCopyArea(display, backstore, wnd, gc, boxx,
1594                                      boxy, boxcx, boxcy, boxx, boxy);
1595                    else
1596                            XCopyArea(display, backstore, wnd, gc, clipx,
1597                                      clipy, clipcx, clipcy, clipx, clipy);
1598            }
1599  }  }
1600    
1601  void  void
# Line 1299  ui_desktop_save(uint32 offset, int x, in Line 1606  ui_desktop_save(uint32 offset, int x, in
1606    
1607          if (ownbackstore)          if (ownbackstore)
1608          {          {
1609                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1610          }          }
1611          else          else
1612          {          {
1613                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(display, wnd, cx, cy, depth);
1614                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1615                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1616                  XFreePixmap(display, pix);                  XFreePixmap(display, pix);
1617          }          }
1618    
1619          offset *= bpp / 8;          offset *= bpp / 8;
1620          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
                           bpp / 8, (uint8 *) image->data);  
1621    
1622          XDestroyImage(image);          XDestroyImage(image);
1623  }  }
# Line 1329  ui_desktop_restore(uint32 offset, int x, Line 1633  ui_desktop_restore(uint32 offset, int x,
1633          if (data == NULL)          if (data == NULL)
1634                  return;                  return;
1635    
1636          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1637                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
                              cx * bpp / 8);  
1638    
1639          if (ownbackstore)          if (ownbackstore)
1640          {          {

Legend:
Removed from v.64  
changed lines
  Added in v.332

  ViewVC Help
Powered by ViewVC 1.1.26