/[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 38 by matthewc, Thu Apr 4 12:04:33 2002 UTC revision 342 by astrand, Fri Mar 14 12:00:17 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
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 24  Line 24 
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  static Display *display;  Display *display;
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 47  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    /* Moving in single app mode */
63    static BOOL moving_wnd;
64    static int move_x_offset = 0;
65    static int move_y_offset = 0;
66    
67    /* MWM decorations */
68    #define MWM_HINTS_DECORATIONS   (1L << 1)
69    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
70    typedef struct
71    {
72            uint32 flags;
73            uint32 functions;
74            uint32 decorations;
75            sint32 inputMode;
76            uint32 status;
77    }
78    PropMotifWmHints;
79    
80    typedef struct
81    {
82            uint32 red;
83            uint32 green;
84            uint32 blue;
85    }
86    PixelColour;
87    
88  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
89  { \  { \
90          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(display, wnd, gc, x, y, cx, cy); \
# Line 54  static Pixmap backstore; Line 92  static Pixmap backstore;
92                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \
93  }  }
94    
95    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
96    { \
97            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
98    }
99    
100  /* colour maps */  /* colour maps */
101  static BOOL owncolmap;  BOOL owncolmap = False;
102  static Colormap xcolmap;  static Colormap xcolmap;
 static uint32 white;  
103  static uint32 *colmap;  static uint32 *colmap;
104    
105  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
106  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
107  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
108    
# Line 87  static int rop2_map[] = { Line 129  static int rop2_map[] = {
129  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
130    
131  static void  static void
132  translate8(uint8 *data, uint8 *out, uint8 *end)  mwm_hide_decorations(void)
133    {
134            PropMotifWmHints motif_hints;
135            Atom hintsatom;
136    
137            /* setup the property */
138            motif_hints.flags = MWM_HINTS_DECORATIONS;
139            motif_hints.decorations = 0;
140    
141            /* get the atom for the property */
142            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
143            if (!hintsatom)
144            {
145                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
146                    return;
147            }
148    
149            XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
150                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
151    }
152    
153    static PixelColour
154    split_colour15(uint32 colour)
155    {
156            PixelColour rv;
157            rv.red = (colour & 0x7c00) >> 10;
158            rv.red = (rv.red * 0xff) / 0x1f;
159            rv.green = (colour & 0x03e0) >> 5;
160            rv.green = (rv.green * 0xff) / 0x1f;
161            rv.blue = (colour & 0x1f);
162            rv.blue = (rv.blue * 0xff) / 0x1f;
163            return rv;
164    }
165    
166    static PixelColour
167    split_colour16(uint32 colour)
168    {
169            PixelColour rv;
170            rv.red = (colour & 0xf800) >> 11;
171            rv.red = (rv.red * 0xff) / 0x1f;
172            rv.green = (colour & 0x07e0) >> 5;
173            rv.green = (rv.green * 0xff) / 0x3f;
174            rv.blue = (colour & 0x001f);
175            rv.blue = (rv.blue * 0xff) / 0x1f;
176            return rv;
177    }
178    
179    static PixelColour
180    split_colour24(uint32 colour)
181    {
182            PixelColour rv;
183            rv.blue = (colour & 0xff0000) >> 16;
184            rv.green = (colour & 0xff00) >> 8;
185            rv.red = (colour & 0xff);
186            return rv;
187    }
188    
189    static uint32
190    make_colour16(PixelColour pc)
191    {
192            pc.red = (pc.red * 0x1f) / 0xff;
193            pc.green = (pc.green * 0x3f) / 0xff;
194            pc.blue = (pc.blue * 0x1f) / 0xff;
195            return (pc.red << 11) | (pc.green << 5) | pc.blue;
196    }
197    
198    static uint32
199    make_colour24(PixelColour pc)
200    {
201            return (pc.red << 16) | (pc.green << 8) | pc.blue;
202    }
203    
204    static uint32
205    make_colour32(PixelColour pc)
206    {
207            return (pc.red << 16) | (pc.green << 8) | pc.blue;
208    }
209    
210    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
211    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
212    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
213                            x = (x << 16) | (x >> 16); }
214    
215    static uint32
216    translate_colour(uint32 colour)
217    {
218            switch (server_bpp)
219            {
220                    case 15:
221                            switch (bpp)
222                            {
223                                    case 16:
224                                            colour = make_colour16(split_colour15(colour));
225                                            break;
226                                    case 24:
227                                            colour = make_colour24(split_colour15(colour));
228                                            break;
229                                    case 32:
230                                            colour = make_colour32(split_colour15(colour));
231                                            break;
232                            }
233                            break;
234                    case 16:
235                            switch (bpp)
236                            {
237                                    case 16:
238                                            break;
239                                    case 24:
240                                            colour = make_colour24(split_colour16(colour));
241                                            break;
242                                    case 32:
243                                            colour = make_colour32(split_colour16(colour));
244                                            break;
245                            }
246                            break;
247                    case 24:
248                            switch (bpp)
249                            {
250                                    case 16:
251                                            colour = make_colour16(split_colour24(colour));
252                                            break;
253                                    case 24:
254                                            break;
255                                    case 32:
256                                            colour = make_colour32(split_colour24(colour));
257                                            break;
258                            }
259                            break;
260            }
261            switch (bpp)
262            {
263                    case 16:
264                            if (host_be != xserver_be)
265                                    BSWAP16(colour);
266                            break;
267    
268                    case 24:
269                            if (xserver_be)
270                                    BSWAP24(colour);
271                            break;
272    
273                    case 32:
274                            if (host_be != xserver_be)
275                                    BSWAP32(colour);
276                            break;
277            }
278    
279            return colour;
280    }
281    
282    static void
283    translate8to8(uint8 * data, uint8 * out, uint8 * end)
284  {  {
285          while (out < end)          while (out < end)
286                  *(out++) = (uint8)colmap[*(data++)];                  *(out++) = (uint8) colmap[*(data++)];
287  }  }
288    
289  static void  static void
290  translate16(uint8 *data, uint16 *out, uint16 *end)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
291  {  {
292          while (out < end)          while (out < end)
293                  *(out++) = (uint16)colmap[*(data++)];                  *(out++) = (uint16) colmap[*(data++)];
294  }  }
295    
296  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
297  static void  static void
298  translate24(uint8 *data, uint8 *out, uint8 *end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
299  {  {
300          uint32 value;          uint32 value;
301    
# Line 116  translate24(uint8 *data, uint8 *out, uin Line 309  translate24(uint8 *data, uint8 *out, uin
309  }  }
310    
311  static void  static void
312  translate32(uint8 *data, uint32 *out, uint32 *end)  translate8to32(uint8 * data, uint32 * out, uint32 * end)
313  {  {
314          while (out < end)          while (out < end)
315                  *(out++) = colmap[*(data++)];                  *(out++) = colmap[*(data++)];
316  }  }
317    
318    /* todo the remaining translate function might need some big endian check ?? */
319    
320    static void
321    translate15to16(uint16 * data, uint16 * out, uint16 * end)
322    {
323            while (out < end)
324                    *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
325    }
326    
327    static void
328    translate15to24(uint16 * data, uint8 * out, uint8 * end)
329    {
330            uint32 value;
331    
332            while (out < end)
333            {
334                    value = make_colour24(split_colour15(*(data++)));
335                    *(out++) = value;
336                    *(out++) = value >> 8;
337                    *(out++) = value >> 16;
338            }
339    }
340    
341    static void
342    translate15to32(uint16 * data, uint32 * out, uint32 * end)
343    {
344            while (out < end)
345                    *(out++) = make_colour32(split_colour15(*(data++)));
346    }
347    
348    static void
349    translate16to16(uint16 * data, uint16 * out, uint16 * end)
350    {
351            while (out < end)
352                    *(out++) = (uint16) (*(data++));
353    }
354    
355    
356    static void
357    translate16to24(uint16 * data, uint8 * out, uint8 * end)
358    {
359            uint32 value;
360    
361            while (out < end)
362            {
363                    value = make_colour24(split_colour16(*(data++)));
364                    *(out++) = value;
365                    *(out++) = value >> 8;
366                    *(out++) = value >> 16;
367            }
368    }
369    
370    static void
371    translate16to32(uint16 * data, uint32 * out, uint32 * end)
372    {
373            while (out < end)
374                    *(out++) = make_colour32(split_colour16(*(data++)));
375    }
376    
377    static void
378    translate24to16(uint8 * data, uint16 * out, uint16 * end)
379    {
380            uint32 pixel = 0;
381            while (out < end)
382            {
383                    pixel = *(data++) << 16;
384                    pixel |= *(data++) << 8;
385                    pixel |= *(data++);
386                    *(out++) = (uint16) make_colour16(split_colour24(pixel));
387            }
388    }
389    
390    static void
391    translate24to24(uint8 * data, uint8 * out, uint8 * end)
392    {
393            while (out < end)
394            {
395                    *(out++) = (*(data++));
396            }
397    }
398    
399    static void
400    translate24to32(uint8 * data, uint32 * out, uint32 * end)
401    {
402            uint32 pixel = 0;
403            while (out < end)
404            {
405                    memcpy(&pixel, data, 3);
406                    data += 3;
407                    *(out++) = pixel;
408            }
409    }
410    
411  static uint8 *  static uint8 *
412  translate_image(int width, int height, uint8 *data)  translate_image(int width, int height, uint8 * data)
413  {  {
414          int size = width * height * bpp/8;          int size = width * height * bpp / 8;
415          uint8 *out = xmalloc(size);          uint8 *out = xmalloc(size);
416          uint8 *end = out + size;          uint8 *end = out + size;
417    
418          switch (bpp)          switch (server_bpp)
419          {          {
420                  case 8:                  case 24:
421                          translate8(data, out, end);                          switch (bpp)
422                            {
423                                    case 32:
424                                            translate24to32(data, (uint32 *) out, (uint32 *) end);
425                                            break;
426                                    case 24:
427                                            translate24to24(data, out, end);
428                                            break;
429                                    case 16:
430                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
431                                            break;
432                            }
433                          break;                          break;
   
434                  case 16:                  case 16:
435                          translate16(data, (uint16 *)out, (uint16 *)end);                          switch (bpp)
436                            {
437                                    case 32:
438                                            translate16to32((uint16 *) data, (uint32 *) out,
439                                                            (uint32 *) end);
440                                            break;
441                                    case 24:
442                                            translate16to24((uint16 *) data, out, end);
443                                            break;
444                                    case 16:
445                                            translate16to16((uint16 *) data, (uint16 *) out,
446                                                            (uint16 *) end);
447                                            break;
448                            }
449                          break;                          break;
450                    case 15:
451                  case 24:                          switch (bpp)
452                          translate24(data, out, end);                          {
453                                    case 32:
454                                            translate15to32((uint16 *) data, (uint32 *) out,
455                                                            (uint32 *) end);
456                                            break;
457                                    case 24:
458                                            translate15to24((uint16 *) data, out, end);
459                                            break;
460                                    case 16:
461                                            translate15to16((uint16 *) data, (uint16 *) out,
462                                                            (uint16 *) end);
463                                            break;
464                            }
465                          break;                          break;
466                    case 8:
467                  case 32:                          switch (bpp)
468                          translate32(data, (uint32 *)out, (uint32 *)end);                          {
469                                    case 8:
470                                            translate8to8(data, out, end);
471                                            break;
472                                    case 16:
473                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
474                                            break;
475                                    case 24:
476                                            translate8to24(data, out, end);
477                                            break;
478                                    case 32:
479                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
480                                            break;
481                            }
482                          break;                          break;
483          }          }
   
484          return out;          return out;
485  }  }
486    
487  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  BOOL
488  #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)  
489  {  {
490          switch (bpp)          int modifierpos, key, keysymMask = 0;
491          {          int offset;
                 case 16:  
                         if (host_be != xserver_be)  
                                 BSWAP16(colour);  
                         break;  
492    
493                  case 24:          KeyCode keycode = XKeysymToKeycode(display, keysym);
                         if (xserver_be)  
                                 BSWAP24(colour);  
                         break;  
494    
495                  case 32:          if (keycode == NoSymbol)
496                          if (host_be != xserver_be)                  return False;
497                                  BSWAP32(colour);  
498                          break;          for (modifierpos = 0; modifierpos < 8; modifierpos++)
499            {
500                    offset = mod_map->max_keypermod * modifierpos;
501    
502                    for (key = 0; key < mod_map->max_keypermod; key++)
503                    {
504                            if (mod_map->modifiermap[offset + key] == keycode)
505                                    keysymMask |= 1 << modifierpos;
506                    }
507          }          }
508    
509          return colour;          return (state & keysymMask) ? True : False;
510  }  }
511    
512  BOOL  BOOL
513  ui_create_window(char *title)  ui_init(void)
514  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
515          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
         Screen *screen;  
516          uint16 test;          uint16 test;
517          int i;          int i;
518    
519          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
520          if (display == NULL)          if (display == NULL)
521          {          {
522                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
523                  return False;                  return False;
524          }          }
525    
# Line 211  ui_create_window(char *title) Line 535  ui_create_window(char *title)
535                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
536                  while (i--)                  while (i--)
537                  {                  {
538                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
539                          {                          {
540                                  bpp = pfm[i].bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
541                          }                          }
# Line 227  ui_create_window(char *title) Line 550  ui_create_window(char *title)
550                  return False;                  return False;
551          }          }
552    
553          if (depth <= 8)          if (owncolmap != True)
554                  owncolmap = True;          {
         else  
555                  xcolmap = DefaultColormapOfScreen(screen);                  xcolmap = DefaultColormapOfScreen(screen);
556                    if (depth <= 8)
557                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
558            }
559    
560            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
561    
562            if (DoesBackingStore(screen) != Always)
563                    ownbackstore = True;
564    
565          test = 1;          test = 1;
566          host_be = !(BOOL)(*(uint8 *)(&test));          host_be = !(BOOL) (*(uint8 *) (&test));
567          xserver_be = (ImageByteOrder(display) == MSBFirst);          xserver_be = (ImageByteOrder(display) == MSBFirst);
568    
569          white = WhitePixelOfScreen(screen);          if ((width == 0) || (height == 0))
570          attribs.background_pixel = BlackPixelOfScreen(screen);          {
571          attribs.backing_store = DoesBackingStore(screen);                  /* Fetch geometry from _NET_WORKAREA */
572                    uint32 x, y, cx, cy;
573    
574          if (attribs.backing_store == NotUseful)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
575                  ownbackstore = True;                  {
576                            width = cx;
577                            height = cy;
578                    }
579                    else
580                    {
581                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
582                            width = 800;
583                            height = 600;
584                    }
585            }
586    
587          if (fullscreen)          if (fullscreen)
588          {          {
                 attribs.override_redirect = True;  
589                  width = WidthOfScreen(screen);                  width = WidthOfScreen(screen);
590                  height = HeightOfScreen(screen);                  height = HeightOfScreen(screen);
591          }          }
592          else  
593            /* make sure width is a multiple of 4 */
594            width = (width + 3) & ~3;
595    
596            if (ownbackstore)
597          {          {
598                  attribs.override_redirect = False;                  backstore =
599                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
600    
601                    /* clear to prevent rubbish being exposed at startup */
602                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
603                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
604          }          }
605    
606          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          mod_map = XGetModifierMapping(display);
607    
608          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          if (enable_compose)
609                              0, 0, width, height, 0, CopyFromParent,                  IM = XOpenIM(display, NULL, NULL, NULL);
610                              InputOutput, CopyFromParent,  
611                              CWBackingStore | CWBackPixel | CWOverrideRedirect,          xkeymap_init();
612                              &attribs);  
613            /* todo take this out when high colour is done */
614            printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
615    
616            return True;
617    }
618    
619    void
620    ui_deinit(void)
621    {
622            if (IM != NULL)
623                    XCloseIM(IM);
624    
625            XFreeModifiermap(mod_map);
626    
627            if (ownbackstore)
628                    XFreePixmap(display, backstore);
629    
630            XFreeGC(display, gc);
631            XCloseDisplay(display);
632            display = NULL;
633    }
634    
635    BOOL
636    ui_create_window(void)
637    {
638            XSetWindowAttributes attribs;
639            XClassHint *classhints;
640            XSizeHints *sizehints;
641            int wndwidth, wndheight;
642            long input_mask, ic_input_mask;
643            XEvent xevent;
644    
645            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
646            wndheight = fullscreen ? HeightOfScreen(screen) : height;
647    
648            attribs.background_pixel = BlackPixelOfScreen(screen);
649            attribs.backing_store = ownbackstore ? NotUseful : Always;
650            attribs.override_redirect = fullscreen;
651    
652            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
653                                0, CopyFromParent, InputOutput, CopyFromParent,
654                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
655    
656          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
657    
658            if (hide_decorations)
659                    mwm_hide_decorations();
660    
661          classhints = XAllocClassHint();          classhints = XAllocClassHint();
662          if (classhints != NULL)          if (classhints != NULL)
663          {          {
# Line 282  ui_create_window(char *title) Line 676  ui_create_window(char *title)
676                  XFree(sizehints);                  XFree(sizehints);
677          }          }
678    
679          xkeymap_init(display);          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
680                    VisibilityChangeMask | FocusChangeMask;
         input_mask = KeyPressMask | KeyReleaseMask  
                         | ButtonPressMask | ButtonReleaseMask  
                         | EnterWindowMask | LeaveWindowMask;  
681    
682          if (sendmotion)          if (sendmotion)
683                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
   
684          if (ownbackstore)          if (ownbackstore)
685                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
686            if (fullscreen || grab_keyboard)
687                    input_mask |= EnterWindowMask;
688            if (grab_keyboard)
689                    input_mask |= LeaveWindowMask;
690    
691            if (IM != NULL)
692            {
693                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
694                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
695    
696                    if ((IC != NULL)
697                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
698                            input_mask |= ic_input_mask;
699            }
700    
701          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
702          gc = XCreateGC(display, wnd, 0, NULL);          XMapWindow(display, wnd);
703    
704          if (ownbackstore)          /* wait for VisibilityNotify */
705                  backstore = XCreatePixmap(display, wnd, width, height, depth);          do
706            {
707                    XMaskEvent(display, VisibilityChangeMask, &xevent);
708            }
709            while (xevent.type != VisibilityNotify);
710    
711            focused = False;
712            mouse_in_wnd = False;
713    
714            /* handle the WM_DELETE_WINDOW protocol */
715            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
716            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
717            XSetWMProtocols(display, wnd, &kill_atom, 1);
718    
         XMapWindow(display, wnd);  
719          return True;          return True;
720  }  }
721    
722  void  void
723  ui_destroy_window()  ui_destroy_window(void)
724  {  {
725          if (ownbackstore)          if (IC != NULL)
726                  XFreePixmap(display, backstore);                  XDestroyIC(IC);
727    
         XFreeGC(display, gc);  
728          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
         XCloseDisplay(display);  
         display = NULL;  
729  }  }
730    
731  static void  void
732  xwin_process_events()  xwin_toggle_fullscreen(void)
733    {
734            Pixmap contents = 0;
735    
736            if (!ownbackstore)
737            {
738                    /* need to save contents of window */
739                    contents = XCreatePixmap(display, wnd, width, height, depth);
740                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
741            }
742    
743            ui_destroy_window();
744            fullscreen = !fullscreen;
745            ui_create_window();
746    
747            XDefineCursor(display, wnd, current_cursor);
748    
749            if (!ownbackstore)
750            {
751                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
752                    XFreePixmap(display, contents);
753            }
754    }
755    
756    /* Process all events in Xlib queue
757       Returns 0 after user quit, 1 otherwise */
758    static int
759    xwin_process_events(void)
760  {  {
761          XEvent event;          XEvent xevent;
762          KeySym keysym;          KeySym keysym;
763          uint8 scancode;          uint16 button, flags;
         uint16 button;  
764          uint32 ev_time;          uint32 ev_time;
765            key_translation tr;
766            char str[256];
767            Status status;
768            unsigned int state;
769            Window wdummy;
770            int dummy;
771    
772          if (display == NULL)          while (XPending(display) > 0)
                 return;  
   
         while (XCheckWindowEvent(display, wnd, ~0, &event))  
773          {          {
774                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
775    
776                  switch (event.type)                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
777                  {                  {
778                            DEBUG_KBD(("Filtering event\n"));
779                            continue;
780                    }
781    
782                    flags = 0;
783    
784                    switch (xevent.type)
785                    {
786                            case ClientMessage:
787                                    /* the window manager told us to quit */
788                                    if ((xevent.xclient.message_type == protocol_atom)
789                                        && (xevent.xclient.data.l[0] == kill_atom))
790                                            /* Quit */
791                                            return 0;
792                                    break;
793    
794                          case KeyPress:                          case KeyPress:
795                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);                                  if (IC != NULL)
796                                  scancode = xkeymap_translate_key(keysym, event.xkey.keycode);                                          /* Multi_key compatible version */
797                                  if (scancode == 0)                                  {
798                                            XmbLookupString(IC,
799                                                            (XKeyPressedEvent *) &
800                                                            xevent, str, sizeof(str), &keysym, &status);
801                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
802                                            {
803                                                    error("XmbLookupString failed with status 0x%x\n",
804                                                          status);
805                                                    break;
806                                            }
807                                    }
808                                    else
809                                    {
810                                            /* Plain old XLookupString */
811                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
812                                            XLookupString((XKeyEvent *) & xevent,
813                                                          str, sizeof(str), &keysym, NULL);
814                                    }
815    
816                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
817                                               get_ksname(keysym)));
818    
819                                    ev_time = time(NULL);
820                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
821                                            break;
822    
823                                    tr = xkeymap_translate_key(keysym,
824                                                               xevent.xkey.keycode, xevent.xkey.state);
825    
826                                    if (tr.scancode == 0)
827                                          break;                                          break;
828    
829                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  ensure_remote_modifiers(ev_time, tr);
830                                                 scancode, 0);  
831                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
832                                  break;                                  break;
833    
834                          case KeyRelease:                          case KeyRelease:
835                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);                                  XLookupString((XKeyEvent *) & xevent, str,
836                                  scancode = xkeymap_translate_key(keysym, event.xkey.keycode);                                                sizeof(str), &keysym, NULL);
837                                  if (scancode == 0)  
838                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
839                                               get_ksname(keysym)));
840    
841                                    ev_time = time(NULL);
842                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
843                                          break;                                          break;
844    
845                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
846                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
847    
848                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xkeymap_translate_button(event.xbutton.button);  
                                 if (button == 0)  
