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

Legend:
Removed from v.201  
changed lines
  Added in v.1042

  ViewVC Help
Powered by ViewVC 1.1.26