/[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 64 by astrand, Thu Jul 18 16:38:31 2002 UTC revision 517 by matthewc, Tue Oct 28 03:30:51 2003 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-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
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
 #include <X11/XKBlib.h>  
23  #include <time.h>  #include <time.h>
24  #include <errno.h>  #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    #include "xproto.h"
27    
28  extern char keymapname[16];  extern int g_width;
29  extern int keylayout;  extern int g_height;
30  extern int width;  extern BOOL g_sendmotion;
31  extern int height;  extern BOOL g_fullscreen;
32  extern BOOL sendmotion;  extern BOOL g_grab_keyboard;
33  extern BOOL fullscreen;  extern BOOL g_hide_decorations;
34    extern char g_title[];
35  Display *display;  extern int g_server_bpp;
36  XkbDescPtr xkb;  extern int g_win_button_size;
37  static int x_socket;  
38  static Window wnd;  Display *g_display;
39  static GC gc;  Time g_last_gesturetime;
40  static Visual *visual;  static int g_x_socket;
41  static int depth;  static Screen *g_screen;
42  static int bpp;  Window g_wnd;
43    BOOL g_enable_compose = False;
44    static GC g_gc;
45    static Visual *g_visual;
46    static int g_depth;
47    static int g_bpp;
48    static XIM g_IM;
49    static XIC g_IC;
50    static XModifierKeymap *g_mod_map;
51    static Cursor g_current_cursor;
52    static HCURSOR g_null_cursor;
53    static Atom g_protocol_atom, g_kill_atom;
54    static BOOL g_focused;
55    static BOOL g_mouse_in_wnd;
56    
57  /* endianness */  /* endianness */
58  static BOOL host_be;  static BOOL g_host_be;
59  static BOOL xserver_be;  static BOOL g_xserver_be;
60    
61  /* software backing store */  /* software backing store */
62  static BOOL ownbackstore;  static BOOL g_ownbackstore;
63  static Pixmap backstore;  static Pixmap g_backstore;
64    
65    /* Moving in single app mode */
66    static BOOL g_moving_wnd;
67    static int g_move_x_offset = 0;
68    static int g_move_y_offset = 0;
69    
70    #ifdef WITH_RDPSND
71    extern int g_dsp_fd;
72    extern BOOL g_dsp_busy;
73    extern BOOL g_rdpsnd;
74    #endif
75    
76    /* MWM decorations */
77    #define MWM_HINTS_DECORATIONS   (1L << 1)
78    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
79    typedef struct
80    {
81            uint32 flags;
82            uint32 functions;
83            uint32 decorations;
84            sint32 inputMode;
85            uint32 status;
86    }
87    PropMotifWmHints;
88    
89    typedef struct
90    {
91            uint32 red;
92            uint32 green;
93            uint32 blue;
94    }
95    PixelColour;
96    
 /* needed to keep track of the modifiers */  
 static unsigned int numlock_modifier_mask = 0;  
 static unsigned int key_down_state = 0;  
   
   
 #define DShift1Mask   (1<<0)  
 #define DLockMask     (1<<1)  
 #define DControl1Mask (1<<2)  
 #define DMod1Mask     (1<<3)  
 #define DMod2Mask     (1<<4)  
 #define DMod3Mask     (1<<5)  
 #define DMod4Mask     (1<<6)  
 #define DMod5Mask     (1<<7)  
 #define DShift2Mask   (1<<8)  
 #define DControl2Mask (1<<9)  
 #define DNumLockMask  (1<<10)  
97    
98  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
99  { \  { \
100          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
101          if (ownbackstore) \          if (g_ownbackstore) \
102                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
103    }
104    
105    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
106    { \
107            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
108  }  }
109    
110  /* colour maps */  /* colour maps */
111  static BOOL owncolmap;  BOOL g_owncolmap = False;
112  static Colormap xcolmap;  static Colormap g_xcolmap;
113  static uint32 white;  static uint32 *g_colmap = NULL;
114  static uint32 *colmap;  
115    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : translate_colour(g_colmap[col]) )
116  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
117  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
 #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  