849                                          break;                                          break;
850    
851                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
852                                  break;                                  break;
853    
854                            case ButtonPress:
855                                    flags = MOUSE_FLAG_DOWN;
856                                    /* fall through */
857    
858                          case ButtonRelease:                          case ButtonRelease:
859                                  button = xkeymap_translate_button(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.xbutton.button);
860                                  if (button == 0)                                  if (button == 0)
861                                          break;                                          break;
862    
863                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
864                                                 button,                                  if (xevent.xbutton.y < win_button_size)
865                                                 event.xbutton.x,                                  {
866                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
867                                            if (moving_wnd && (xevent.type == ButtonRelease))
868                                                    moving_wnd = False;
869    
870                                            /*  Check from right to left: */
871    
872                                            if (xevent.xbutton.x >= width - win_button_size)
873                                            {
874                                                    /* The close button, continue */
875                                                    ;
876                                            }
877                                            else if (xevent.xbutton.x >= width - win_button_size * 2)
878                                            {
879                                                    /* The maximize/restore button. Do not send to
880                                                       server.  It might be a good idea to change the
881                                                       cursor or give some other visible indication
882                                                       that rdesktop inhibited this click */
883                                                    break;
884                                            }
885                                            else if (xevent.xbutton.x >= width - win_button_size * 3)
886                                            {
887                                                    /* The minimize button. Iconify window. */
888                                                    XIconifyWindow(display, wnd,
889                                                                   DefaultScreen(display));
890                                                    break;
891                                            }
892                                            else if (xevent.xbutton.x <= win_button_size)
893                                            {
894                                                    /* The system menu. Ignore. */
895                                                    break;
896                                            }
897                                            else
898                                            {
899                                                    /* The title bar. */
900                                                    if ((xevent.type == ButtonPress) && !fullscreen
901                                                        && hide_decorations)
902                                                    {
903                                                            moving_wnd = True;
904                                                            move_x_offset = xevent.xbutton.x;
905                                                            move_y_offset = xevent.xbutton.y;
906                                                    }
907                                                    break;
908    
909                                            }
910                                    }
911    
912                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
913                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
914                                  break;                                  break;
915    
916                          case MotionNotify:                          case MotionNotify:
917                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (moving_wnd)
918                                                 MOUSE_FLAG_MOVE,                                  {
919                                                 event.xmotion.x,                                          XMoveWindow(display, wnd,
920                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - move_x_offset,
921                                                        xevent.xmotion.y_root - move_y_offset);
922                                            break;
923                                    }
924    
925                                    if (fullscreen && !focused)
926                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
927                                                           CurrentTime);
928                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
929                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
930                                    break;
931    
932                            case FocusIn:
933                                    if (xevent.xfocus.mode == NotifyGrab)
934                                            break;
935                                    focused = True;
936                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
937                                                  &dummy, &dummy, &state);
938                                    reset_modifier_keys(state);
939                                    if (grab_keyboard && mouse_in_wnd)
940                                            XGrabKeyboard(display, wnd, True,
941                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
942                                    break;
943    
944                            case FocusOut:
945                                    if (xevent.xfocus.mode == NotifyUngrab)
946                                            break;
947                                    focused = False;
948                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
949                                            XUngrabKeyboard(display, CurrentTime);
950                                  break;                                  break;
951    
952                          case EnterNotify:                          case EnterNotify:
953                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
954                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
955                                    mouse_in_wnd = True;
956                                    if (fullscreen)
957                                    {
958                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
959                                                           CurrentTime);
960                                            break;
961                                    }
962                                    if (focused)
963                                            XGrabKeyboard(display, wnd, True,
964                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
965                                  break;                                  break;
966    
967                          case LeaveNotify:                          case LeaveNotify:
968                                    /* we only register for this event when grab_keyboard */
969                                    mouse_in_wnd = False;
970                                  XUngrabKeyboard(display, CurrentTime);                                  XUngrabKeyboard(display, CurrentTime);
971                                  break;                                  break;
972    
973                          case Expose:                          case Expose:
974                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(display, backstore, wnd, gc,
975                                            event.xexpose.x, event.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
976                                            event.xexpose.width, event.xexpose.height,                                            xevent.xexpose.width,
977                                            event.xexpose.x, event.xexpose.y);                                            xevent.xexpose.height,
978                                              xevent.xexpose.x, xevent.xexpose.y);
979                                  break;                                  break;
980    
981                            case MappingNotify:
982                                    /* Refresh keyboard mapping if it has changed. This is important for
983                                       Xvnc, since it allocates keycodes dynamically */
984                                    if (xevent.xmapping.request == MappingKeyboard
985                                        || xevent.xmapping.request == MappingModifier)
986                                            XRefreshKeyboardMapping(&xevent.xmapping);
987    
988                                    if (xevent.xmapping.request == MappingModifier)
989                                    {
990                                            XFreeModifiermap(mod_map);
991                                            mod_map = XGetModifierMapping(display);
992                                    }
993                                    break;
994    
995                  }                  }
996          }          }
997            /* Keep going */
998            return 1;
999  }  }
1000    
1001  void  /* Returns 0 after user quit, 1 otherwise */
1002    int
1003  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1004  {  {
1005          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1006          fd_set rfds;          fd_set rfds;
1007    
         XFlush(display);  
   
1008          FD_ZERO(&rfds);          FD_ZERO(&rfds);
1009    
1010          while (True)          while (True)
1011          {          {
1012                    /* Process any events already waiting */
1013                    if (!xwin_process_events())
1014                            /* User quit */
1015                            return 0;
1016    
1017                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1018                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1019                  FD_SET(x_socket, &rfds);                  FD_SET(x_socket, &rfds);
# Line 428  ui_select(int rdp_socket) Line 1027  ui_select(int rdp_socket)
1027                                  continue;                                  continue;
1028                  }                  }
1029    
                 if (FD_ISSET(x_socket, &rfds))  
                         xwin_process_events();  
   
1030                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1031                          return;                          return 1;
1032          }          }
1033  }  }
1034    
# Line 443  ui_move_pointer(int x, int y) Line 1039  ui_move_pointer(int x, int y)
1039  }  }
1040    
1041  HBITMAP  HBITMAP
1042  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1043  {  {
1044          XImage *image;          XImage *image;
1045          Pixmap bitmap;          Pixmap bitmap;
# Line 451  ui_create_bitmap(int width, int height, Line 1047  ui_create_bitmap(int width, int height,
1047    
1048          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1049          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
1050          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1051                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1052    
1053          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1054    
# Line 463  ui_create_bitmap(int width, int height, Line 1059  ui_create_bitmap(int width, int height,
1059  }  }
1060    
1061  void  void
1062  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)  
1063  {  {
1064          XImage *image;          XImage *image;
1065          uint8 *tdata;          uint8 *tdata;
   
1066          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1067          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1068                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1069    
1070          if (ownbackstore)          if (ownbackstore)
1071          {          {
# Line 491  ui_paint_bitmap(int x, int y, int cx, in Line 1085  ui_paint_bitmap(int x, int y, int cx, in
1085  void  void
1086  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1087  {  {
1088          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
1089  }  }
1090    
1091  HGLYPH  HGLYPH
1092  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1093  {  {
1094          XImage *image;          XImage *image;
1095          Pixmap bitmap;          Pixmap bitmap;
# Line 507  ui_create_glyph(int width, int height, u Line 1101  ui_create_glyph(int width, int height, u
1101          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
1102          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
1103    
1104          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1105                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1106          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1107          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1108          XInitImage(image);          XInitImage(image);
# Line 517  ui_create_glyph(int width, int height, u Line 1111  ui_create_glyph(int width, int height, u
1111    
1112          XFree(image);          XFree(image);
1113          XFreeGC(display, gc);          XFreeGC(display, gc);
1114          return (HGLYPH)bitmap;          return (HGLYPH) bitmap;
1115  }  }
1116    
1117  void  void
1118  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1119  {  {
1120          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap) glyph);
1121  }  }
1122    
1123  HCURSOR  HCURSOR
1124  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1125                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1126  {  {
1127          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1128          XColor bg, fg;          XColor bg, fg;
# Line 585  ui_create_cursor(unsigned int x, unsigne Line 1179  ui_create_cursor(unsigned int x, unsigne
1179    
1180          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1181          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1182            
1183          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
1184                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1185                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1186    
1187          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1188          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
1189          xfree(mask);          xfree(mask);
1190          xfree(cursor);          xfree(cursor);
1191          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1192  }  }
1193    
1194  void  void
1195  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1196  {  {
1197          XDefineCursor(display, wnd, (Cursor)cursor);          current_cursor = (Cursor) cursor;
1198            XDefineCursor(display, wnd, current_cursor);
1199  }  }
1200    
1201  void  void
1202  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1203  {  {
1204          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(display, (Cursor) cursor);
1205  }  }
1206    
1207  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 614  ui_destroy_cursor(HCURSOR cursor) Line 1210  ui_destroy_cursor(HCURSOR cursor)
1210                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1211                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1212    
1213    
1214  HCOLOURMAP  HCOLOURMAP
1215  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
1216  {  {
1217          COLOURENTRY *entry;          COLOURENTRY *entry;
1218          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1219            if (!owncolmap)
1220            {
1221                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1222                    XColor xentry;
1223                    XColor xc_cache[256];
1224                    uint32 colour;
1225                    int colLookup = 256;
1226                    for (i = 0; i < ncolours; i++)
1227                    {
1228                            entry = &colours->colours[i];
1229                            MAKE_XCOLOR(&xentry, entry);
1230    
1231                            if (XAllocColor(display, xcolmap, &xentry) == 0)
1232                            {
1233                                    /* Allocation failed, find closest match. */
1234                                    int j = 256;
1235                                    int nMinDist = 3 * 256 * 256;
1236                                    long nDist = nMinDist;
1237    
1238                                    /* only get the colors once */
1239                                    while (colLookup--)
1240                                    {
1241                                            xc_cache[colLookup].pixel = colLookup;
1242                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1243                                                    xc_cache[colLookup].blue = 0;
1244                                            xc_cache[colLookup].flags = 0;
1245                                            XQueryColor(display,
1246                                                        DefaultColormap(display,
1247                                                                        DefaultScreen(display)),
1248                                                        &xc_cache[colLookup]);
1249                                    }
1250                                    colLookup = 0;
1251    
1252                                    /* approximate the pixel */
1253                                    while (j--)
1254                                    {
1255                                            if (xc_cache[j].flags)
1256                                            {
1257                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1258                                                             (long) (xentry.red >> 8)) *
1259                                                            ((long) (xc_cache[j].red >> 8) -
1260                                                             (long) (xentry.red >> 8)) +
1261                                                            ((long) (xc_cache[j].green >> 8) -
1262                                                             (long) (xentry.green >> 8)) *
1263                                                            ((long) (xc_cache[j].green >> 8) -
1264                                                             (long) (xentry.green >> 8)) +
1265                                                            ((long) (xc_cache[j].blue >> 8) -
1266                                                             (long) (xentry.blue >> 8)) *
1267                                                            ((long) (xc_cache[j].blue >> 8) -
1268                                                             (long) (xentry.blue >> 8));
1269                                            }
1270                                            if (nDist < nMinDist)
1271                                            {
1272                                                    nMinDist = nDist;
1273                                                    xentry.pixel = j;
1274                                            }
1275                                    }
1276                            }
1277                            colour = xentry.pixel;
1278    
1279                            /* update our cache */
1280                            if (xentry.pixel < 256)
1281                            {
1282                                    xc_cache[xentry.pixel].red = xentry.red;
1283                                    xc_cache[xentry.pixel].green = xentry.green;
1284                                    xc_cache[xentry.pixel].blue = xentry.blue;
1285    
1286          if (owncolmap)                          }
1287    
1288    
1289                            /* byte swap here to make translate_image faster */
1290                            map[i] = translate_colour(colour);
1291                    }
1292                    return map;
1293            }
1294            else
1295          {          {
1296                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1297                  Colormap map;                  Colormap map;
# Line 638  ui_create_colourmap(COLOURMAP *colours) Line 1309  ui_create_colourmap(COLOURMAP *colours)
1309                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(display, map, xcolours, ncolours);
1310    
1311                  xfree(xcolours);                  xfree(xcolours);
1312                  return (HCOLOURMAP)map;                  return (HCOLOURMAP) map;
         }  
         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;  
1313          }          }
1314  }  }
1315    
1316  void  void
1317  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1318  {  {
1319          if (owncolmap)          if (!owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1320                  xfree(map);                  xfree(map);
1321            else
1322                    XFreeColormap(display, (Colormap) map);
1323  }  }
1324    
1325  void  void
1326  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1327  {  {
1328          if (owncolmap)          if (!owncolmap)
                 XSetWindowColormap(display, wnd, (Colormap)map);  
         else  
1329                  colmap = map;                  colmap = map;
1330            else
1331                    XSetWindowColormap(display, wnd, (Colormap) map);
1332  }  }
1333    
1334  void  void
# Line 695  ui_set_clip(int x, int y, int cx, int cy Line 1344  ui_set_clip(int x, int y, int cx, int cy
1344  }  }
1345    
1346  void  void
1347  ui_reset_clip()  ui_reset_clip(void)
1348  {  {
1349          XRectangle rect;          XRectangle rect;
1350    
# Line 707  ui_reset_clip() Line 1356  ui_reset_clip()
1356  }  }
1357    
1358  void  void
1359  ui_bell()  ui_bell(void)
1360  {  {
1361          XBell(display, 0);          XBell(display, 0);
1362  }  }
# Line 724  ui_destblt(uint8 opcode, Line 1373  ui_destblt(uint8 opcode,
1373  void  void
1374  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1375            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1376            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1377  {  {
1378          Pixmap fill;          Pixmap fill;
1379            uint8 i, ipattern[8];
1380    
1381          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1382    
# Line 738  ui_patblt(uint8 opcode, Line 1388  ui_patblt(uint8 opcode,
1388                          break;                          break;
1389    
1390                  case 3: /* Pattern */                  case 3: /* Pattern */
1391                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
1392                                    ipattern[7 - i] = brush->pattern[i];
1393                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1394    
1395                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1396                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
# Line 749  ui_patblt(uint8 opcode, Line 1401  ui_patblt(uint8 opcode,
1401                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1402    
1403                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1404                          ui_destroy_glyph((HGLYPH)fill);                          XSetTSOrigin(display, gc, 0, 0);
1405                            ui_destroy_glyph((HGLYPH) fill);
1406                          break;                          break;
1407    
1408                  default:                  default:
# Line 767  ui_screenblt(uint8 opcode, Line 1420  ui_screenblt(uint8 opcode,
1420          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1421          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1422          if (ownbackstore)          if (ownbackstore)
1423                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1424          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1425  }  }
1426    
# Line 778  ui_memblt(uint8 opcode, Line 1430  ui_memblt(uint8 opcode,
1430            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1431  {  {
1432          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1433          XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1434          if (ownbackstore)          if (ownbackstore)
1435                  XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1436          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1437  }  }
1438    
# Line 789  void Line 1440  void
1440  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1441            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1442            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1443            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1444  {  {
1445          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1446             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 798  ui_triblt(uint8 opcode, Line 1449  ui_triblt(uint8 opcode,
1449          {          {
1450                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1451                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1452                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1453                          break;                          break;
1454    
1455                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1456                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1457                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1458                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1459                          break;                          break;
1460    
1461                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1462                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1463                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1464                          break;                          break;
1465    
1466                  default:                  default:
# Line 825  ui_triblt(uint8 opcode, Line 1472  ui_triblt(uint8 opcode,
1472  void  void
1473  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1474          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1475          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1476  {  {
1477          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1478          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
# Line 844  ui_rect( Line 1491  ui_rect(
1491          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1492  }  }
1493    
1494    /* warning, this function only draws on wnd or backstore, not both */
1495  void  void
1496  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1497                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1498                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1499                int fgcolour)                int bgcolour, int fgcolour)
1500  {  {
1501          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1502          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1503    
1504          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(display, gc,
1505                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1506          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(display, gc, (Pixmap) glyph);
1507          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(display, gc, x, y);
1508    
1509          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1510    
1511          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1512  }  }
1513    
1514    #define DO_GLYPH(ttext,idx) \
1515    {\
1516      glyph = cache_get_font (font, ttext[idx]);\
1517      if (!(flags & TEXT2_IMPLICIT_X))\
1518        {\
1519          xyoffset = ttext[++idx];\
1520          if ((xyoffset & 0x80))\
1521            {\
1522              if (flags & TEXT2_VERTICAL) \
1523                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1524              else\
1525                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1526              idx += 2;\
1527            }\
1528          else\
1529            {\
1530              if (flags & TEXT2_VERTICAL) \
1531                y += xyoffset;\
1532              else\
1533                x += xyoffset;\
1534            }\
1535        }\
1536      if (glyph != NULL)\
1537        {\
1538          ui_draw_glyph (mixmode, x + glyph->offset,\
1539                         y + glyph->baseline,\
1540                         glyph->width, glyph->height,\
1541                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1542          if (flags & TEXT2_IMPLICIT_X)\
1543            x += glyph->width;\
1544        }\
1545    }
1546    
1547  void  void
1548  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,
1549               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1550               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1551               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1552  {  {
1553          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1554          int i, offset;          int i, j, xyoffset;
1555            DATABLOB *entry;
1556    
1557          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
1558    
1559          if (boxcx > 1)          if (boxcx > 1)
1560          {          {
1561                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1562          }          }
1563          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1564          {          {
1565                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1566          }          }
1567    
1568          /* Paint text, character by character */          /* Paint text, character by character */
1569          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1570          {          {
1571                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
1572                  {                  {
1573                          offset = text[++i];                          case 0xff:
1574                          if (offset & 0x80)                                  if (i + 2 < length)
1575                                  offset = ((offset & 0x7f) << 8) | text[++i];                                          cache_put_text(text[i + 1], text, text[i + 2]);
1576                                    else
1577                          if (flags & TEXT2_VERTICAL)                                  {
1578                                  y += offset;                                          error("this shouldn't be happening\n");
1579                          else                                          exit(1);
1580                                  x += offset;                                  }
1581                  }                                  /* this will move pointer from start to first character after FF command */
1582                                    length -= i + 3;
1583                                    text = &(text[i + 3]);
1584                                    i = 0;
1585                                    break;
1586    
1587                  if (glyph != NULL)                          case 0xfe:
1588                  {                                  entry = cache_get_text(text[i + 1]);
1589                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  if (entry != NULL)
1590                                        y + (short) glyph->baseline,                                  {
1591                                        glyph->width, glyph->height,                                          if ((((uint8 *) (entry->data))[1] ==
1592                                        glyph->pixmap, 0, 0,                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1593                                        bgcolour, fgcolour);                                          {
1594                                                    if (flags & TEXT2_VERTICAL)
1595                                                            y += text[i + 2];
1596                                                    else
1597                                                            x += text[i + 2];
1598                                            }
1599                                            for (j = 0; j < entry->size; j++)
1600                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1601                                    }
1602                                    if (i + 2 < length)
1603                                            i += 3;
1604                                    else
1605                                            i += 2;
1606                                    length -= i;
1607                                    /* this will move pointer from start to first character after FE command */
1608                                    text = &(text[i]);
1609                                    i = 0;
1610                                    break;
1611    
1612                          if (flags & TEXT2_IMPLICIT_X)                          default:
1613                                  x += glyph->width;                                  DO_GLYPH(text, i);
1614                                    i++;
1615                                    break;
1616                  }                  }
1617          }          }
1618            if (ownbackstore)
1619            {
1620                    if (boxcx > 1)
1621                            XCopyArea(display, backstore, wnd, gc, boxx,
1622                                      boxy, boxcx, boxcy, boxx, boxy);
1623                    else
1624                            XCopyArea(display, backstore, wnd, gc, clipx,
1625                                      clipy, clipcx, clipcy, clipx, clipy);
1626            }
1627  }  }
1628    
1629  void  void
# Line 922  ui_desktop_save(uint32 offset, int x, in Line 1634  ui_desktop_save(uint32 offset, int x, in
1634    
1635          if (ownbackstore)          if (ownbackstore)
1636          {          {
1637                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1638          }          }
1639          else          else
1640          {          {
1641                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(display, wnd, cx, cy, depth);
1642                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1643                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1644                  XFreePixmap(display, pix);                  XFreePixmap(display, pix);
1645          }          }
1646    
1647          offset *= bpp/8;          offset *= bpp / 8;
1648          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);  
1649    
1650          XDestroyImage(image);          XDestroyImage(image);
1651  }  }
# Line 947  ui_desktop_restore(uint32 offset, int x, Line 1656  ui_desktop_restore(uint32 offset, int x,
1656          XImage *image;          XImage *image;
1657          uint8 *data;          uint8 *data;
1658    
1659          offset *= bpp/8;          offset *= bpp / 8;
1660          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1661          if (data == NULL)          if (data == NULL)
1662                  return;                  return;
1663    
1664          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1665                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
                              cx * bpp/8);  
1666    
1667          if (ownbackstore)          if (ownbackstore)
1668          {          {

Legend:
Removed from v.38  
changed lines
  Added in v.342

  ViewVC Help
Powered by ViewVC 1.1.26