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

Legend:
Removed from v.54  
changed lines
  Added in v.500

  ViewVC Help
Powered by ViewVC 1.1.26