118    
119  static int rop2_map[] = {  static int rop2_map[] = {
120          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 102  static int rop2_map[] = { Line 135  static int rop2_map[] = {
135          GXset                   /* 1 */          GXset                   /* 1 */
136  };  };
137    
138  #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]); }
139  #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); }
140    
141    static void
142    mwm_hide_decorations(void)
143    {
144            PropMotifWmHints motif_hints;
145            Atom hintsatom;
146    
147            /* setup the property */
148            motif_hints.flags = MWM_HINTS_DECORATIONS;
149            motif_hints.decorations = 0;
150    
151            /* get the atom for the property */
152            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
153            if (!hintsatom)
154            {
155                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
156                    return;
157            }
158    
159            XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
160                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
161    }
162    
163    static PixelColour
164    split_colour15(uint32 colour)
165    {
166            PixelColour rv;
167            rv.red = (colour & 0x7c00) >> 10;
168            rv.red = (rv.red * 0xff) / 0x1f;
169            rv.green = (colour & 0x03e0) >> 5;
170            rv.green = (rv.green * 0xff) / 0x1f;
171            rv.blue = (colour & 0x1f);
172            rv.blue = (rv.blue * 0xff) / 0x1f;
173            return rv;
174    }
175    
176    static PixelColour
177    split_colour16(uint32 colour)
178    {
179            PixelColour rv;
180            rv.red = (colour & 0xf800) >> 11;
181            rv.red = (rv.red * 0xff) / 0x1f;
182            rv.green = (colour & 0x07e0) >> 5;
183            rv.green = (rv.green * 0xff) / 0x3f;
184            rv.blue = (colour & 0x001f);
185            rv.blue = (rv.blue * 0xff) / 0x1f;
186            return rv;
187    }
188    
189    static PixelColour
190    split_colour24(uint32 colour)
191    {
192            PixelColour rv;
193            rv.blue = (colour & 0xff0000) >> 16;
194            rv.green = (colour & 0xff00) >> 8;
195            rv.red = (colour & 0xff);
196            return rv;
197    }
198    
199    static uint32
200    make_colour16(PixelColour pc)
201    {
202            pc.red = (pc.red * 0x1f) / 0xff;
203            pc.green = (pc.green * 0x3f) / 0xff;
204            pc.blue = (pc.blue * 0x1f) / 0xff;
205            return (pc.red << 11) | (pc.green << 5) | pc.blue;
206    }
207    
208    static uint32
209    make_colour24(PixelColour pc)
210    {
211            if (g_xserver_be)
212            {
213                    return pc.red | (pc.green << 8) | (pc.blue << 16);
214            }
215            else
216            {
217                    return (pc.red << 16) | (pc.green << 8) | pc.blue;
218            }
219    }
220    
221  void xwin_get_numlock_mask();  static uint32
222  void xwin_mod_update(uint32 state, uint32 ev_time);  make_colour32(PixelColour pc)
223  void xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode);  {
224  void xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode);          if (g_xserver_be)
225            {
226                    return pc.red | (pc.green << 8) | (pc.blue << 16);
227            }
228            else
229            {
230                    return (pc.red << 16) | (pc.green << 8) | pc.blue;
231            }
232    }
233    
234    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
235    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
236    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
237                            x = (x << 16) | (x >> 16); }
238    
239    static uint32
240    translate_colour(uint32 colour)
241    {
242            switch (g_server_bpp)
243            {
244                    case 15:
245                            switch (g_bpp)
246                            {
247                                    case 16:
248                                            colour = make_colour16(split_colour15(colour));
249                                            break;
250                                    case 24:
251                                            colour = make_colour24(split_colour15(colour));
252                                            break;
253                                    case 32:
254                                            colour = make_colour32(split_colour15(colour));
255                                            break;
256                            }
257                            break;
258                    case 16:
259                            switch (g_bpp)
260                            {
261                                    case 16:
262                                            break;
263                                    case 24:
264                                            colour = make_colour24(split_colour16(colour));
265                                            break;
266                                    case 32:
267                                            colour = make_colour32(split_colour16(colour));
268                                            break;
269                            }
270                            break;
271                    case 24:
272                            switch (g_bpp)
273                            {
274                                    case 16:
275                                            colour = make_colour16(split_colour24(colour));
276                                            break;
277                                    case 24:
278                                            break;
279                                    case 32:
280                                            colour = make_colour32(split_colour24(colour));
281                                            break;
282                            }
283                            break;
284            }
285            return colour;
286    }
287    
288  static void  static void
289  translate8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(uint8 * data, uint8 * out, uint8 * end)
290  {  {
291          while (out < end)          while (out < end)
292                  *(out++) = (uint8) colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
293  }  }
294    
295  static void  static void
296  translate16(uint8 * data, uint16 * out, uint16 * end)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
297  {  {
298          while (out < end)          while (out < end)
299                  *(out++) = (uint16) colmap[*(data++)];                  *(out++) = (uint16) g_colmap[*(data++)];
300  }  }
301    
302  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
303  static void  static void
304  translate24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
305  {  {
306          uint32 value;          uint32 value;
307    
308          while (out < end)          while (out < end)
309          {          {
310                  value = colmap[*(data++)];                  value = g_colmap[*(data++)];
311                  *(out++) = value;                  *(out++) = value;
312                  *(out++) = value >> 8;                  *(out++) = value >> 8;
313                  *(out++) = value >> 16;                  *(out++) = value >> 16;
# Line 140  translate24(uint8 * data, uint8 * out, u Line 315  translate24(uint8 * data, uint8 * out, u
315  }  }
316    
317  static void  static void
318  translate32(uint8 * data, uint32 * out, uint32 * end)  translate8to32(uint8 * data, uint32 * out, uint32 * end)
319  {  {
320          while (out < end)          while (out < end)
321                  *(out++) = colmap[*(data++)];                  *(out++) = g_colmap[*(data++)];
322  }  }
323    
324  static uint8 *  /* todo the remaining translate function might need some big endian check ?? */
325  translate_image(int width, int height, uint8 * data)  
326    static void
327    translate15to16(uint16 * data, uint8 * out, uint8 * end)
328  {  {
329          int size = width * height * bpp / 8;          uint16 pixel;
330          uint8 *out = xmalloc(size);          uint16 value;
         uint8 *end = out + size;  
331    
332          switch (bpp)          while (out < end)
333          {          {
334                  case 8:                  pixel = *(data++);
                         translate8(data, out, end);  
                         break;  
335    
336                  case 16:                  if (g_host_be)
337                          translate16(data, (uint16 *) out, (uint16 *) end);                  {
338                          break;                  BSWAP16(pixel)}
339    
340                  case 24:                  value = make_colour16(split_colour15(pixel));
                         translate24(data, out, end);  
                         break;  
341    
342                  case 32:                  if (g_xserver_be)
343                          translate32(data, (uint32 *) out, (uint32 *) end);                  {
344                          break;                          *(out++) = value >> 8;
345                            *(out++) = value;
346                    }
347                    else
348                    {
349                            *(out++) = value;
350                            *(out++) = value >> 8;
351                    }
352          }          }
353    }
354    
355          return out;  static void
356    translate15to24(uint16 * data, uint8 * out, uint8 * end)
357    {
358            uint32 value;
359            uint16 pixel;
360    
361            while (out < end)
362            {
363                    pixel = *(data++);
364    
365                    if (g_host_be)
366                    {
367                    BSWAP16(pixel)}
368    
369                    value = make_colour24(split_colour15(pixel));
370                    if (g_xserver_be)
371                    {
372                            *(out++) = value >> 16;
373                            *(out++) = value >> 8;
374                            *(out++) = value;
375                    }
376                    else
377                    {
378                            *(out++) = value;
379                            *(out++) = value >> 8;
380                            *(out++) = value >> 16;
381                    }
382            }
383  }  }
384    
385  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  static void
386  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  translate15to32(uint16 * data, uint8 * out, uint8 * end)
387  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  {
388                          x = (x << 16) | (x >> 16); }          uint16 pixel;
389            uint32 value;
390    
391  static uint32          while (out < end)
392  translate_colour(uint32 colour)          {
393                    pixel = *(data++);
394    
395                    if (g_host_be)
396                    {
397                            BSWAP16(pixel);
398                    }
399    
400                    value = make_colour32(split_colour15(pixel));
401    
402                    if (g_xserver_be)
403                    {
404                            *(out++) = value >> 24;
405                            *(out++) = value >> 16;
406                            *(out++) = value >> 8;
407                            *(out++) = value;
408                    }
409                    else
410                    {
411                            *(out++) = value;
412                            *(out++) = value >> 8;
413                            *(out++) = value >> 16;
414                            *(out++) = value >> 24;
415                    }
416            }
417    }
418    
419    static void
420    translate16to16(uint16 * data, uint16 * out, uint16 * end)
421  {  {
422          switch (bpp)          uint16 value;
423    
424            if (g_xserver_be)
425          {          {
426                  case 16:                  while (out < end)
427                          if (host_be != xserver_be)                  {
428                                  BSWAP16(colour);                          value = *data;
429                          break;                          BSWAP16(value);
430                            *out = value;
431                            data++;
432                            out++;
433                    }
434    
435                  case 24:          }
436                          if (xserver_be)          else
437                                  BSWAP24(colour);          {
438                          break;                  while (out < end)
439                    {
440                            *out = *data;
441                            out++;
442                            data++;
443                    }
444            }
445    }
446    
447                  case 32:  
448                          if (host_be != xserver_be)  static void
449                                  BSWAP32(colour);  translate16to24(uint16 * data, uint8 * out, uint8 * end)
450                          break;  {
451            uint32 value;
452            uint16 pixel;
453    
454            while (out < end)
455            {
456                    pixel = *(data++);
457    
458                    if (g_host_be)
459                    {
460                    BSWAP16(pixel)}
461    
462                    value = make_colour24(split_colour16(pixel));
463    
464                    if (g_xserver_be)
465                    {
466                            *(out++) = value >> 16;
467                            *(out++) = value >> 8;
468                            *(out++) = value;
469                    }
470                    else
471                    {
472                            *(out++) = value;
473                            *(out++) = value >> 8;
474                            *(out++) = value >> 16;
475                    }
476          }          }
477    }
478    
479          return colour;  static void
480    translate16to32(uint16 * data, uint8 * out, uint8 * end)
481    {
482            uint16 pixel;
483            uint32 value;
484    
485            while (out < end)
486            {
487                    pixel = *(data++);
488    
489                    if (g_host_be)
490                    {
491                    BSWAP16(pixel)}
492    
493                    value = make_colour32(split_colour16(pixel));
494    
495                    if (g_xserver_be)
496                    {
497                            *(out++) = value >> 24;
498                            *(out++) = value >> 16;
499                            *(out++) = value >> 8;
500                            *(out++) = value;
501                    }
502                    else
503                    {
504                            *(out++) = value;
505                            *(out++) = value >> 8;
506                            *(out++) = value >> 16;
507                            *(out++) = value >> 24;
508                    }
509            }
510  }  }
511    
512  BOOL  static void
513  ui_create_window(char *title)  translate24to16(uint8 * data, uint8 * out, uint8 * end)
514  {  {
515          XSetWindowAttributes attribs;          uint32 pixel = 0;
516          XClassHint *classhints;          uint16 value;
517          XSizeHints *sizehints;          while (out < end)
518          unsigned long input_mask;          {
519          XPixmapFormatValues *pfm;                  pixel = *(data++) << 16;
520          Screen *screen;                  pixel |= *(data++) << 8;
521          uint16 test;                  pixel |= *(data++);
         int i;  
522    
523          int xkb_minor, xkb_major;                  value = (uint16) make_colour16(split_colour24(pixel));
         int xkb_event, xkb_error, xkb_reason;  
524    
525          /* compare compiletime libs with runtime libs. */                  if (g_xserver_be)
526          xkb_major = XkbMajorVersion;                  {
527          xkb_minor = XkbMinorVersion;                          *(out++) = value >> 8;
528          if (XkbLibraryVersion(&xkb_major, &xkb_minor) == False)                          *(out++) = value;
529                    }
530                    else
531                    {
532                            *(out++) = value;
533                            *(out++) = value >> 8;
534                    }
535            }
536    }
537    
538    static void
539    translate24to24(uint8 * data, uint8 * out, uint8 * end)
540    {
541            while (out < end)
542          {          {
543                  error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");                  *(out++) = (*(data++));
                 return False;  
544          }          }
545    }
546    
547    static void
548    translate24to32(uint8 * data, uint8 * out, uint8 * end)
549    {
550            while (out < end)
551            {
552                    if (g_xserver_be)
553                    {
554                            *(out++) = 0x00;
555                            *(out++) = *(data++);
556                            *(out++) = *(data++);
557                            *(out++) = *(data++);
558                    }
559                    else
560                    {
561                            *(out++) = *(data++);
562                            *(out++) = *(data++);
563                            *(out++) = *(data++);
564                            *(out++) = 0x00;
565                    }
566            }
567    }
568    
569    static uint8 *
570    translate_image(int width, int height, uint8 * data)
571    {
572            int size = width * height * g_bpp / 8;
573            uint8 *out = (uint8 *) xmalloc(size);
574            uint8 *end = out + size;
575    
576          display =          switch (g_server_bpp)
                 XkbOpenDisplay(NULL, &xkb_event, &xkb_error, &xkb_major,  
                                &xkb_minor, &xkb_reason);  
         switch (xkb_reason)  
577          {          {
578                  case XkbOD_BadLibraryVersion:                  case 24:
579                          error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");                          switch (g_bpp)
580                          break;                          {
581                  case XkbOD_ConnectionRefused:                                  case 32:
582                          error("XkbOD_ConnectionRefused\n");                                          translate24to32(data, out, end);
583                                            break;
584                                    case 24:
585                                            translate24to24(data, out, end);
586                                            break;
587                                    case 16:
588                                            translate24to16(data, out, end);
589                                            break;
590                            }
591                          break;                          break;
592                  case XkbOD_BadServerVersion:                  case 16:
593                          error("XkbOD_BadServerVersion\n");                          switch (g_bpp)
594                            {
595                                    case 32:
596                                            translate16to32((uint16 *) data, out, end);
597                                            break;
598                                    case 24:
599                                            translate16to24((uint16 *) data, out, end);
600                                            break;
601                                    case 16:
602                                            translate16to16((uint16 *) data, (uint16 *) out,
603                                                            (uint16 *) end);
604                                            break;
605                            }
606                          break;                          break;
607                  case XkbOD_NonXkbServer:                  case 15:
608                          error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");                          switch (g_bpp)
609                            {
610                                    case 32:
611                                            translate15to32((uint16 *) data, out, end);
612                                            break;
613                                    case 24:
614                                            translate15to24((uint16 *) data, out, end);
615                                            break;
616                                    case 16:
617                                            translate15to16((uint16 *) data, out, end);
618                                            break;
619                            }
620                          break;                          break;
621                  case XkbOD_Success:                  case 8:
622                          DEBUG("XkbOD_Success: Connection established with display\n");                          switch (g_bpp)
623                            {
624                                    case 8:
625                                            translate8to8(data, out, end);
626                                            break;
627                                    case 16:
628                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
629                                            break;
630                                    case 24:
631                                            translate8to24(data, out, end);
632                                            break;
633                                    case 32:
634                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
635                                            break;
636                            }
637                          break;                          break;
638          }          }
639            return out;
640    }
641    
642    BOOL
643    get_key_state(unsigned int state, uint32 keysym)
644    {
645            int modifierpos, key, keysymMask = 0;
646            int offset;
647    
648            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
649    
650          if (display == NULL)          if (keycode == NoSymbol)
651                    return False;
652    
653            for (modifierpos = 0; modifierpos < 8; modifierpos++)
654          {          {
655                  error("Failed to open display\n");                  offset = g_mod_map->max_keypermod * modifierpos;
656    
657                    for (key = 0; key < g_mod_map->max_keypermod; key++)
658                    {
659                            if (g_mod_map->modifiermap[offset + key] == keycode)
660                                    keysymMask |= 1 << modifierpos;
661                    }
662            }
663    
664            return (state & keysymMask) ? True : False;
665    }
666    
667    BOOL
668    ui_init(void)
669    {
670            XPixmapFormatValues *pfm;
671            uint16 test;
672            int i;
673    
674            g_display = XOpenDisplay(NULL);
675            if (g_display == NULL)
676            {
677                    error("Failed to open display: %s\n", XDisplayName(NULL));
678                  return False;                  return False;
679          }          }
680    
681          x_socket = ConnectionNumber(display);          g_x_socket = ConnectionNumber(g_display);
682          screen = DefaultScreenOfDisplay(display);          g_screen = DefaultScreenOfDisplay(g_display);
683          visual = DefaultVisualOfScreen(screen);          g_visual = DefaultVisualOfScreen(g_screen);
684          depth = DefaultDepthOfScreen(screen);          g_depth = DefaultDepthOfScreen(g_screen);
685    
686          pfm = XListPixmapFormats(display, &i);          pfm = XListPixmapFormats(g_display, &i);
687          if (pfm != NULL)          if (pfm != NULL)
688          {          {
689                  /* Use maximum bpp for this depth - this is generally                  /* Use maximum bpp for this depth - this is generally
690                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
691                  while (i--)                  while (i--)
692                  {                  {
693                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
694                          {                          {
695                                  bpp = pfm[i].bits_per_pixel;                                  g_bpp = pfm[i].bits_per_pixel;
696                          }                          }
697                  }                  }
698                  XFree(pfm);                  XFree(pfm);
699          }          }
700    
701          if (bpp < 8)          if (g_bpp < 8)
702          {          {
703                  error("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
704                  XCloseDisplay(display);                  XCloseDisplay(g_display);
705                  return False;                  return False;
706          }          }
707    
708          if (depth <= 8)          /* private colour map code only works for 8 bpp */
709                  owncolmap = True;          if (g_owncolmap && (g_bpp > 8))
710          else                  g_owncolmap = False;
                 xcolmap = DefaultColormapOfScreen(screen);  
711    
712          test = 1;          if (!g_owncolmap)
713          host_be = !(BOOL) (*(uint8 *) (&test));          {
714          xserver_be = (ImageByteOrder(display) == MSBFirst);                  g_xcolmap = DefaultColormapOfScreen(g_screen);
715                    if (g_depth <= 8)
716                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
717            }
718    
719          white = WhitePixelOfScreen(screen);          g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);
         attribs.background_pixel = BlackPixelOfScreen(screen);  
         attribs.backing_store = DoesBackingStore(screen);  
720    
721          if (attribs.backing_store == NotUseful)          if (DoesBackingStore(g_screen) != Always)
722                  ownbackstore = True;                  g_ownbackstore = True;
723    
724            test = 1;
725            g_host_be = !(BOOL) (*(uint8 *) (&test));
726            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
727    
728          if (fullscreen)          /*
729             * Determine desktop size
730             */
731            if (g_width < 0)
732          {          {
733                  attribs.override_redirect = True;                  /* Percent of screen */
734                  width = WidthOfScreen(screen);                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
735                  height = HeightOfScreen(screen);                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
736          }          }
737          else          else if (g_width == 0)
738          {          {
739                  attribs.override_redirect = False;                  /* Fetch geometry from _NET_WORKAREA */
740                    uint32 x, y, cx, cy;
741    
742                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
743                    {
744                            g_width = cx;
745                            g_height = cy;
746                    }
747                    else
748                    {
749                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
750                            g_width = 800;
751                            g_height = 600;
752                    }
753            }
754            else if (g_fullscreen)
755            {
756                    g_width = WidthOfScreen(g_screen);
757                    g_height = HeightOfScreen(g_screen);
758          }          }
759    
760          width = (width + 3) & ~3;       /* make width a multiple of 32 bits */          /* make sure width is a multiple of 4 */
761            g_width = (g_width + 3) & ~3;
762    
763            if (g_ownbackstore)
764            {
765                    g_backstore =
766                            XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,
767                                          g_depth);
768    
769                    /* clear to prevent rubbish being exposed at startup */
770                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
771                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
772            }
773    
774            g_mod_map = XGetModifierMapping(g_display);
775    
776            xkeymap_init();
777    
778            if (g_enable_compose)
779                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
780    
781            xclip_init();
782    
783          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          /* todo take this out when high colour is done */
784                              0, 0, width, height, 0, CopyFromParent,          printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth);
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
785    
786          XStoreName(display, wnd, title);          return True;
787    }
788    
789    void
790    ui_deinit(void)
791    {
792            if (g_IM != NULL)
793                    XCloseIM(g_IM);
794    
795            XFreeModifiermap(g_mod_map);
796    
797            if (g_ownbackstore)
798                    XFreePixmap(g_display, g_backstore);
799    
800            XFreeGC(g_display, g_gc);
801            XCloseDisplay(g_display);
802            g_display = NULL;
803    }
804    
805    #define NULL_POINTER_MASK       "\x80"
806    #define NULL_POINTER_DATA       "\x0\x0\x0"
807            
808    BOOL
809    ui_create_window(void)
810    {
811            XSetWindowAttributes attribs;
812            XClassHint *classhints;
813            XSizeHints *sizehints;
814            int wndwidth, wndheight;
815            long input_mask, ic_input_mask;
816            XEvent xevent;
817    
818            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
819            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
820    
821            attribs.background_pixel = BlackPixelOfScreen(g_screen);
822            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
823            attribs.override_redirect = g_fullscreen;
824    
825            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
826                                  0, CopyFromParent, InputOutput, CopyFromParent,
827                                  CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
828    
829            XStoreName(g_display, g_wnd, g_title);
830    
831            if (g_hide_decorations)
832                    mwm_hide_decorations();
833    
834          classhints = XAllocClassHint();          classhints = XAllocClassHint();
835          if (classhints != NULL)          if (classhints != NULL)
836          {          {
837                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
838                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
839                  XFree(classhints);                  XFree(classhints);
840          }          }
841    
# Line 334  ui_create_window(char *title) Line 843  ui_create_window(char *title)
843          if (sizehints)          if (sizehints)
844          {          {
845                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
846                  sizehints->min_width = sizehints->max_width = width;                  sizehints->min_width = sizehints->max_width = g_width;
847                  sizehints->min_height = sizehints->max_height = height;                  sizehints->min_height = sizehints->max_height = g_height;
848                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
849                  XFree(sizehints);                  XFree(sizehints);
850          }          }
851    
852          xkeymap_init();          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
853                    VisibilityChangeMask | FocusChangeMask;
854    
855          input_mask = KeyPressMask | KeyReleaseMask |          if (g_sendmotion)
                 ButtonPressMask | ButtonReleaseMask |  
                 EnterWindowMask | LeaveWindowMask;  
         if (sendmotion)  
856                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
857            if (g_ownbackstore)
         if (ownbackstore)  
858                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
859            if (g_fullscreen || g_grab_keyboard)
860                    input_mask |= EnterWindowMask;
861            if (g_grab_keyboard)
862                    input_mask |= LeaveWindowMask;
863    
864          XSelectInput(display, wnd, input_mask);          if (g_IM != NULL)
865          gc = XCreateGC(display, wnd, 0, NULL);          {
866                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
867                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
868    
869          if (ownbackstore)                  if ((g_IC != NULL)
870                  backstore = XCreatePixmap(display, wnd, width, height, depth);                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
871                            input_mask |= ic_input_mask;
872            }
873    
874          XMapWindow(display, wnd);          XSelectInput(g_display, g_wnd, input_mask);
875            XMapWindow(g_display, g_wnd);
876    
877          /* TODO: error texts... make them friendly. */          /* wait for VisibilityNotify */
878          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);          do
         if ((int) xkb == BadAlloc || xkb == NULL)  
879          {          {
880                  error("XkbGetKeyboard failed.\n");                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
                 exit(0);  
881          }          }
882            while (xevent.type != VisibilityNotify);
883    
884          /* TODO: error texts... make them friendly. */          g_focused = False;
885          if (XkbSelectEvents          g_mouse_in_wnd = False;
             (display, xkb->device_spec, XkbAllEventsMask,  
              XkbAllEventsMask) == False)  
         {  
                 error("XkbSelectEvents failed.\n");  
                 exit(0);  
         }  
886    
887          xwin_get_numlock_mask();          /* handle the WM_DELETE_WINDOW protocol */
888            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
889            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
890            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
891    
892            /* create invisible 1x1 cursor to be used as null cursor */
893            g_null_cursor = ui_create_cursor(0, 0, 1, 1, NULL_POINTER_MASK, NULL_POINTER_DATA);
894    
895          return True;          return True;
896  }  }
897    
898  void  void
899  xwin_get_numlock_mask()  ui_destroy_window(void)
900  {  {
901          KeyCode numlockcode;          ui_destroy_cursor(g_null_cursor);
902          KeyCode *keycode;          
903          XModifierKeymap *modmap;          if (g_IC != NULL)
904          int i, j;                  XDestroyIC(g_IC);
   
         /* Find out if numlock is already defined as a modifier key, and if so where */  
         numlockcode = XKeysymToKeycode(display, 0xFF7F);        /* XF_Num_Lock = 0xFF7F */  
         if (numlockcode)  
         {  
                 modmap = XGetModifierMapping(display);  
                 if (modmap)  
                 {  
                         keycode = modmap->modifiermap;  
                         for (i = 0; i < 8; i++)  
                                 for (j = modmap->max_keypermod; j--;)  
                                 {  
                                         if (*keycode == numlockcode)  
                                         {  
                                                 numlock_modifier_mask =  
                                                         (1 << i);  
                                                 i = 8;  
                                                 break;  
                                         }  
                                         keycode++;  
                                 }  
                         if (!numlock_modifier_mask)  
                         {  
                                 modmap->modifiermap[7 *  
                                                     modmap->max_keypermod] =  
                                         numlockcode;  
                                 if (XSetModifierMapping(display, modmap) ==  
                                     MappingSuccess)  
                                         numlock_modifier_mask = (1 << 7);  
                                 else  
                                         printf("XSetModifierMapping failed!\n");  
                         }  
                         XFreeModifiermap(modmap);  
                 }  
         }  
   
         if (!numlock_modifier_mask)  
                 printf("WARNING: Failed to get a numlock modifier mapping.\n");  
905    
906            XDestroyWindow(g_display, g_wnd);
907  }  }
908    
909  void  void
910  ui_destroy_window()  xwin_toggle_fullscreen(void)
911  {  {
912          if (xkb != NULL)          Pixmap contents = 0;
913                  XkbFreeKeyboard(xkb, XkbAllControlsMask, True);  
914            if (!g_ownbackstore)
915            {
916                    /* need to save contents of window */
917                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
918                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
919            }
920    
921            ui_destroy_window();
922            g_fullscreen = !g_fullscreen;
923            ui_create_window();
924    
925          if (ownbackstore)          XDefineCursor(g_display, g_wnd, g_current_cursor);
                 XFreePixmap(display, backstore);  
926    
927          XFreeGC(display, gc);          if (!g_ownbackstore)
928          XDestroyWindow(display, wnd);          {
929          XCloseDisplay(display);                  XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
930          display = NULL;                  XFreePixmap(g_display, contents);
931            }
932  }  }
933    
934  static void  /* Process all events in Xlib queue
935  xwin_process_events()     Returns 0 after user quit, 1 otherwise */
936    static int
937    xwin_process_events(void)
938  {  {
939          XEvent xevent;          XEvent xevent;
   
940          KeySym keysym;          KeySym keysym;
         uint8 scancode;  
941          uint16 button, flags;          uint16 button, flags;
942          uint32 ev_time;          uint32 ev_time;
943          uint32 tmpmods;          key_translation tr;
944            char str[256];
945            Status status;
946            unsigned int state;
947            Window wdummy;
948            int dummy;
949    
950          while (XCheckMaskEvent(display, ~0, &xevent))          while (XPending(g_display) > 0)
951          {          {
952                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
953    
954                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
955                    {
956                            DEBUG_KBD(("Filtering event\n"));
957                            continue;
958                    }
959    
960                  flags = 0;                  flags = 0;
961    
962                  switch (xevent.type)                  switch (xevent.type)
963                  {                  {
964                          case KeyRelease:                          case ClientMessage:
965                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;                                  /* the window manager told us to quit */
966                                  /* fall through */                                  if ((xevent.xclient.message_type == g_protocol_atom)
967                          case KeyPress:                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
968                                  if (XkbTranslateKeyCode                                          /* Quit */
969                                      (xkb, xevent.xkey.keycode,                                          return 0;
                                      xevent.xkey.state, &tmpmods,  
                                      &keysym) == False)  
                                         break;  
                                 scancode =  
                                         xkeymap_translate_key(keysym,  
                                                               xevent.xkey.  
                                                               keycode,  
                                                               &flags);  
   
                                 if (scancode == 0)  
                                         break;  
   
                                 /* keep track of the modifiers -- needed for stickykeys... */  
                                 if (xevent.type == KeyPress)  
                                         xwin_mod_press(xevent.xkey.state,  
                                                        ev_time, scancode);  
   
                                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                                flags, scancode, 0);  
   
                                 if (xevent.type == KeyRelease)  
                                         xwin_mod_release(xevent.xkey.state,  
                                                          ev_time, scancode);  
   
970                                  break;                                  break;
971    
972                          case ButtonPress:                          case KeyPress:
973                                  flags = MOUSE_FLAG_DOWN;                                  g_last_gesturetime = xevent.xkey.time;
974                                  /* fall through */                                  if (g_IC != NULL)
975                                            /* Multi_key compatible version */
976                          case ButtonRelease:                                  {
977                                  button = xkeymap_translate_button(xevent.                                          XmbLookupString(g_IC,
978                                                                    xbutton.                                                          &xevent.xkey, str, sizeof(str), &keysym,
979                                                                    button);                                                          &status);
980                                  if (button == 0)                                          if (!((status == XLookupKeySym) || (status == XLookupBoth)))
981                                          break;                                          {
982                                                    error("XmbLookupString failed with status 0x%x\n",
983                                                          status);
984                                                    break;
985                                            }
986                                    }
987                                    else
988                                    {
989                                            /* Plain old XLookupString */
990                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
991                                            XLookupString((XKeyEvent *) & xevent,
992                                                          str, sizeof(str), &keysym, NULL);
993                                    }
994    
995                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
996                                                 flags | button,                                             get_ksname(keysym)));
                                                xevent.xbutton.x,  
                                                xevent.xbutton.y);  
                                 break;  
997    
998                          case MotionNotify:                                  ev_time = time(NULL);
999                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1000                                                 MOUSE_FLAG_MOVE,                                          break;
                                                xevent.xmotion.x,  
                                                xevent.xmotion.y);  
                                 break;  
1001    
1002                          case EnterNotify:                                  tr = xkeymap_translate_key(keysym,
1003                                  XGrabKeyboard(display, wnd, True,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                               GrabModeAsync, GrabModeAsync,  
                                               CurrentTime);  
1004    
1005                                  xwin_mod_update(xevent.xcrossing.state,                                  if (tr.scancode == 0)
1006                                                  ev_time);                                          break;
                                 break;  
1007    
1008                          case LeaveNotify:                                  save_remote_modifiers(tr.scancode);
1009                                  XUngrabKeyboard(display, CurrentTime);                                  ensure_remote_modifiers(ev_time, tr);
1010                                  break;                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1011                                    restore_remote_modifiers(ev_time, tr.scancode);
1012    
                         case Expose:  
                                 XCopyArea(display, backstore, wnd, gc,  
                                           xevent.xexpose.x, xevent.xexpose.y,  
                                           xevent.xexpose.width,  
                                           xevent.xexpose.height,  
                                           xevent.xexpose.x, xevent.xexpose.y);  
1013                                  break;                                  break;
                 }  
         }  
 }  
   
 void  
 xwin_mod_update(uint32 state, uint32 ev_time)  
 {  
         xwin_mod_press(state, ev_time, 0);  
         xwin_mod_release(state, ev_time, 0);  
 }  
   
 void  
 xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode)  
 {  
         switch (scancode)  
         {  
                 case 0x2a:  
                         key_down_state &= ~DShift1Mask;  
                         break;  
                 case 0x36:  
                         key_down_state &= ~DShift2Mask;  
                         break;  
                 case 0x1d:  
                         key_down_state &= ~DControl1Mask;  
                         break;  
                 case 0x9d:  
                         key_down_state &= ~DControl2Mask;  
                         break;  
                 case 0x38:  
                         key_down_state &= ~DMod1Mask;  
                         break;  
                 case 0xb8:  
                         key_down_state &= ~DMod2Mask;  
                         break;  
         }  
   
         if (!(numlock_modifier_mask & state)  
             && (key_down_state & DNumLockMask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);  
                 key_down_state &= ~DNumLockMask;  
         }  
   
         if (!(LockMask & state) && (key_down_state & DLockMask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);  
                 key_down_state &= ~DLockMask;  
   
         }  
1014    
1015                            case KeyRelease:
1016                                    g_last_gesturetime = xevent.xkey.time;
1017                                    XLookupString((XKeyEvent *) & xevent, str,
1018                                                  sizeof(str), &keysym, NULL);
1019    
1020          if (!(ShiftMask & state) && (key_down_state & DShift1Mask))                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1021          {                                             get_ksname(keysym)));
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a,  
                                0);  
                 key_down_state &= ~DShift1Mask;  
