/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

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

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

Legend:
Removed from v.30  
changed lines
  Added in v.800

  ViewVC Help
Powered by ViewVC 1.1.26