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

Legend:
Removed from v.36  
changed lines
  Added in v.679

  ViewVC Help
Powered by ViewVC 1.1.26