1022    
1023          }                                  ev_time = time(NULL);
1024                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1025                                            break;
1026    
1027          if (!(ControlMask & state) && (key_down_state & DControl1Mask))                                  tr = xkeymap_translate_key(keysym,
1028          {                                                             xevent.xkey.keycode, xevent.xkey.state);
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d,  
                                0);  
                 key_down_state &= ~DControl1Mask;  
1029    
1030          }                                  if (tr.scancode == 0)
1031                                            break;
1032    
1033          if (!(Mod1Mask & state) && (key_down_state & DMod1Mask))                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1034          {                                  break;
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38,  
                                0);  
                 key_down_state &= ~DMod1Mask;  
1035    
1036          }                          case ButtonPress:
1037                                    flags = MOUSE_FLAG_DOWN;
1038                                    /* fall through */
1039    
1040          if (!(Mod2Mask & state) && (key_down_state & DMod2Mask))                          case ButtonRelease:
1041          {                                  g_last_gesturetime = xevent.xbutton.time;
1042                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8,                                  button = xkeymap_translate_button(xevent.xbutton.button);
1043                                 0);                                  if (button == 0)
1044                  key_down_state &= ~DMod2Mask;                                          break;
         }  
 }  
1045    
1046                                    /* If win_button_size is nonzero, enable single app mode */
1047                                    if (xevent.xbutton.y < g_win_button_size)
1048                                    {
1049                                            /* Stop moving window when button is released, regardless of cursor position */
1050                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1051                                                    g_moving_wnd = False;
1052    
1053  void                                          /*  Check from right to left: */
 xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode)  
 {  
1054    
1055          switch (scancode)                                          if (xevent.xbutton.x >= g_width - g_win_button_size)
1056          {                                          {
1057                  case 0x2a:                                                  /* The close button, continue */
1058                          key_down_state |= DShift1Mask;                                                  ;
1059                          break;                                          }
1060                  case 0x36:                                          else if (xevent.xbutton.x >=
1061                          key_down_state |= DShift2Mask;                                                   g_width - g_win_button_size * 2)
1062                          break;                                          {
1063                  case 0x1d:                                                  /* The maximize/restore button. Do not send to
1064                          key_down_state |= DControl1Mask;                                                     server.  It might be a good idea to change the
1065                          break;                                                     cursor or give some other visible indication
1066                  case 0x9d:                                                     that rdesktop inhibited this click */
1067                          key_down_state |= DControl2Mask;                                                  break;
1068                          break;                                          }
1069                  case 0x3a:                                          else if (xevent.xbutton.x >=
1070                          key_down_state ^= DLockMask;                                                   g_width - g_win_button_size * 3)
1071                          break;                                          {
1072                  case 0x45:                                                  /* The minimize button. Iconify window. */
1073                          key_down_state ^= DNumLockMask;                                                  XIconifyWindow(g_display, g_wnd,
1074                          break;                                                                 DefaultScreen(g_display));
1075                  case 0x38:                                                  break;
1076                          key_down_state |= DMod1Mask;                                          }
1077                          break;                                          else if (xevent.xbutton.x <= g_win_button_size)
1078                  case 0xb8:                                          {
1079                          key_down_state |= DMod2Mask;                                                  /* The system menu. Ignore. */
1080                          break;                                                  break;
1081          }                                          }
1082                                            else
1083                                            {
1084                                                    /* The title bar. */
1085                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1086                                                        && g_hide_decorations)
1087                                                    {
1088                                                            g_moving_wnd = True;
1089                                                            g_move_x_offset = xevent.xbutton.x;
1090                                                            g_move_y_offset = xevent.xbutton.y;
1091                                                    }
1092                                                    break;
1093    
1094          if ((numlock_modifier_mask && state)                                          }
1095              && !(key_down_state & DNumLockMask))                                  }
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);  
                 key_down_state |= DNumLockMask;  
         }  
