/[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 35 by matty, Sat Sep 15 14:01:45 2001 UTC revision 644 by jsorg71, Thu Mar 25 22:58:45 2004 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-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 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 BOOL g_sendmotion;
34  extern BOOL fullscreen;  extern BOOL g_fullscreen;
35    extern BOOL g_grab_keyboard;
36  static Display *display;  extern BOOL g_hide_decorations;
37  static int x_socket;  extern char g_title[];
38  static Window wnd;  extern int g_server_bpp;
39  static GC gc;  extern int g_win_button_size;
40  static Visual *visual;  
41  static int depth;  Display *g_display;
42  static int bpp;  Time g_last_gesturetime;
43    static int g_x_socket;
44    static Screen *g_screen;
45    Window g_wnd;
46    uint32 g_embed_wnd;
47    BOOL g_enable_compose = False;
48    static GC g_gc = NULL;
49    static Visual *g_visual;
50    static int g_depth;
51    static int g_bpp;
52    static XIM g_IM;
53    static XIC g_IC;
54    static XModifierKeymap *g_mod_map;
55    static Cursor g_current_cursor;
56    static HCURSOR g_null_cursor = NULL;
57    static Atom g_protocol_atom, g_kill_atom;
58    static BOOL g_focused;
59    static BOOL g_mouse_in_wnd;
60    static BOOL g_arch_match = False; /* set to True if RGB XServer and little endian */
61    
62  /* endianness */  /* endianness */
63  static BOOL host_be;  static BOOL g_host_be;
64  static BOOL xserver_be;  static BOOL g_xserver_be;
65    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
66    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
67    
68  /* software backing store */  /* software backing store */
69  static BOOL ownbackstore;  BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
70  static Pixmap backstore;  static Pixmap g_backstore = 0;
71    
72    /* Moving in single app mode */
73    static BOOL g_moving_wnd;
74    static int g_move_x_offset = 0;
75    static int g_move_y_offset = 0;
76    
77    #ifdef WITH_RDPSND
78    extern int g_dsp_fd;
79    extern BOOL g_dsp_busy;
80    extern BOOL g_rdpsnd;
81    #endif
82    
83    /* MWM decorations */
84    #define MWM_HINTS_DECORATIONS   (1L << 1)
85    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
86    typedef struct
87    {
88            uint32 flags;
89            uint32 functions;
90            uint32 decorations;
91            sint32 inputMode;
92            uint32 status;
93    }
94    PropMotifWmHints;
95    
96    typedef struct
97    {
98            uint32 red;
99            uint32 green;
100            uint32 blue;
101    }
102    PixelColour;
103    
104    
105  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
106  { \  { \
107          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
108          if (ownbackstore) \          if (g_ownbackstore) \
109                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
110    }
111    
112    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
113    { \
114            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
115  }  }
116    
117  /* colour maps */  /* colour maps */
118  static BOOL owncolmap;  BOOL g_owncolmap = False;
119  static Colormap xcolmap;  static Colormap g_xcolmap;
120  static uint32 white;  static uint32 *g_colmap = NULL;
121  static uint32 *colmap;  
122    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
123  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
124  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
 #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  
125    
126  static int rop2_map[] = {  static int rop2_map[] = {
127          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 81  static int rop2_map[] = { Line 142  static int rop2_map[] = {
142          GXset                   /* 1 */          GXset                   /* 1 */
143  };  };
144    
145  #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]); }
146  #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); }
147    
148  static void  static void
149  translate8(uint8 *data, uint8 *out, uint8 *end)  mwm_hide_decorations(void)
150  {  {
151          while (out < end)          PropMotifWmHints motif_hints;
152                  *(out++) = (uint8)colmap[*(data++)];          Atom hintsatom;
153    
154            /* setup the property */
155            motif_hints.flags = MWM_HINTS_DECORATIONS;
156            motif_hints.decorations = 0;
157    
158            /* get the atom for the property */
159            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
160            if (!hintsatom)
161            {
162                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
163                    return;
164            }
165    
166            XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
167                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
168    }
169    
170    static PixelColour
171    split_colour15(uint32 colour)
172    {
173            PixelColour rv;
174            rv.red = (colour & 0x7c00) >> 7;
175            rv.green = (colour & 0x03e0) >> 2;
176            rv.blue = (colour & 0x001f) << 3;
177            return rv;
178    }
179    
180    static PixelColour
181    split_colour16(uint32 colour)
182    {
183            PixelColour rv;
184            rv.red = (colour & 0xf800) >> 8;
185            rv.green = (colour & 0x07e0) >> 3;
186            rv.blue = (colour & 0x001f) << 3;
187            return rv;
188    }
189    
190    static PixelColour
191    split_colour24(uint32 colour)
192    {
193            PixelColour rv;
194            rv.blue = (colour & 0xff0000) >> 16;
195            rv.green = (colour & 0x00ff00) >> 8;
196            rv.red = (colour & 0x0000ff);
197            return rv;
198    }
199    
200    static uint32
201    make_colour(PixelColour pc)
202    {
203            return (((pc.red >> g_red_shift_r) << g_red_shift_l)
204                    | ((pc.green >> g_green_shift_r) << g_green_shift_l)
205                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));
206    }
207    
208    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
209    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
210    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
211                            x = (x << 16) | (x >> 16); }
212    
213    static uint32
214    translate_colour(uint32 colour)
215    {
216            PixelColour pc;
217            switch (g_server_bpp)
218            {
219                    case 15:
220                            pc = split_colour15(colour);
221                            break;
222                    case 16:
223                            pc = split_colour16(colour);
224                            break;
225                    case 24:
226                            pc = split_colour24(colour);
227                            break;
228            }
229            return make_colour(pc);
230  }  }
231    
232  static void  static void
233  translate16(uint8 *data, uint16 *out, uint16 *end)  translate8to8(uint8 * data, uint8 * out, uint8 * end)
234  {  {
235          while (out < end)          while (out < end)
236                  *(out++) = (uint16)colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
237    }
238    
239    static void
240    translate8to16(uint8 * data, uint8 * out, uint8 * end)
241    {
242            uint16 value;
243    
244            if (g_xserver_be)
245            {
246                    while (out < end)
247                    {
248                            value = (uint16) g_colmap[*(data++)];
249                            *(out++) = value >> 8;
250                            *(out++) = value;
251                    }
252            }
253            else
254            {
255                    while (out < end)
256                    {
257                            value = (uint16) g_colmap[*(data++)];
258                            *(out++) = value;
259                            *(out++) = value >> 8;
260                    }
261            }
262  }  }
263    
264  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
265  static void  static void
266  translate24(uint8 *data, uint8 *out, uint8 *end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
267  {  {
268          uint32 value;          uint32 value;
269    
270            if (g_xserver_be)
271            {
272                    while (out < end)
273                    {
274                            value = g_colmap[*(data++)];
275                            *(out++) = value >> 16;
276                            *(out++) = value >> 8;
277                            *(out++) = value;
278                    }
279            }
280            else
281            {
282                    while (out < end)
283                    {
284                            value = g_colmap[*(data++)];
285                            *(out++) = value;
286                            *(out++) = value >> 8;
287                            *(out++) = value >> 16;
288                    }
289            }
290    }
291    
292    static void
293    translate8to32(uint8 * data, uint8 * out, uint8 * end)
294    {
295            uint32 value;
296    
297            if (g_xserver_be)
298            {
299                    while (out < end)
300                    {
301                            value = g_colmap[*(data++)];
302                            *(out++) = value >> 24;
303                            *(out++) = value >> 16;
304                            *(out++) = value >> 8;
305                            *(out++) = value;
306                    }
307            }
308            else
309            {
310                    while (out < end)
311                    {
312                            value = g_colmap[*(data++)];
313                            *(out++) = value;
314                            *(out++) = value >> 8;
315                            *(out++) = value >> 16;
316                            *(out++) = value >> 24;
317                    }
318            }
319    }
320    
321    static void
322    translate15to16(uint16 * data, uint8 * out, uint8 * end)
323    {
324            uint16 pixel;
325            uint16 value;
326    
327          while (out < end)          while (out < end)
328          {          {
329                  value = colmap[*(data++)];                  pixel = *(data++);
330                  *(out++) = value;  
331                  *(out++) = value >> 8;                  if (g_host_be)
332                  *(out++) = value >> 16;                  {
333                            BSWAP16(pixel);
334                    }
335    
336                    value = make_colour(split_colour15(pixel));
337    
338                    if (g_xserver_be)
339                    {
340                            *(out++) = value >> 8;
341                            *(out++) = value;
342                    }
343                    else
344                    {
345                            *(out++) = value;
346                            *(out++) = value >> 8;
347                    }
348          }          }
349  }  }
350    
351  static void  static void
352  translate32(uint8 *data, uint32 *out, uint32 *end)  translate15to24(uint16 * data, uint8 * out, uint8 * end)
353  {  {
354            uint32 value;
355            uint16 pixel;
356    
357          while (out < end)          while (out < end)
358                  *(out++) = colmap[*(data++)];          {
359                    pixel = *(data++);
360    
361                    if (g_host_be)
362                    {
363                            BSWAP16(pixel);
364                    }
365    
366                    value = make_colour(split_colour15(pixel));
367                    if (g_xserver_be)
368                    {
369                            *(out++) = value >> 16;
370                            *(out++) = value >> 8;
371                            *(out++) = value;
372                    }
373                    else
374                    {
375                            *(out++) = value;
376                            *(out++) = value >> 8;
377                            *(out++) = value >> 16;
378                    }
379            }
380  }  }
381    
382  static uint8 *  static void
383  translate_image(int width, int height, uint8 *data)  translate15to32(uint16 * data, uint8 * out, uint8 * end)
384  {  {
385          int size = width * height * bpp/8;          uint16 pixel;
386          uint8 *out = xmalloc(size);          uint32 value;
         uint8 *end = out + size;  
387    
388          switch (bpp)          while (out < end)
389          {          {
390                  case 8:                  pixel = *(data++);
                         translate8(data, out, end);  
                         break;  
391    
392                  case 16:                  if (g_host_be)
393                          translate16(data, (uint16 *)out, (uint16 *)end);                  {
394                          break;                          BSWAP16(pixel);
395                    }
396    
397                  case 24:                  value = make_colour(split_colour15(pixel));
                         translate24(data, out, end);  
                         break;  
398    
399                  case 32:                  if (g_xserver_be)
400                          translate32(data, (uint32 *)out, (uint32 *)end);                  {
401                          break;                          *(out++) = value >> 24;
402                            *(out++) = value >> 16;
403                            *(out++) = value >> 8;
404                            *(out++) = value;
405                    }
406                    else
407                    {
408                            *(out++) = value;
409                            *(out++) = value >> 8;
410                            *(out++) = value >> 16;
411                            *(out++) = value >> 24;
412                    }
413          }          }
414    }
415    
416          return out;  static void
417    translate16to16(uint16 * data, uint8 * out, uint8 * end)
418    {
419            uint16 pixel;
420            uint16 value;
421    
422            while (out < end)
423            {
424                    pixel = *(data++);
425    
426                    if (g_host_be)
427                    {
428                            BSWAP16(pixel);
429                    }
430    
431                    value = make_colour(split_colour16(pixel));
432    
433                    if (g_xserver_be)
434                    {
435                            *(out++) = value >> 8;
436                            *(out++) = value;
437                    }
438                    else
439                    {
440                            *(out++) = value;
441                            *(out++) = value >> 8;
442                    }
443            }
444  }  }
445    
446  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  static void
447  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  translate16to24(uint16 * data, uint8 * out, uint8 * end)
448  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  {
449                          x = (x << 16) | (x >> 16); }          uint32 value;
450            uint16 pixel;
451    
452  static uint32          while (out < end)
453  translate_colour(uint32 colour)          {
454                    pixel = *(data++);
455    
456                    if (g_host_be)
457                    {
458                            BSWAP16(pixel);
459                    }
460    
461                    value = make_colour(split_colour16(pixel));
462    
463                    if (g_xserver_be)
464                    {
465                            *(out++) = value >> 16;
466                            *(out++) = value >> 8;
467                            *(out++) = value;
468                    }
469                    else
470                    {
471                            *(out++) = value;
472                            *(out++) = value >> 8;
473                            *(out++) = value >> 16;
474                    }
475            }
476    }
477    
478    static void
479    translate16to32(uint16 * data, uint8 * out, uint8 * end)
480  {  {
481          switch (bpp)          uint16 pixel;
482            uint32 value;
483    
484            while (out < end)
485          {          {
486                  case 16:                  pixel = *(data++);
                         if (host_be != xserver_be)  
                                 BSWAP16(colour);  
                         break;  
487    
488                    if (g_host_be)
489                    {
490                            BSWAP16(pixel);
491                    }
492    
493                    value = make_colour(split_colour16(pixel));
494    
495                    if (g_xserver_be)
496                    {
497                            *(out++) = value >> 24;
498                            *(out++) = value >> 16;
499                            *(out++) = value >> 8;
500                            *(out++) = value;
501                    }
502                    else
503                    {
504                            *(out++) = value;
505                            *(out++) = value >> 8;
506                            *(out++) = value >> 16;
507                            *(out++) = value >> 24;
508                    }
509            }
510    }
511    
512    static void
513    translate24to16(uint8 * data, uint8 * out, uint8 * end)
514    {
515            uint32 pixel = 0;
516            uint16 value;
517            while (out < end)
518            {
519                    pixel = *(data++) << 16;
520                    pixel |= *(data++) << 8;
521                    pixel |= *(data++);
522    
523                    value = (uint16) make_colour(split_colour24(pixel));
524    
525                    if (g_xserver_be)
526                    {
527                            *(out++) = value >> 8;
528                            *(out++) = value;
529                    }
530                    else
531                    {
532                            *(out++) = value;
533                            *(out++) = value >> 8;
534                    }
535            }
536    }
537    
538    static void
539    translate24to24(uint8 * data, uint8 * out, uint8 * end)
540    {
541            uint32 pixel;
542            uint32 value;
543    
544            while (out < end)
545            {
546                    pixel = *(data++) << 16;
547                    pixel |= *(data++) << 8;
548                    pixel |= *(data++);
549    
550                    value = make_colour(split_colour24(pixel));
551    
552                    if (g_xserver_be)
553                    {
554                            *(out++) = value >> 16;
555                            *(out++) = value >> 8;
556                            *(out++) = value;
557                    }
558                    else
559                    {
560                            *(out++) = value;
561                            *(out++) = value >> 8;
562                            *(out++) = value >> 16;
563                    }
564            }
565    }
566    
567    static void
568    translate24to32(uint8 * data, uint8 * out, uint8 * end)
569    {
570            uint32 pixel;
571            uint32 value;
572    
573            while (out < end)
574            {
575                    pixel = *(data++) << 16;
576                    pixel |= *(data++) << 8;
577                    pixel |= *(data++);
578    
579                    value = make_colour(split_colour24(pixel));
580    
581                    if (g_xserver_be)
582                    {
583                            *(out++) = value >> 24;
584                            *(out++) = value >> 16;
585                            *(out++) = value >> 8;
586                            *(out++) = value;
587                    }
588                    else
589                    {
590                            *(out++) = value;
591                            *(out++) = value >> 8;
592                            *(out++) = value >> 16;
593                            *(out++) = value >> 24;
594                    }
595            }
596    }
597    
598    static uint8 *
599    translate_image(int width, int height, uint8 * data)
600    {
601            int size;
602            uint8 *out;
603            uint8 *end;
604    
605            /* if server and xserver bpp match, */
606            /* and arch(endian) matches, no need to translate */
607            /* just return data */
608            if (g_depth > 8)
609                    if (g_arch_match)
610                            if (g_depth == g_server_bpp)
611                                    return data;
612    
613            size = width * height * (g_bpp / 8);
614            out = (uint8 *) xmalloc(size);
615            end = out + size;
616    
617            switch (g_server_bpp)
618            {
619                  case 24:                  case 24:
620                          if (xserver_be)                          switch (g_bpp)
621                                  BSWAP24(colour);                          {
622                                    case 32:
623                                            translate24to32(data, out, end);
624                                            break;
625                                    case 24:
626                                            translate24to24(data, out, end);
627                                            break;
628                                    case 16:
629                                            translate24to16(data, out, end);
630                                            break;
631                            }
632                          break;                          break;
633                    case 16:
634                  case 32:                          switch (g_bpp)
635                          if (host_be != xserver_be)                          {
636                                  BSWAP32(colour);                                  case 32:
637                                            translate16to32((uint16 *) data, out, end);
638                                            break;
639                                    case 24:
640                                            translate16to24((uint16 *) data, out, end);
641                                            break;
642                                    case 16:
643                                            translate16to16((uint16 *) data, out, end);
644                                            break;
645                            }
646                            break;
647                    case 15:
648                            switch (g_bpp)
649                            {
650                                    case 32:
651                                            translate15to32((uint16 *) data, out, end);
652                                            break;
653                                    case 24:
654                                            translate15to24((uint16 *) data, out, end);
655                                            break;
656                                    case 16:
657                                            translate15to16((uint16 *) data, out, end);
658                                            break;
659                            }
660                            break;
661                    case 8:
662                            switch (g_bpp)
663                            {
664                                    case 8:
665                                            translate8to8(data, out, end);
666                                            break;
667                                    case 16:
668                                            translate8to16(data, out, end);
669                                            break;
670                                    case 24:
671                                            translate8to24(data, out, end);
672                                            break;
673                                    case 32:
674                                            translate8to32(data, out, end);
675                                            break;
676                            }
677                          break;                          break;
678          }          }
679            return out;
680    }
681    
682    BOOL
683    get_key_state(unsigned int state, uint32 keysym)
684    {
685            int modifierpos, key, keysymMask = 0;
686            int offset;
687    
688          return colour;          KeyCode keycode = XKeysymToKeycode(g_display, keysym);
689    
690            if (keycode == NoSymbol)
691                    return False;
692    
693            for (modifierpos = 0; modifierpos < 8; modifierpos++)
694            {
695                    offset = g_mod_map->max_keypermod * modifierpos;
696    
697                    for (key = 0; key < g_mod_map->max_keypermod; key++)
698                    {
699                            if (g_mod_map->modifiermap[offset + key] == keycode)
700                                    keysymMask |= 1 << modifierpos;
701                    }
702            }
703    
704            return (state & keysymMask) ? True : False;
705    }
706    
707    static void
708    calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
709    {
710            *shift_l = ffs(mask) - 1;
711            mask >>= *shift_l;
712            *shift_r = 8 - ffs(mask & ~(mask >> 1));
713  }  }
714    
715  BOOL  BOOL
716  ui_create_window(char *title)  ui_init(void)
717  {  {
718          XSetWindowAttributes attribs;          XVisualInfo vi;
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
719          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
         Screen *screen;  
720          uint16 test;          uint16 test;
721          int i;          int i, screen_num, nvisuals;
722            XVisualInfo *vmatches = NULL;
723            XVisualInfo template;
724            Bool TrueColorVisual = False;
725    
726          display = XOpenDisplay(NULL);          g_display = XOpenDisplay(NULL);
727          if (display == NULL)          if (g_display == NULL)
728          {          {
729                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
730                  return False;                  return False;
731          }          }
732    
733          x_socket = ConnectionNumber(display);          screen_num = DefaultScreen(g_display);
734          screen = DefaultScreenOfDisplay(display);          g_x_socket = ConnectionNumber(g_display);
735          visual = DefaultVisualOfScreen(screen);          g_screen = ScreenOfDisplay(g_display, screen_num);
736          depth = DefaultDepthOfScreen(screen);          g_depth = DefaultDepthOfScreen(g_screen);
737    
738            /* Search for best TrueColor depth */
739            template.class = TrueColor;
740            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
741    
742            nvisuals--;
743            while (nvisuals >= 0)
744            {
745                    if ((vmatches + nvisuals)->depth > g_depth)
746                    {
747                            g_depth = (vmatches + nvisuals)->depth;
748                    }
749                    nvisuals--;
750                    TrueColorVisual = True;
751            }
752    
753            test = 1;
754            g_host_be = !(BOOL) (*(uint8 *) (&test));
755            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
756    
757            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
758            {
759                    /* we use a colourmap, so the default visual should do */
760                    g_visual = DefaultVisualOfScreen(g_screen);
761                    g_depth = DefaultDepthOfScreen(g_screen);
762    
763                    /* Do not allocate colours on a TrueColor visual */
764                    if (g_visual->class == TrueColor)
765                    {
766                            g_owncolmap = False;
767                    }
768            }
769            else
770            {
771                    /* need a truecolour visual */
772                    if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
773                    {
774                            error("The display does not support true colour - high colour support unavailable.\n");
775                            return False;
776                    }
777    
778                    g_visual = vi.visual;
779                    g_owncolmap = False;
780                    calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
781                    calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
782                    calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
783    
784                    /* if RGB video and averything is little endian */
785                    if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask)
786                            if (!g_xserver_be && !g_host_be)
787                                    g_arch_match = True;
788            }
789    
790          pfm = XListPixmapFormats(display, &i);          pfm = XListPixmapFormats(g_display, &i);
791          if (pfm != NULL)          if (pfm != NULL)
792          {          {
793                  /* Use maximum bpp for this depth - this is generally                  /* Use maximum bpp for this depth - this is generally
794                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
795                  while (i--)                  while (i--)
796                  {                  {
797                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
798                          {                          {
799                                  bpp = pfm[i].bits_per_pixel;                                  g_bpp = pfm[i].bits_per_pixel;
800                          }                          }
801                  }                  }
802                  XFree(pfm);                  XFree(pfm);
803          }          }
804    
805          if (bpp < 8)          if (g_bpp < 8)
806          {          {
807                  error("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
808                  XCloseDisplay(display);                  XCloseDisplay(g_display);
809                  return False;                  return False;
810          }          }
811    
812          if (depth <= 8)          if (!g_owncolmap)
813                  owncolmap = True;          {
814          else                  g_xcolmap =
815                  xcolmap = DefaultColormapOfScreen(screen);                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
816                                            AllocNone);
817          test = 1;                  if (g_depth <= 8)
818          host_be = !(BOOL)(*(uint8 *)(&test));                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
819          xserver_be = (ImageByteOrder(display) == MSBFirst);          }
   
         white = WhitePixelOfScreen(screen);  
         attribs.background_pixel = BlackPixelOfScreen(screen);  
         attribs.backing_store = DoesBackingStore(screen);  
820    
821          if (attribs.backing_store == NotUseful)          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
822                  ownbackstore = True;          {
823                    warning("External BackingStore not available, using internal\n");
824                    g_ownbackstore = True;
825            }
826    
827          if (fullscreen)          /*
828             * Determine desktop size
829             */
830            if (g_fullscreen)
831          {          {
832                  attribs.override_redirect = True;                  g_width = WidthOfScreen(g_screen);
833                  width = WidthOfScreen(screen);                  g_height = HeightOfScreen(g_screen);
                 height = HeightOfScreen(screen);  
834          }          }
835          else          else if (g_width < 0)
836          {          {
837                  attribs.override_redirect = False;                  /* Percent of screen */
838                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
839                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
840          }          }
841            else if (g_width == 0)
842            {
843                    /* Fetch geometry from _NET_WORKAREA */
844                    uint32 x, y, cx, cy;
845    
846                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
847                    {
848                            g_width = cx;
849                            g_height = cy;
850                    }
851                    else
852                    {
853                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
854                            g_width = 800;
855                            g_height = 600;
856                    }
857            }
858    
859            /* make sure width is a multiple of 4 */
860            g_width = (g_width + 3) & ~3;
861    
862          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          g_mod_map = XGetModifierMapping(g_display);
863    
864          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          xkeymap_init();
                             0, 0, width, height, 0, CopyFromParent,  
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
865    
866          XStoreName(display, wnd, title);          if (g_enable_compose)
867                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
868    
869            xclip_init();
870    
871            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
872    
873            return True;
874    }
875    
876    void
877    ui_deinit(void)
878    {
879            if (g_IM != NULL)
880                    XCloseIM(g_IM);
881    
882            if (g_null_cursor != NULL)
883                    ui_destroy_cursor(g_null_cursor);
884    
885            XFreeModifiermap(g_mod_map);
886    
887            if (g_ownbackstore)
888                    XFreePixmap(g_display, g_backstore);
889    
890            XFreeGC(g_display, g_gc);
891            XCloseDisplay(g_display);
892            g_display = NULL;
893    }
894    
895    BOOL
896    ui_create_window(void)
897    {
898            uint8 null_pointer_mask[1] = { 0x80 };
899            uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };
900            XSetWindowAttributes attribs;
901            XClassHint *classhints;
902            XSizeHints *sizehints;
903            int wndwidth, wndheight;
904            long input_mask, ic_input_mask;
905            XEvent xevent;
906    
907            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
908            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
909    
910            attribs.background_pixel = BlackPixelOfScreen(g_screen);
911            attribs.border_pixel = WhitePixelOfScreen(g_screen);
912            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
913            attribs.override_redirect = g_fullscreen;
914            attribs.colormap = g_xcolmap;
915    
916            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
917                                  0, g_depth, InputOutput, g_visual,
918                                  CWBackPixel | CWBackingStore | CWOverrideRedirect |
919                                  CWColormap | CWBorderPixel, &attribs);
920    
921            if (g_gc == NULL)
922                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
923    
924            if ((g_ownbackstore) && (g_backstore == 0))
925            {
926                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
927    
928                    /* clear to prevent rubbish being exposed at startup */
929                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
930                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
931            }
932    
933            XStoreName(g_display, g_wnd, g_title);
934    
935            if (g_hide_decorations)
936                    mwm_hide_decorations();
937    
938          classhints = XAllocClassHint();          classhints = XAllocClassHint();
939          if (classhints != NULL)          if (classhints != NULL)
940          {          {
941                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
942                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
943                  XFree(classhints);                  XFree(classhints);
944          }          }
945    
# Line 274  ui_create_window(char *title) Line 947  ui_create_window(char *title)
947          if (sizehints)          if (sizehints)
948          {          {
949                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
950                  sizehints->min_width = sizehints->max_width = width;                  sizehints->min_width = sizehints->max_width = g_width;
951                  sizehints->min_height = sizehints->max_height = height;                  sizehints->min_height = sizehints->max_height = g_height;
952                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
953                  XFree(sizehints);                  XFree(sizehints);
954          }          }
955    
956          input_mask = KeyPressMask | KeyReleaseMask          if ( g_embed_wnd )
957                          | ButtonPressMask | ButtonReleaseMask          {
958                          | EnterWindowMask | LeaveWindowMask;                  XReparentWindow(g_display, g_wnd, (Window)g_embed_wnd, 0, 0);
959            }
960    
961          if (sendmotion)          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
962                  input_mask |= PointerMotionMask;                  VisibilityChangeMask | FocusChangeMask;
963    
964          if (ownbackstore)          if (g_sendmotion)
965                    input_mask |= PointerMotionMask;
966            if (g_ownbackstore)
967                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
968            if (g_fullscreen || g_grab_keyboard)
969                    input_mask |= EnterWindowMask;
970            if (g_grab_keyboard)
971                    input_mask |= LeaveWindowMask;
972    
973          XSelectInput(display, wnd, input_mask);          if (g_IM != NULL)
974          gc = XCreateGC(display, wnd, 0, NULL);          {
975                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
976                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
977    
978          if (ownbackstore)                  if ((g_IC != NULL)
979                  backstore = XCreatePixmap(display, wnd, width, height, depth);                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
980                            input_mask |= ic_input_mask;
981            }
982    
983            XSelectInput(g_display, g_wnd, input_mask);
984            XMapWindow(g_display, g_wnd);
985    
986            /* wait for VisibilityNotify */
987            do
988            {
989                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
990            }
991            while (xevent.type != VisibilityNotify);
992    
993            g_focused = False;
994            g_mouse_in_wnd = False;
995    
996            /* handle the WM_DELETE_WINDOW protocol */
997            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
998            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
999            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1000    
1001            /* create invisible 1x1 cursor to be used as null cursor */
1002            if (g_null_cursor == NULL)
1003                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1004    
         XMapWindow(display, wnd);  
1005          return True;          return True;
1006  }  }
1007    
1008  void  void
1009  ui_destroy_window()  ui_destroy_window(void)
1010    {
1011            if (g_IC != NULL)
1012                    XDestroyIC(g_IC);
1013    
1014            XDestroyWindow(g_display, g_wnd);
1015    }
1016    
1017    void
1018    xwin_toggle_fullscreen(void)
1019  {  {
1020          if (ownbackstore)          Pixmap contents = 0;
                 XFreePixmap(display, backstore);  
1021    
1022          XFreeGC(display, gc);          if (!g_ownbackstore)
1023          XDestroyWindow(display, wnd);          {
1024          XCloseDisplay(display);                  /* need to save contents of window */
1025          display = NULL;                  contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1026  }                  XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
   
 static uint8  
 xwin_translate_key(unsigned long key)  
 {  
         DEBUG(("KEY(code=0x%lx)\n", key));  
   
         if ((key > 8) && (key <= 0x60))  
                 return (key - 8);  
   
         switch (key)  
         {  
                 case 0x61:      /* home */  
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0xff;    /* real scancode is 5b */  
                 case 0x74:      /* right window key */  
                         return 0xff;    /* real scancode is 5c */  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
         }  
   
         return 0;  
 }  
   
 static uint16  
 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
         {  
                 case Button1:   /* left */  
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2:   /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
1027          }          }
1028    
1029          return 0;          ui_destroy_window();
1030            g_fullscreen = !g_fullscreen;
1031            ui_create_window();
1032    
1033            XDefineCursor(g_display, g_wnd, g_current_cursor);
1034    
1035            if (!g_ownbackstore)
1036            {
1037                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1038                    XFreePixmap(g_display, contents);
1039            }
1040  }  }
1041    
1042  static void  /* Process all events in Xlib queue
1043  xwin_process_events()     Returns 0 after user quit, 1 otherwise */
1044    static int
1045    xwin_process_events(void)
1046  {  {
1047          XEvent event;          XEvent xevent;
1048          uint8 scancode;          KeySym keysym;
1049          uint16 button;          uint16 button, flags;
1050          uint32 ev_time;          uint32 ev_time;
1051            key_translation tr;
1052            char str[256];
1053            Status status;
1054    
1055          if (display == NULL)          while (XPending(g_display) > 0)
                 return;  
   
         while (XCheckWindowEvent(display, wnd, ~0, &event))  
1056          {          {
1057                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
1058    
1059                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1060                    {
1061                            DEBUG_KBD(("Filtering event\n"));
1062                            continue;
1063                    }
1064    
1065                    flags = 0;
1066    
1067                  switch (event.type)                  switch (xevent.type)
1068                  {                  {
1069                            case ClientMessage:
1070                                    /* the window manager told us to quit */
1071                                    if ((xevent.xclient.message_type == g_protocol_atom)
1072                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1073                                            /* Quit */
1074                                            return 0;
1075                                    break;
1076    
1077                          case KeyPress:                          case KeyPress:
1078                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1079                                  if (scancode == 0)                                  if (g_IC != NULL)
1080                                            /* Multi_key compatible version */
1081                                    {
1082                                            XmbLookupString(g_IC,
1083                                                            &xevent.xkey, str, sizeof(str), &keysym,
1084                                                            &status);
1085                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1086                                            {
1087                                                    error("XmbLookupString failed with status 0x%x\n",
1088                                                          status);
1089                                                    break;
1090                                            }
1091                                    }
1092                                    else
1093                                    {
1094                                            /* Plain old XLookupString */
1095                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1096                                            XLookupString((XKeyEvent *) & xevent,
1097                                                          str, sizeof(str), &keysym, NULL);
1098                                    }
1099    
1100                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1101                                               get_ksname(keysym)));
1102    
1103                                    ev_time = time(NULL);
1104                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1105                                            break;
1106    
1107                                    tr = xkeymap_translate_key(keysym,
1108                                                               xevent.xkey.keycode, xevent.xkey.state);
1109    
1110                                    if (tr.scancode == 0)
1111                                          break;                                          break;
1112    
1113                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  save_remote_modifiers(tr.scancode);
1114                                                 scancode, 0);                                  ensure_remote_modifiers(ev_time, tr);
1115                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1116                                    restore_remote_modifiers(ev_time, tr.scancode);
1117    
1118                                  break;                                  break;
1119    
1120                          case KeyRelease:                          case KeyRelease:
1121                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1122                                  if (scancode == 0)                                  XLookupString((XKeyEvent *) & xevent, str,
1123                                                  sizeof(str), &keysym, NULL);
1124    
1125                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1126                                               get_ksname(keysym)));
1127    
1128                                    ev_time = time(NULL);
1129                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1130                                          break;                                          break;
1131    
1132                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
1133                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
1134    
1135                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xwin_translate_mouse(event.xbutton.button);  
                                 if (button == 0)  
1136                                          break;                                          break;
1137    
1138                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
1139                                  break;                                  break;
1140    
1141                            case ButtonPress:
1142                                    flags = MOUSE_FLAG_DOWN;
1143                                    /* fall through */
1144    
1145                          case ButtonRelease:                          case ButtonRelease:
1146                                  button = xwin_translate_mouse(event.xbutton.button);                                  g_last_gesturetime = xevent.xbutton.time;
1147                                    button = xkeymap_translate_button(xevent.xbutton.button);
1148                                  if (button == 0)                                  if (button == 0)
1149                                          break;                                          break;
1150    
1151                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
1152                                                 button,                                  if (xevent.xbutton.y < g_win_button_size)
1153                                                 event.xbutton.x,                                  {
1154                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
1155                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1156                                                    g_moving_wnd = False;
1157    
1158                                            /*  Check from right to left: */
1159    
1160                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
1161                                            {
1162                                                    /* The close button, continue */
1163                                                    ;
1164                                            }
1165                                            else if (xevent.xbutton.x >=
1166                                                     g_width - g_win_button_size * 2)
1167                                            {
1168                                                    /* The maximize/restore button. Do not send to
1169                                                       server.  It might be a good idea to change the
1170                                                       cursor or give some other visible indication
1171                                                       that rdesktop inhibited this click */
1172                                                    break;
1173                                            }
1174                                            else if (xevent.xbutton.x >=
1175                                                     g_width - g_win_button_size * 3)
1176                                            {
1177                                                    /* The minimize button. Iconify window. */
1178                                                    XIconifyWindow(g_display, g_wnd,
1179                                                                   DefaultScreen(g_display));
1180                                                    break;
1181                                            }
1182                                            else if (xevent.xbutton.x <= g_win_button_size)
1183                                            {
1184                                                    /* The system menu. Ignore. */
1185                                                    break;
1186                                            }
1187                                            else
1188                                            {
1189                                                    /* The title bar. */
1190                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1191                                                        && g_hide_decorations)
1192                                                    {
1193                                                            g_moving_wnd = True;
1194                                                            g_move_x_offset = xevent.xbutton.x;
1195                                                            g_move_y_offset = xevent.xbutton.y;
1196                                                    }
1197                                                    break;
1198    
1199                                            }
1200                                    }
1201    
1202                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1203                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1204                                  break;                                  break;
1205    
1206                          case MotionNotify:                          case MotionNotify:
1207                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_moving_wnd)
1208                                                 MOUSE_FLAG_MOVE,                                  {
1209                                                 event.xmotion.x,                                          XMoveWindow(g_display, g_wnd,
1210                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - g_move_x_offset,
1211                                                        xevent.xmotion.y_root - g_move_y_offset);
1212                                            break;
1213                                    }
1214    
1215                                    if (g_fullscreen && !g_focused)
1216                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1217                                                           CurrentTime);
1218                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1219                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1220                                    break;
1221    
1222                            case FocusIn:
1223                                    if (xevent.xfocus.mode == NotifyGrab)
1224                                            break;
1225                                    g_focused = True;
1226                                    reset_modifier_keys();
1227                                    if (g_grab_keyboard && g_mouse_in_wnd)
1228                                            XGrabKeyboard(g_display, g_wnd, True,
1229                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1230                                    break;
1231    
1232                            case FocusOut:
1233                                    if (xevent.xfocus.mode == NotifyUngrab)
1234                                            break;
1235                                    g_focused = False;
1236                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1237                                            XUngrabKeyboard(g_display, CurrentTime);
1238                                  break;                                  break;
1239    
1240                          case EnterNotify:                          case EnterNotify:
1241                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
1242                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
1243                                    g_mouse_in_wnd = True;
1244                                    if (g_fullscreen)
1245                                    {
1246                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1247                                                           CurrentTime);
1248                                            break;
1249                                    }
1250                                    if (g_focused)
1251                                            XGrabKeyboard(g_display, g_wnd, True,
1252                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1253                                  break;                                  break;
1254    
1255                          case LeaveNotify:                          case LeaveNotify:
1256                                  XUngrabKeyboard(display, CurrentTime);                                  /* we only register for this event when grab_keyboard */
1257                                    g_mouse_in_wnd = False;
1258                                    XUngrabKeyboard(g_display, CurrentTime);
1259                                  break;                                  break;
1260    
1261                          case Expose:                          case Expose:
1262                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1263                                            event.xexpose.x, event.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
1264                                            event.xexpose.width, event.xexpose.height,                                            xevent.xexpose.width,
1265                                            event.xexpose.x, event.xexpose.y);                                            xevent.xexpose.height,
1266                                              xevent.xexpose.x, xevent.xexpose.y);
1267                                    break;
1268    
1269                            case MappingNotify:
1270                                    /* Refresh keyboard mapping if it has changed. This is important for
1271                                       Xvnc, since it allocates keycodes dynamically */
1272                                    if (xevent.xmapping.request == MappingKeyboard
1273                                        || xevent.xmapping.request == MappingModifier)
1274                                            XRefreshKeyboardMapping(&xevent.xmapping);
1275    
1276                                    if (xevent.xmapping.request == MappingModifier)
1277                                    {
1278                                            XFreeModifiermap(g_mod_map);
1279                                            g_mod_map = XGetModifierMapping(g_display);
1280                                    }
1281                                    break;
1282    
1283                                    /* clipboard stuff */
1284                            case SelectionNotify:
1285                                    xclip_handle_SelectionNotify(&xevent.xselection);
1286                                    break;
1287                            case SelectionRequest:
1288                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1289                                    break;
1290                            case SelectionClear:
1291                                    xclip_handle_SelectionClear();
1292                                    break;
1293                            case PropertyNotify:
1294                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1295                                  break;                                  break;
1296                  }                  }
1297          }          }
1298            /* Keep going */
1299            return 1;
1300  }  }
1301    
1302  void  /* Returns 0 after user quit, 1 otherwise */
1303    int
1304  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1305  {  {
1306          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n;
1307          fd_set rfds;          fd_set rfds, wfds;
1308            struct timeval tv;
1309          XFlush(display);          BOOL s_timeout = False;
   
         FD_ZERO(&rfds);  
1310    
1311          while (True)          while (True)
1312          {          {
1313                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1314                    /* Process any events already waiting */
1315                    if (!xwin_process_events())
1316                            /* User quit */
1317                            return 0;
1318    
1319                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1320                    FD_ZERO(&wfds);
1321                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1322                  FD_SET(x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
1323    
1324    #ifdef WITH_RDPSND
1325                    /* FIXME: there should be an API for registering fds */
1326                    if (g_dsp_busy)
1327                    {
1328                            FD_SET(g_dsp_fd, &wfds);
1329                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
1330                    }
1331    #endif
1332                    /* default timeout */
1333                    tv.tv_sec = 60;
1334                    tv.tv_usec = 0;
1335    
1336                    /* add redirection handles */
1337                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1338    
1339                  switch (select(n, &rfds, NULL, NULL, NULL))                  n++;
1340    
1341                    switch (select(n, &rfds, &wfds, NULL, &tv))
1342                  {                  {
1343                          case -1:                          case -1:
1344                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1345    
1346                          case 0:                          case 0:
1347                                    /* TODO: if tv.tv_sec just times out
1348                                     * we will segfault.
1349                                     * FIXME:
1350                                     */
1351                                    //s_timeout = True;
1352                                    //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1353                                  continue;                                  continue;
1354                  }                  }
1355    
1356                  if (FD_ISSET(x_socket, &rfds))                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
                         xwin_process_events();  
1357    
1358                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1359                          return;                          return 1;
1360    
1361    #ifdef WITH_RDPSND
1362                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1363                            wave_out_play();
1364    #endif
1365          }          }
1366  }  }
1367    
1368  void  void
1369  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1370  {  {
1371          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1372  }  }
1373    
1374  HBITMAP  HBITMAP
1375  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1376  {  {
1377          XImage *image;          XImage *image;
1378          Pixmap bitmap;          Pixmap bitmap;
1379          uint8 *tdata;          uint8 *tdata;
1380            int bitmap_pad;
1381    
1382          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_server_bpp == 8)
1383          bitmap = XCreatePixmap(display, wnd, width, height, depth);          {
1384          image = XCreateImage(display, visual, depth, ZPixmap,                  bitmap_pad = 8;
1385                               0, tdata, width, height, 8, 0);          }
1386            else
1387            {
1388                    bitmap_pad = g_bpp;
1389    
1390          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);                  if (g_bpp == 24)
1391                            bitmap_pad = 32;
1392            }
1393    
1394            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1395            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1396            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1397                                 (char *) tdata, width, height, bitmap_pad, 0);
1398    
1399            XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1400    
1401          XFree(image);          XFree(image);
1402          if (!owncolmap)          if (tdata != data)
1403                  xfree(tdata);                  xfree(tdata);
1404          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1405  }  }
1406    
1407  void  void
1408  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 int width, int height, uint8 *data)  
1409  {  {
1410          XImage *image;          XImage *image;
1411          uint8 *tdata;          uint8 *tdata;
1412            int bitmap_pad;
1413    
1414            if (g_server_bpp == 8)
1415            {
1416                    bitmap_pad = 8;
1417            }
1418            else
1419            {
1420                    bitmap_pad = g_bpp;
1421    
1422          tdata = (owncolmap ? data : translate_image(width, height, data));                  if (g_bpp == 24)
1423          image = XCreateImage(display, visual, depth, ZPixmap,                          bitmap_pad = 32;
1424                               0, tdata, width, height, 8, 0);          }
1425    
1426            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1427            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1428                                 (char *) tdata, width, height, bitmap_pad, 0);
1429    
1430          if (ownbackstore)          if (g_ownbackstore)
1431          {          {
1432                  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);
1433                  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);
1434          }          }
1435          else          else
1436          {          {
1437                  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);
1438          }          }
1439    
1440          XFree(image);          XFree(image);
1441          if (!owncolmap)          if (tdata != data)
1442                  xfree(tdata);                  xfree(tdata);
1443  }  }
1444    
1445  void  void
1446  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1447  {  {
1448          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1449  }  }
1450    
1451  HGLYPH  HGLYPH
1452  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1453  {  {
1454          XImage *image;          XImage *image;
1455          Pixmap bitmap;          Pixmap bitmap;
# Line 566  ui_create_glyph(int width, int height, u Line 1458  ui_create_glyph(int width, int height, u
1458    
1459          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1460    
1461          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1462          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(g_display, bitmap, 0, NULL);
1463    
1464          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1465                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1466          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1467          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1468          XInitImage(image);          XInitImage(image);
1469    
1470          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1471    
1472          XFree(image);          XFree(image);
1473          XFreeGC(display, gc);          XFreeGC(g_display, gc);
1474          return (HGLYPH)bitmap;          return (HGLYPH) bitmap;
1475  }  }
1476    
1477  void  void
1478  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1479  {  {
1480          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1481  }  }
1482    
1483  HCURSOR  HCURSOR
1484  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1485                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1486  {  {
1487          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1488          XColor bg, fg;          XColor bg, fg;
# Line 604  ui_create_cursor(unsigned int x, unsigne Line 1496  ui_create_cursor(unsigned int x, unsigne
1496          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1497          offset = scanline * height;          offset = scanline * height;
1498    
1499          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1500          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1501    
1502          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1503          memset(mask, 0, offset);          memset(mask, 0, offset);
1504    
1505          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 647  ui_create_cursor(unsigned int x, unsigne Line 1539  ui_create_cursor(unsigned int x, unsigne
1539    
1540          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1541          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1542            
1543          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
1544                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1545                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1546    
1547          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1548          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
1549          xfree(mask);          xfree(mask);
1550          xfree(cursor);          xfree(cursor);
1551          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1552  }  }
1553    
1554  void  void
1555  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1556  {  {
1557          XDefineCursor(display, wnd, (Cursor)cursor);          g_current_cursor = (Cursor) cursor;
1558            XDefineCursor(g_display, g_wnd, g_current_cursor);
1559  }  }
1560    
1561  void  void
1562  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1563  {  {
1564          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(g_display, (Cursor) cursor);
1565    }
1566    
1567    void
1568    ui_set_null_cursor(void)
1569    {
1570            ui_set_cursor(g_null_cursor);
1571  }  }
1572    
1573  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 676  ui_destroy_cursor(HCURSOR cursor) Line 1576  ui_destroy_cursor(HCURSOR cursor)
1576                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1577                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1578    
1579    
1580  HCOLOURMAP  HCOLOURMAP
1581  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
1582  {  {
1583          COLOURENTRY *entry;          COLOURENTRY *entry;
1584          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1585            if (!g_owncolmap)
         if (owncolmap)  
1586          {          {
1587                  XColor *xcolours, *xentry;                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1588                  Colormap map;                  XColor xentry;
1589                    XColor xc_cache[256];
1590                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  uint32 colour;
1591                    int colLookup = 256;
1592                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1593                  {                  {
1594                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1595                          xentry = &xcolours[i];                          MAKE_XCOLOR(&xentry, entry);
1596                          xentry->pixel = i;  
1597                          MAKE_XCOLOR(xentry, entry);                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1598                  }                          {
1599                                    /* Allocation failed, find closest match. */
1600                                    int j = 256;
1601                                    int nMinDist = 3 * 256 * 256;
1602                                    long nDist = nMinDist;
1603    
1604                  map = XCreateColormap(display, wnd, visual, AllocAll);                                  /* only get the colors once */
1605                  XStoreColors(display, map, xcolours, ncolours);                                  while (colLookup--)
1606                                    {
1607                                            xc_cache[colLookup].pixel = colLookup;
1608                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1609                                                    xc_cache[colLookup].blue = 0;
1610                                            xc_cache[colLookup].flags = 0;
1611                                            XQueryColor(g_display,
1612                                                        DefaultColormap(g_display,
1613                                                                        DefaultScreen(g_display)),
1614                                                        &xc_cache[colLookup]);
1615                                    }
1616                                    colLookup = 0;
1617    
1618                  xfree(xcolours);                                  /* approximate the pixel */
1619                  return (HCOLOURMAP)map;                                  while (j--)
1620                                    {
1621                                            if (xc_cache[j].flags)
1622                                            {
1623                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1624                                                             (long) (xentry.red >> 8)) *
1625                                                            ((long) (xc_cache[j].red >> 8) -
1626                                                             (long) (xentry.red >> 8)) +
1627                                                            ((long) (xc_cache[j].green >> 8) -
1628                                                             (long) (xentry.green >> 8)) *
1629                                                            ((long) (xc_cache[j].green >> 8) -
1630                                                             (long) (xentry.green >> 8)) +
1631                                                            ((long) (xc_cache[j].blue >> 8) -
1632                                                             (long) (xentry.blue >> 8)) *
1633                                                            ((long) (xc_cache[j].blue >> 8) -
1634                                                             (long) (xentry.blue >> 8));
1635                                            }
1636                                            if (nDist < nMinDist)
1637                                            {
1638                                                    nMinDist = nDist;
1639                                                    xentry.pixel = j;
1640                                            }
1641                                    }
1642                            }
1643                            colour = xentry.pixel;
1644    
1645                            /* update our cache */
1646                            if (xentry.pixel < 256)
1647                            {
1648                                    xc_cache[xentry.pixel].red = xentry.red;
1649                                    xc_cache[xentry.pixel].green = xentry.green;
1650                                    xc_cache[xentry.pixel].blue = xentry.blue;
1651    
1652                            }
1653    
1654                            map[i] = colour;
1655                    }
1656                    return map;
1657          }          }
1658          else          else
1659          {          {
1660                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  XColor *xcolours, *xentry;
1661                  XColor xentry;                  Colormap map;
                 uint32 colour;  
1662    
1663                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1664                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1665                  {                  {
1666                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1667                          MAKE_XCOLOR(&xentry, entry);                          xentry = &xcolours[i];
1668                            xentry->pixel = i;
1669                          if (XAllocColor(display, xcolmap, &xentry) != 0)                          MAKE_XCOLOR(xentry, entry);
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
1670                  }                  }
1671    
1672                  return map;                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1673                    XStoreColors(g_display, map, xcolours, ncolours);
1674    
1675                    xfree(xcolours);
1676                    return (HCOLOURMAP) map;
1677          }          }
1678  }  }
1679    
1680  void  void
1681  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1682  {  {
1683          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1684                  xfree(map);                  xfree(map);
1685            else
1686                    XFreeColormap(g_display, (Colormap) map);
1687  }  }
1688    
1689  void  void
1690  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1691  {  {
1692          if (owncolmap)          if (!g_owncolmap)
1693                  XSetWindowColormap(display, wnd, (Colormap)map);          {
1694                    if (g_colmap)
1695                            xfree(g_colmap);
1696    
1697                    g_colmap = (uint32 *) map;
1698            }
1699          else          else
1700                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1701  }  }
1702    
1703  void  void
# Line 753  ui_set_clip(int x, int y, int cx, int cy Line 1709  ui_set_clip(int x, int y, int cx, int cy
1709          rect.y = y;          rect.y = y;
1710          rect.width = cx;          rect.width = cx;
1711          rect.height = cy;          rect.height = cy;
1712          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1713  }  }
1714    
1715  void  void
1716  ui_reset_clip()  ui_reset_clip(void)
1717  {  {
1718          XRectangle rect;          XRectangle rect;
1719    
1720          rect.x = 0;          rect.x = 0;
1721          rect.y = 0;          rect.y = 0;
1722          rect.width = width;          rect.width = g_width;
1723          rect.height = height;          rect.height = g_height;
1724          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1725  }  }
1726    
1727  void  void
1728  ui_bell()  ui_bell(void)
1729  {  {
1730          XBell(display, 0);          XBell(g_display, 0);
1731  }  }
1732    
1733  void  void
# Line 783  ui_destblt(uint8 opcode, Line 1739  ui_destblt(uint8 opcode,
1739          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1740  }  }
1741    
1742    static uint8 hatch_patterns[] = {
1743            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1744            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1745            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1746            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1747            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1748            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1749    };
1750    
1751  void  void
1752  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1753            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1754            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1755  {  {
1756          Pixmap fill;          Pixmap fill;
1757            uint8 i, ipattern[8];
1758    
1759          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1760    
# Line 799  ui_patblt(uint8 opcode, Line 1765  ui_patblt(uint8 opcode,
1765                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1766                          break;                          break;
1767    
1768                    case 2: /* Hatch */
1769                            fill = (Pixmap) ui_create_glyph(8, 8,
1770                                                            hatch_patterns + brush->pattern[0] * 8);
1771                            SET_FOREGROUND(fgcolour);
1772                            SET_BACKGROUND(bgcolour);
1773                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1774                            XSetStipple(g_display, g_gc, fill);
1775                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1776                            FILL_RECTANGLE(x, y, cx, cy);
1777                            XSetFillStyle(g_display, g_gc, FillSolid);
1778                            XSetTSOrigin(g_display, g_gc, 0, 0);
1779                            ui_destroy_glyph((HGLYPH) fill);
1780                            break;
1781    
1782                  case 3: /* Pattern */                  case 3: /* Pattern */
1783                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
1784                                    ipattern[7 - i] = brush->pattern[i];
1785                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1786    
1787                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1788                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
1789                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1790                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
1791                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1792    
1793                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1794    
1795                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
1796                          ui_destroy_glyph((HGLYPH)fill);                          XSetTSOrigin(g_display, g_gc, 0, 0);
1797                            ui_destroy_glyph((HGLYPH) fill);
1798                          break;                          break;
1799    
1800                  default:                  default:
# Line 827  ui_screenblt(uint8 opcode, Line 1810  ui_screenblt(uint8 opcode,
1810               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1811  {  {
1812          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1813          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
1814          if (ownbackstore)          {
1815                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1816                            cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1817            }
1818            else
1819            {
1820                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1821            }
1822          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1823  }  }
1824    
# Line 840  ui_memblt(uint8 opcode, Line 1828  ui_memblt(uint8 opcode,
1828            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1829  {  {
1830          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1831          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);
1832          if (ownbackstore)          if (g_ownbackstore)
1833                  XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1834          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1835  }  }
1836    
# Line 851  void Line 1838  void
1838  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1839            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1840            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1841            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1842  {  {
1843          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1844             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 860  ui_triblt(uint8 opcode, Line 1847  ui_triblt(uint8 opcode,
1847          {          {
1848                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1849                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1850                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1851                          break;                          break;
1852    
1853                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1854                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1855                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1856                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1857                          break;                          break;
1858    
1859                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1860                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1861                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1862                          break;                          break;
1863    
1864                  default:                  default:
# Line 887  ui_triblt(uint8 opcode, Line 1870  ui_triblt(uint8 opcode,
1870  void  void
1871  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1872          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1873          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1874  {  {
1875          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1876          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
1877          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1878          if (ownbackstore)          if (g_ownbackstore)
1879                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1880          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1881  }  }
1882    
# Line 906  ui_rect( Line 1889  ui_rect(
1889          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1890  }  }
1891    
1892    /* warning, this function only draws on wnd or backstore, not both */
1893  void  void
1894  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1895                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1896                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1897                int fgcolour)                int bgcolour, int fgcolour)
1898  {  {
1899          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1900          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1901    
1902          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
1903                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1904          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
1905          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
1906    
1907          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1908    
1909          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
1910    }
1911    
1912    #define DO_GLYPH(ttext,idx) \
1913    {\
1914      glyph = cache_get_font (font, ttext[idx]);\
1915      if (!(flags & TEXT2_IMPLICIT_X))\
1916      {\
1917        xyoffset = ttext[++idx];\
1918        if ((xyoffset & 0x80))\
1919        {\
1920          if (flags & TEXT2_VERTICAL)\
1921            y += ttext[idx+1] | (ttext[idx+2] << 8);\
1922          else\
1923            x += ttext[idx+1] | (ttext[idx+2] << 8);\
1924          idx += 2;\
1925        }\
1926        else\
1927        {\
1928          if (flags & TEXT2_VERTICAL)\
1929            y += xyoffset;\
1930          else\
1931            x += xyoffset;\
1932        }\
1933      }\
1934      if (glyph != NULL)\
1935      {\
1936        x1 = x + glyph->offset;\
1937        y1 = y + glyph->baseline;\
1938        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
1939        XSetTSOrigin(g_display, g_gc, x1, y1);\
1940        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
1941        if (flags & TEXT2_IMPLICIT_X)\
1942          x += glyph->width;\
1943      }\
1944  }  }
1945    
1946  void  void
1947  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1948               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1949               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1950               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1951  {  {
1952          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1953          int i, offset;          int i, j, xyoffset, x1, y1;
1954            DATABLOB *entry;
1955    
1956          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
1957    
1958            /* Sometimes, the boxcx value is something really large, like
1959               32691. This makes XCopyArea fail with Xvnc. The code below
1960               is a quick fix. */
1961            if (boxx + boxcx > g_width)
1962                    boxcx = g_width - boxx;
1963    
1964          if (boxcx > 1)          if (boxcx > 1)
1965          {          {
1966                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1967          }          }
1968          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1969          {          {
1970                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1971          }          }
1972    
1973            SET_FOREGROUND(fgcolour);
1974            SET_BACKGROUND(bgcolour);
1975            XSetFillStyle(g_display, g_gc, FillStippled);
1976    
1977          /* Paint text, character by character */          /* Paint text, character by character */
1978          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1979          {          {
1980                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
1981                  {                  {
1982                          offset = text[++i];                          case 0xff:
1983                          if (offset & 0x80)                                  if (i + 2 < length)
1984                                  offset = ((offset & 0x7f) << 8) | text[++i];                                          cache_put_text(text[i + 1], text, text[i + 2]);
1985                                    else
1986                                    {
1987                                            error("this shouldn't be happening\n");
1988                                            exit(1);
1989                                    }
1990                                    /* this will move pointer from start to first character after FF command */
1991                                    length -= i + 3;
1992                                    text = &(text[i + 3]);
1993                                    i = 0;
1994                                    break;
1995    
1996                            case 0xfe:
1997                                    entry = cache_get_text(text[i + 1]);
1998                                    if (entry != NULL)
1999                                    {
2000                                            if ((((uint8 *) (entry->data))[1] ==
2001                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
2002                                            {
2003                                                    if (flags & TEXT2_VERTICAL)
2004                                                            y += text[i + 2];
2005                                                    else
2006                                                            x += text[i + 2];
2007                                            }
2008                                            for (j = 0; j < entry->size; j++)
2009                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
2010                                    }
2011                                    if (i + 2 < length)
2012                                            i += 3;
2013                                    else
2014                                            i += 2;
2015                                    length -= i;
2016                                    /* this will move pointer from start to first character after FE command */
2017                                    text = &(text[i]);
2018                                    i = 0;
2019                                    break;
2020    
2021                          if (flags & TEXT2_VERTICAL)                          default:
2022                                  y += offset;                                  DO_GLYPH(text, i);
2023                          else                                  i++;
2024                                  x += offset;                                  break;
2025                  }                  }
2026            }
2027    
2028                  if (glyph != NULL)          XSetFillStyle(g_display, g_gc, FillSolid);
                 {  
                         ui_draw_glyph(mixmode, x + (short) glyph->offset,  
                                       y + (short) glyph->baseline,  
                                       glyph->width, glyph->height,  
                                       glyph->pixmap, 0, 0,  
                                       bgcolour, fgcolour);  
2029    
2030                          if (flags & TEXT2_IMPLICIT_X)          if (g_ownbackstore)
2031                                  x += glyph->width;          {
2032                  }                  if (boxcx > 1)
2033                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2034                                      boxy, boxcx, boxcy, boxx, boxy);
2035                    else
2036                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2037                                      clipy, clipcx, clipcy, clipx, clipy);
2038          }          }
2039  }  }
2040    
# Line 982  ui_desktop_save(uint32 offset, int x, in Line 2044  ui_desktop_save(uint32 offset, int x, in
2044          Pixmap pix;          Pixmap pix;
2045          XImage *image;          XImage *image;
2046    
2047          if (ownbackstore)          if (g_ownbackstore)
2048          {          {
2049                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
2050          }          }
2051          else          else
2052          {          {
2053                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2054                  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);
2055                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2056                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
2057          }          }
2058    
2059          offset *= bpp/8;          offset *= g_bpp / 8;
2060          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
                           bpp/8, image->data);  
2061    
2062          XDestroyImage(image);          XDestroyImage(image);
2063  }  }
# Line 1009  ui_desktop_restore(uint32 offset, int x, Line 2068  ui_desktop_restore(uint32 offset, int x,
2068          XImage *image;          XImage *image;
2069          uint8 *data;          uint8 *data;
2070    
2071          offset *= bpp/8;          offset *= g_bpp / 8;
2072          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2073          if (data == NULL)          if (data == NULL)
2074                  return;                  return;
2075    
2076          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2077                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * bpp/8);  
2078    
2079          if (ownbackstore)          if (g_ownbackstore)
2080          {          {
2081                  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);
2082                  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);
2083          }          }
2084          else          else
2085          {          {
2086                  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);
2087          }          }
2088    
2089          XFree(image);          XFree(image);

Legend:
Removed from v.35  
changed lines
  Added in v.644

  ViewVC Help
Powered by ViewVC 1.1.26