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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26