1096    
1097          if ((LockMask & state) && !(key_down_state & DLockMask))                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1098          {                                                 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1099                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);                                  break;
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);  
                 key_down_state |= DLockMask;  
1100    
1101          }                          case MotionNotify:
1102                                    if (g_moving_wnd)
1103                                    {
1104                                            XMoveWindow(g_display, g_wnd,
1105                                                        xevent.xmotion.x_root - g_move_x_offset,
1106                                                        xevent.xmotion.y_root - g_move_y_offset);
1107                                            break;
1108                                    }
1109    
1110                                    if (g_fullscreen && !g_focused)
1111                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1112                                                           CurrentTime);
1113                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1114                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1115                                    break;
1116    
1117          if ((ShiftMask & state)                          case FocusIn:
1118              && !((key_down_state & DShift1Mask)                                  if (xevent.xfocus.mode == NotifyGrab)
1119                   || (key_down_state & DShift2Mask)))                                          break;
1120          {                                  g_focused = True;
1121                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                  XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,
1122                                 0x2a, 0);                                                &dummy, &dummy, &state);
1123                  key_down_state |= DShift1Mask;                                  reset_modifier_keys(state);
1124                                    if (g_grab_keyboard && g_mouse_in_wnd)
1125                                            XGrabKeyboard(g_display, g_wnd, True,
1126                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1127                                    break;
1128    
1129          }                          case FocusOut:
1130                                    if (xevent.xfocus.mode == NotifyUngrab)
1131                                            break;
1132                                    g_focused = False;
1133                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1134                                            XUngrabKeyboard(g_display, CurrentTime);
1135                                    break;
1136    
1137          if ((ControlMask & state)                          case EnterNotify:
1138              && !((key_down_state & DControl1Mask)                                  /* we only register for this event when in fullscreen mode */
1139                   || (key_down_state & DControl2Mask)))                                  /* or grab_keyboard */
1140          {                                  g_mouse_in_wnd = True;
1141                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                  if (g_fullscreen)
1142                                 0x1d, 0);                                  {
1143                  key_down_state |= DControl1Mask;                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1144                                                           CurrentTime);
1145                                            break;
1146                                    }
1147                                    if (g_focused)
1148                                            XGrabKeyboard(g_display, g_wnd, True,
1149                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1150                                    break;
1151    
1152          }                          case LeaveNotify:
1153                                    /* we only register for this event when grab_keyboard */
1154                                    g_mouse_in_wnd = False;
1155                                    XUngrabKeyboard(g_display, CurrentTime);
1156                                    break;
1157    
1158          if ((Mod1Mask & state) && !(key_down_state & DMod1Mask))                          case Expose:
1159          {                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1160                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                            xevent.xexpose.x, xevent.xexpose.y,
1161                                 0x38, 0);                                            xevent.xexpose.width,
1162                  key_down_state |= DMod1Mask;                                            xevent.xexpose.height,
1163                                              xevent.xexpose.x, xevent.xexpose.y);
1164                                    break;
1165    
1166          }                          case MappingNotify:
1167                                    /* Refresh keyboard mapping if it has changed. This is important for
1168                                       Xvnc, since it allocates keycodes dynamically */
1169                                    if (xevent.xmapping.request == MappingKeyboard
1170                                        || xevent.xmapping.request == MappingModifier)
1171                                            XRefreshKeyboardMapping(&xevent.xmapping);
1172    
1173          if ((Mod2Mask & state) && !(key_down_state & DMod2Mask))                                  if (xevent.xmapping.request == MappingModifier)
1174          {                                  {
1175                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                          XFreeModifiermap(g_mod_map);
1176                                 0xb8, 0);                                          g_mod_map = XGetModifierMapping(g_display);
1177                  key_down_state |= DMod2Mask;                                  }
1178                                    break;
1179    
1180                                    /* clipboard stuff */
1181                            case SelectionNotify:
1182                                    xclip_handle_SelectionNotify(&xevent.xselection);
1183                                    break;
1184                            case SelectionRequest:
1185                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1186                                    break;
1187                            case SelectionClear:
1188                                    xclip_handle_SelectionClear();
1189                                    break;
1190                            case PropertyNotify:
1191                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1192                                    break;
1193                    }
1194          }          }
1195            /* Keep going */
1196            return 1;
1197  }  }
1198    
1199  void  /* Returns 0 after user quit, 1 otherwise */
1200    int
1201  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1202  {  {
1203          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;          int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
1204          fd_set rfds;          fd_set rfds, wfds;
   
         FD_ZERO(&rfds);  
1205    
1206          while (True)          while (True)
1207          {          {
1208                    /* Process any events already waiting */
1209                    if (!xwin_process_events())
1210                            /* User quit */
1211                            return 0;
1212    
1213                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1214                    FD_ZERO(&wfds);
1215                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1216                  if (display != NULL)                  FD_SET(g_x_socket, &rfds);
1217    
1218    #ifdef WITH_RDPSND
1219                    /* FIXME: there should be an API for registering fds */
1220                    if (g_dsp_busy)
1221                  {                  {
1222                          FD_SET(x_socket, &rfds);                          FD_SET(g_dsp_fd, &wfds);
1223                          XFlush(display);                          n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1224                  }                  }
1225    #endif
1226    
1227                  switch (select(n, &rfds, NULL, NULL, NULL))                  switch (select(n, &rfds, &wfds, NULL, NULL))
1228                  {                  {
1229                          case -1:                          case -1:
1230                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
# Line 741  ui_select(int rdp_socket) Line 1233  ui_select(int rdp_socket)
1233                                  continue;                                  continue;
1234                  }                  }
1235    
                 if (FD_ISSET(x_socket, &rfds))  
                         xwin_process_events();  
   
1236                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1237                          return;                          return 1;
1238    
1239    #ifdef WITH_RDPSND
1240                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1241                            wave_out_play();
1242    #endif
1243          }          }
1244  }  }
1245    
1246  void  void
1247  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1248  {  {
1249          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1250  }  }
1251    
1252  HBITMAP  HBITMAP
# Line 762  ui_create_bitmap(int width, int height, Line 1256  ui_create_bitmap(int width, int height,
1256          Pixmap bitmap;          Pixmap bitmap;
1257          uint8 *tdata;          uint8 *tdata;
1258    
1259          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1260          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1261          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1262                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1263    
1264          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1265    
1266          XFree(image);          XFree(image);
1267          if (!owncolmap)          if (!g_owncolmap)
1268                  xfree(tdata);                  xfree(tdata);
1269          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1270  }  }
1271    
1272  void  void
1273  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)  
1274  {  {
1275          XImage *image;          XImage *image;
1276          uint8 *tdata;          uint8 *tdata;
1277            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1278            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1279                                 (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1280    
1281          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_ownbackstore)
         image = XCreateImage(display, visual, depth, ZPixmap,  
                              0, tdata, width, height, 8, 0);  
   
         if (ownbackstore)  
1282          {          {
1283                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1284                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1285          }          }
1286          else          else
1287          {          {
1288                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1289          }          }
1290    
1291          XFree(image);          XFree(image);
1292          if (!owncolmap)          if (!g_owncolmap)
1293                  xfree(tdata);                  xfree(tdata);
1294  }  }
1295    
1296  void  void
1297  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1298  {  {
1299          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1300  }  }
1301    
1302  HGLYPH  HGLYPH
# Line 817  ui_create_glyph(int width, int height, u Line 1309  ui_create_glyph(int width, int height, u
1309    
1310          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1311    
1312          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1313          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(g_display, bitmap, 0, NULL);
1314    
1315          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1316                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1317          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1318          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1319          XInitImage(image);          XInitImage(image);
1320    
1321          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1322    
1323          XFree(image);          XFree(image);
1324          XFreeGC(display, gc);          XFreeGC(g_display, gc);
1325          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1326  }  }
1327    
1328  void  void
1329  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1330  {  {
1331          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1332  }  }
1333    
1334  HCURSOR  HCURSOR
1335  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1336                   int height, uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
1337  {  {
1338          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1339          XColor bg, fg;          XColor bg, fg;
# Line 855  ui_create_cursor(unsigned int x, unsigne Line 1347  ui_create_cursor(unsigned int x, unsigne
1347          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1348          offset = scanline * height;          offset = scanline * height;
1349    
1350          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1351          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1352    
1353          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1354          memset(mask, 0, offset);          memset(mask, 0, offset);
1355    
1356          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 899  ui_create_cursor(unsigned int x, unsigne Line 1391  ui_create_cursor(unsigned int x, unsigne
1391          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1392          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1393    
1394          xcursor = XCreatePixmapCursor(display, (Pixmap) cursorglyph,          xcursor =
1395                                        (Pixmap) maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1396                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1397    
1398          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1399          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
# Line 912  ui_create_cursor(unsigned int x, unsigne Line 1405  ui_create_cursor(unsigned int x, unsigne
1405  void  void
1406  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1407  {  {
1408          XDefineCursor(display, wnd, (Cursor) cursor);          g_current_cursor = (Cursor) cursor;
1409            XDefineCursor(g_display, g_wnd, g_current_cursor);
1410  }  }
1411    
1412  void  void
1413  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1414  {  {
1415          XFreeCursor(display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
1416    }
1417    
1418    void
1419    ui_set_null_cursor(void)
1420    {
1421            ui_set_cursor(g_null_cursor);
1422  }  }
1423    
1424  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 927  ui_destroy_cursor(HCURSOR cursor) Line 1427  ui_destroy_cursor(HCURSOR cursor)
1427                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1428                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1429    
1430    
1431  HCOLOURMAP  HCOLOURMAP
1432  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
1433  {  {
1434          COLOURENTRY *entry;          COLOURENTRY *entry;
1435          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1436            if (!g_owncolmap)
1437            {
1438                    uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1439                    XColor xentry;
1440                    XColor xc_cache[256];
1441                    uint32 colour;
1442                    int colLookup = 256;
1443                    for (i = 0; i < ncolours; i++)
1444                    {
1445                            entry = &colours->colours[i];
1446                            MAKE_XCOLOR(&xentry, entry);
1447    
1448                            if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1449                            {
1450                                    /* Allocation failed, find closest match. */
1451                                    int j = 256;
1452                                    int nMinDist = 3 * 256 * 256;
1453                                    long nDist = nMinDist;
1454    
1455                                    /* only get the colors once */
1456                                    while (colLookup--)
1457                                    {
1458                                            xc_cache[colLookup].pixel = colLookup;
1459                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1460                                                    xc_cache[colLookup].blue = 0;
1461                                            xc_cache[colLookup].flags = 0;
1462                                            XQueryColor(g_display,
1463                                                        DefaultColormap(g_display,
1464                                                                        DefaultScreen(g_display)),
1465                                                        &xc_cache[colLookup]);
1466                                    }
1467                                    colLookup = 0;
1468    
1469                                    /* approximate the pixel */
1470                                    while (j--)
1471                                    {
1472                                            if (xc_cache[j].flags)
1473                                            {
1474                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1475                                                             (long) (xentry.red >> 8)) *
1476                                                            ((long) (xc_cache[j].red >> 8) -
1477                                                             (long) (xentry.red >> 8)) +
1478                                                            ((long) (xc_cache[j].green >> 8) -
1479                                                             (long) (xentry.green >> 8)) *
1480                                                            ((long) (xc_cache[j].green >> 8) -
1481                                                             (long) (xentry.green >> 8)) +
1482                                                            ((long) (xc_cache[j].blue >> 8) -
1483                                                             (long) (xentry.blue >> 8)) *
1484                                                            ((long) (xc_cache[j].blue >> 8) -
1485                                                             (long) (xentry.blue >> 8));
1486                                            }
1487                                            if (nDist < nMinDist)
1488                                            {
1489                                                    nMinDist = nDist;
1490                                                    xentry.pixel = j;
1491                                            }
1492                                    }
1493                            }
1494                            colour = xentry.pixel;
1495    
1496                            /* update our cache */
1497                            if (xentry.pixel < 256)
1498                            {
1499                                    xc_cache[xentry.pixel].red = xentry.red;
1500                                    xc_cache[xentry.pixel].green = xentry.green;
1501                                    xc_cache[xentry.pixel].blue = xentry.blue;
1502    
1503          if (owncolmap)                          }
1504    
1505    
1506                            /* byte swap here to make translate_image faster */
1507                            map[i] = translate_colour(colour);
1508                    }
1509                    return map;
1510            }
1511            else
1512          {          {
1513                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1514                  Colormap map;                  Colormap map;
1515    
1516                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1517                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1518                  {                  {
1519                          entry = &colours->colours[i];                          entry = &colours->colours[i];
# Line 947  ui_create_colourmap(COLOURMAP * colours) Line 1522  ui_create_colourmap(COLOURMAP * colours)
1522                          MAKE_XCOLOR(xentry, entry);                          MAKE_XCOLOR(xentry, entry);
1523                  }                  }
1524    
1525                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1526                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
1527    
1528                  xfree(xcolours);                  xfree(xcolours);
1529                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
1530          }          }
         else  
         {  
                 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);  
                 XColor xentry;  
                 uint32 colour;  
   
                 for (i = 0; i < ncolours; i++)  
                 {  
                         entry = &colours->colours[i];  
                         MAKE_XCOLOR(&xentry, entry);  
   
                         if (XAllocColor(display, xcolmap, &xentry) != 0)  
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
                 }  
   
                 return map;  
         }  
1531  }  }
1532    
1533  void  void
1534  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1535  {  {
1536          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap) map);  
         else  
1537                  xfree(map);                  xfree(map);
1538            else
1539                    XFreeColormap(g_display, (Colormap) map);
1540  }  }
1541    
1542  void  void
1543  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1544  {  {
1545          if (owncolmap)          if (!g_owncolmap)
1546                  XSetWindowColormap(display, wnd, (Colormap) map);          {
1547                    if (g_colmap)
1548                            xfree(g_colmap);
1549    
1550                    g_colmap = (uint32 *) map;
1551            }
1552          else          else
1553                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1554  }  }
1555    
1556  void  void
# Line 1004  ui_set_clip(int x, int y, int cx, int cy Line 1562  ui_set_clip(int x, int y, int cx, int cy
1562          rect.y = y;          rect.y = y;
1563          rect.width = cx;          rect.width = cx;
1564          rect.height = cy;          rect.height = cy;
1565          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1566  }  }
1567    
1568  void  void
1569  ui_reset_clip()  ui_reset_clip(void)
1570  {  {
1571          XRectangle rect;          XRectangle rect;
1572    
1573          rect.x = 0;          rect.x = 0;
1574          rect.y = 0;          rect.y = 0;
1575          rect.width = width;          rect.width = g_width;
1576          rect.height = height;          rect.height = g_height;
1577          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1578  }  }
1579    
1580  void  void
1581  ui_bell()  ui_bell(void)
1582  {  {
1583          XBell(display, 0);          XBell(g_display, 0);
1584  }  }
1585    
1586  void  void
# Line 1034  ui_destblt(uint8 opcode, Line 1592  ui_destblt(uint8 opcode,
1592          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1593  }  }
1594    
1595    static uint8 hatch_patterns[] = {
1596            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1597            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1598            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1599            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1600            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1601            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1602    };
1603    
1604  void  void
1605  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1606            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
# Line 1051  ui_patblt(uint8 opcode, Line 1618  ui_patblt(uint8 opcode,
1618                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1619                          break;                          break;
1620    
1621                    case 2: /* Hatch */
1622                            fill = (Pixmap) ui_create_glyph(8, 8,
1623                                                            hatch_patterns + brush->pattern[0] * 8);
1624                            SET_FOREGROUND(fgcolour);
1625                            SET_BACKGROUND(bgcolour);
1626                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1627                            XSetStipple(g_display, g_gc, fill);
1628                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1629                            FILL_RECTANGLE(x, y, cx, cy);
1630                            XSetFillStyle(g_display, g_gc, FillSolid);
1631                            XSetTSOrigin(g_display, g_gc, 0, 0);
1632                            ui_destroy_glyph((HGLYPH) fill);
1633                            break;
1634    
1635                  case 3: /* Pattern */                  case 3: /* Pattern */
1636                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
1637                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
# Line 1058  ui_patblt(uint8 opcode, Line 1639  ui_patblt(uint8 opcode,
1639    
1640                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1641                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
1642                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1643                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
1644                          XSetTSOrigin(display, gc, brush->xorigin,                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
                                      brush->yorigin);  
1645    
1646                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1647    
1648                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
1649                            XSetTSOrigin(g_display, g_gc, 0, 0);
1650                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1651                          break;                          break;
1652    
# Line 1082  ui_screenblt(uint8 opcode, Line 1663  ui_screenblt(uint8 opcode,
1663               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1664  {  {
1665          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1666          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1667          if (ownbackstore)          if (g_ownbackstore)
1668                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1669          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1670  }  }
1671    
# Line 1095  ui_memblt(uint8 opcode, Line 1675  ui_memblt(uint8 opcode,
1675            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1676  {  {
1677          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1678          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);
1679          if (ownbackstore)          if (g_ownbackstore)
1680                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1681          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1682  }  }
1683    
# Line 1115  ui_triblt(uint8 opcode, Line 1694  ui_triblt(uint8 opcode,
1694          {          {
1695                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1696                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1697                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1698                          break;                          break;
1699    
1700                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1701                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1702                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1703                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1704                          break;                          break;
1705    
1706                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1707                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1708                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1709                          break;                          break;
1710    
1711                  default:                  default:
# Line 1146  ui_line(uint8 opcode, Line 1721  ui_line(uint8 opcode,
1721  {  {
1722          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1723          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
1724          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1725          if (ownbackstore)          if (g_ownbackstore)
1726                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1727          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1728  }  }
1729    
# Line 1161  ui_rect( Line 1736  ui_rect(
1736          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1737  }  }
1738    
1739    /* warning, this function only draws on wnd or backstore, not both */
1740  void  void
1741  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1742                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1743                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1744                int fgcolour)                int bgcolour, int fgcolour)
1745  {  {
1746          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1747          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1748    
1749          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
1750                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1751          XSetStipple(display, gc, (Pixmap) glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
1752          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
1753    
1754          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1755    
1756          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
1757  }  }
1758    
1759  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
# Line 1189  ui_draw_glyph(int mixmode, Line 1765  ui_draw_glyph(int mixmode,
1765        if ((xyoffset & 0x80))\        if ((xyoffset & 0x80))\
1766          {\          {\
1767            if (flags & TEXT2_VERTICAL) \            if (flags & TEXT2_VERTICAL) \
1768              y += ttext[++idx] | (ttext[++idx] << 8);\              y += ttext[idx+1] | (ttext[idx+2] << 8);\
1769            else\            else\
1770              x += ttext[++idx] | (ttext[++idx] << 8);\              x += ttext[idx+1] | (ttext[idx+2] << 8);\
1771              idx += 2;\
1772          }\          }\
1773        else\        else\
1774          {\          {\
# Line 1203  ui_draw_glyph(int mixmode, Line 1780  ui_draw_glyph(int mixmode,
1780      }\      }\
1781    if (glyph != NULL)\    if (glyph != NULL)\
1782      {\      {\
1783        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        ui_draw_glyph (mixmode, x + glyph->offset,\
1784                       y + (short) glyph->baseline,\                       y + glyph->baseline,\
1785                       glyph->width, glyph->height,\                       glyph->width, glyph->height,\
1786                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1787        if (flags & TEXT2_IMPLICIT_X)\        if (flags & TEXT2_IMPLICIT_X)\
# Line 1214  ui_draw_glyph(int mixmode, Line 1791  ui_draw_glyph(int mixmode,
1791    
1792  void  void
1793  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,
1794               int clipx, int clipy, int clipcx, int clipcy, int boxx,               int clipx, int clipy, int clipcx, int clipcy,
1795               int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1796               int fgcolour, uint8 * text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1797  {  {
1798          FONTGLYPH *glyph;          FONTGLYPH *glyph;
# Line 1226  ui_draw_text(uint8 font, uint8 flags, in Line 1803  ui_draw_text(uint8 font, uint8 flags, in
1803    
1804          if (boxcx > 1)          if (boxcx > 1)
1805          {          {
1806                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1807          }          }
1808          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1809          {          {
1810                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1811          }          }
1812    
1813          /* Paint text, character by character */          /* Paint text, character by character */
# Line 1240  ui_draw_text(uint8 font, uint8 flags, in Line 1817  ui_draw_text(uint8 font, uint8 flags, in
1817                  {                  {
1818                          case 0xff:                          case 0xff:
1819                                  if (i + 2 < length)                                  if (i + 2 < length)
1820                                          cache_put_text(text[i + 1], text,                                          cache_put_text(text[i + 1], text, text[i + 2]);
                                                        text[i + 2]);  
1821                                  else                                  else
1822                                  {                                  {
1823                                          error("this shouldn't be happening\n");                                          error("this shouldn't be happening\n");
1824                                          break;                                          exit(1);
1825                                  }                                  }
1826                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
1827                                  length -= i + 3;                                  length -= i + 3;
# Line 1258  ui_draw_text(uint8 font, uint8 flags, in Line 1834  ui_draw_text(uint8 font, uint8 flags, in
1834                                  if (entry != NULL)                                  if (entry != NULL)
1835                                  {                                  {
1836                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] ==
1837                                               0)                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
                                             && (!(flags & TEXT2_IMPLICIT_X)))  
1838                                          {                                          {
1839                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
1840                                                          y += text[i + 2];                                                          y += text[i + 2];
1841                                                  else                                                  else
1842                                                          x += text[i + 2];                                                          x += text[i + 2];
1843                                          }                                          }
                                         if (i + 2 < length)  
                                                 i += 3;  
                                         else  
                                                 i += 2;  
                                         length -= i;  
                                         /* this will move pointer from start to first character after FE command */  
                                         text = &(text[i]);  
                                         i = 0;  
1844                                          for (j = 0; j < entry->size; j++)                                          for (j = 0; j < entry->size; j++)
1845                                                  DO_GLYPH(((uint8 *) (entry->                                                  DO_GLYPH(((uint8 *) (entry->data)), j);
                                                                      data)),  
                                                          j);  
1846                                  }                                  }
1847                                    if (i + 2 < length)
1848                                            i += 3;
1849                                    else
1850                                            i += 2;
1851                                    length -= i;
1852                                    /* this will move pointer from start to first character after FE command */
1853                                    text = &(text[i]);
1854                                    i = 0;
1855                                  break;                                  break;
1856    
1857                          default:                          default:
# Line 1287  ui_draw_text(uint8 font, uint8 flags, in Line 1860  ui_draw_text(uint8 font, uint8 flags, in
1860                                  break;                                  break;
1861                  }                  }
1862          }          }
1863            if (g_ownbackstore)
1864            {
1865                    if (boxcx > 1)
1866                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1867                                      boxy, boxcx, boxcy, boxx, boxy);
1868                    else
1869                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1870                                      clipy, clipcx, clipcy, clipx, clipy);
1871            }
1872  }  }
1873    
1874  void  void
# Line 1297  ui_desktop_save(uint32 offset, int x, in Line 1877  ui_desktop_save(uint32 offset, int x, in
1877          Pixmap pix;          Pixmap pix;
1878          XImage *image;          XImage *image;
1879    
1880          if (ownbackstore)          if (g_ownbackstore)
1881          {          {
1882                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1883          }          }
1884          else          else
1885          {          {
1886                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1887                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1888                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1889                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
1890          }          }
1891    
1892          offset *= bpp / 8;          offset *= g_bpp / 8;
1893          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
                           bpp / 8, (uint8 *) image->data);  
1894    
1895          XDestroyImage(image);          XDestroyImage(image);
1896  }  }
# Line 1324  ui_desktop_restore(uint32 offset, int x, Line 1901  ui_desktop_restore(uint32 offset, int x,
1901          XImage *image;          XImage *image;
1902          uint8 *data;          uint8 *data;
1903    
1904          offset *= bpp / 8;          offset *= g_bpp / 8;
1905          data = cache_get_desktop(offset, cx, cy, bpp / 8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1906          if (data == NULL)          if (data == NULL)
1907                  return;                  return;
1908    
1909          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1910                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * bpp / 8);  
1911    
1912          if (ownbackstore)          if (g_ownbackstore)
1913          {          {
1914                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1915                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1916          }          }
1917          else          else
1918          {          {
1919                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1920          }          }
1921    
1922          XFree(image);          XFree(image);

Legend:
Removed from v.64  
changed lines
  Added in v.517

  ViewVC Help
Powered by ViewVC 1.1.26