/[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 52 by n-ki, Fri Apr 26 08:22:39 2002 UTC revision 478 by matthewc, Sun Oct 5 12:07:56 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;  BOOL g_enable_compose = False;
38  static Window wnd;  BOOL g_focused;
39  static GC gc;  BOOL g_mouse_in_wnd;
40  static Visual *visual;  
41  static int depth;  Display *g_display;
42  static int bpp;  Time g_last_gesturetime;
43    static int g_x_socket;
44    static Screen *g_screen;
45    Window g_wnd;
46    static GC g_gc;
47    static Visual *g_visual;
48    static int g_depth;
49    static int g_bpp;
50    static XIM g_IM;
51    static XIC g_IC;
52    static XModifierKeymap *g_mod_map;
53    static Cursor g_current_cursor;
54    static Atom g_protocol_atom, g_kill_atom;
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 key_modifier_state = 0;  
 static unsigned int key_down_state = 0;  
   
 #define DShift1Mask   (1<<0)  
 #define DShift2Mask   (1<<1)  
 #define DControl1Mask (1<<2)  
 #define DControl2Mask (1<<3)  
 #define DMod1Mask     (1<<4)  
 #define DMod2Mask     (1<<5)  
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 96  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    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
233    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
234    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
235                            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            switch (g_bpp)
284            {
285                    case 16:
286                            if (g_host_be != g_xserver_be)
287                                    BSWAP16(colour);
288                            break;
289    
290                    case 24:
291                            if (g_xserver_be)
292                                    BSWAP24(colour);
293                            break;
294    
295  void xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);                  case 32:
296  void xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);                          if (g_host_be != g_xserver_be)
297                                    BSWAP32(colour);
298                            break;
299            }
300    
301            return colour;
302    }
303    
304  static void  static void
305  translate8(uint8 *data, uint8 *out, uint8 *end)  translate8to8(uint8 * data, uint8 * out, uint8 * end)
306  {  {
307          while (out < end)          while (out < end)
308                  *(out++) = (uint8)colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
309  }  }
310    
311  static void  static void
312  translate16(uint8 *data, uint16 *out, uint16 *end)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
313  {  {
314          while (out < end)          while (out < end)
315                  *(out++) = (uint16)colmap[*(data++)];                  *(out++) = (uint16) g_colmap[*(data++)];
316  }  }
317    
318  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
319  static void  static void
320  translate24(uint8 *data, uint8 *out, uint8 *end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
321  {  {
322          uint32 value;          uint32 value;
323    
324          while (out < end)          while (out < end)
325          {          {
326                  value = colmap[*(data++)];                  value = g_colmap[*(data++)];
327                  *(out++) = value;                  *(out++) = value;
328                  *(out++) = value >> 8;                  *(out++) = value >> 8;
329                  *(out++) = value >> 16;                  *(out++) = value >> 16;
# Line 132  translate24(uint8 *data, uint8 *out, uin Line 331  translate24(uint8 *data, uint8 *out, uin
331  }  }
332    
333  static void  static void
334  translate32(uint8 *data, uint32 *out, uint32 *end)  translate8to32(uint8 * data, uint32 * out, uint32 * end)
335  {  {
336          while (out < end)          while (out < end)
337                  *(out++) = colmap[*(data++)];                  *(out++) = g_colmap[*(data++)];
338  }  }
339    
340  static uint8 *  /* todo the remaining translate function might need some big endian check ?? */
341  translate_image(int width, int height, uint8 *data)  
342    static void
343    translate15to16(uint16 * data, uint16 * out, uint16 * end)
344  {  {
345          int size = width * height * bpp/8;          while (out < end)
346          uint8 *out = xmalloc(size);                  *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
347          uint8 *end = out + size;  }
348    
349          switch (bpp)  static void
350          {  translate15to24(uint16 * data, uint8 * out, uint8 * end)
351                  case 8:  {
352                          translate8(data, out, end);          uint32 value;
                         break;  
353    
354                  case 16:          while (out < end)
355                          translate16(data, (uint16 *)out, (uint16 *)end);          {
356                          break;                  value = make_colour24(split_colour15(*(data++)));
357                    *(out++) = value;
358                    *(out++) = value >> 8;
359                    *(out++) = value >> 16;
360            }
361    }
362    
363                  case 24:  static void
364                          translate24(data, out, end);  translate15to32(uint16 * data, uint32 * out, uint32 * end)
365                          break;  {
366            uint16 pixel;
367    
368                  case 32:          while (out < end)
369                          translate32(data, (uint32 *)out, (uint32 *)end);          {
370                          break;                  if (g_host_be)
371                    {
372                            pixel = *(data++);
373                            pixel = (pixel & 0xff) << 8 | (pixel & 0xff00) >> 8;
374                            *(out++) = make_colour32(split_colour15(pixel));
375                    }
376                    else
377                    {
378                            *(out++) = make_colour32(split_colour15(*(data++)));
379                    }
380          }          }
381    }
382    
383          return out;  static void
384    translate16to16(uint16 * data, uint16 * out, uint16 * end)
385    {
386            while (out < end)
387                    *(out++) = (uint16) (*(data++));
388  }  }
389    
 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  
 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  
 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  
                         x = (x << 16) | (x >> 16); }  
390    
391  static uint32  static void
392  translate_colour(uint32 colour)  translate16to24(uint16 * data, uint8 * out, uint8 * end)
393  {  {
394          switch (bpp)          uint32 value;
395    
396            while (out < end)
397          {          {
398                  case 16:                  value = make_colour24(split_colour16(*(data++)));
399                          if (host_be != xserver_be)                  *(out++) = value;
400                                  BSWAP16(colour);                  *(out++) = value >> 8;
401                          break;                  *(out++) = value >> 16;
402            }
403    }
404    
405                  case 24:  static void
406                          if (xserver_be)  translate16to32(uint16 * data, uint32 * out, uint32 * end)
407                                  BSWAP24(colour);  {
408                          break;          uint16 pixel;
409    
410                  case 32:          while (out < end)
411                          if (host_be != xserver_be)          {
412                                  BSWAP32(colour);                  if (g_host_be)
413                          break;                  {
414                            pixel = *(data++);
415                            pixel = (pixel & 0xff) << 8 | (pixel & 0xff00) >> 8;
416                            *(out++) = make_colour32(split_colour16(pixel));
417                    }
418                    else
419                    {
420                            *(out++) = make_colour32(split_colour16(*(data++)));
421                    }
422          }          }
423    }
424    
425          return colour;  static void
426    translate24to16(uint8 * data, uint16 * out, uint16 * end)
427    {
428            uint32 pixel = 0;
429            while (out < end)
430            {
431                    pixel = *(data++) << 16;
432                    pixel |= *(data++) << 8;
433                    pixel |= *(data++);
434                    *(out++) = (uint16) make_colour16(split_colour24(pixel));
435            }
436  }  }
437    
438  BOOL  static void
439  ui_create_window(char *title)  translate24to24(uint8 * data, uint8 * out, uint8 * end)
440  {  {
441          XSetWindowAttributes attribs;          while (out < end)
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         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 )  
442          {          {
443                  error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");                  *(out++) = (*(data++));
444                  return False;          }
445    }
446    
447    static void
448    translate24to32(uint8 * data, uint32 * out, uint32 * end)
449    {
450            uint32 pixel = 0;
451            while (out < end)
452            {
453                    if (g_host_be)
454                    {
455                            pixel = *(data++) << 16;
456                            pixel |= *(data++) << 8;
457                            pixel |= *(data++);
458                    }
459                    else
460                    {
461                            pixel = *(data++);
462                            pixel |= *(data++) << 8;
463                            pixel |= *(data++) << 16;
464                    }
465                    *(out++) = pixel;
466          }          }
467    }
468    
469    static uint8 *
470    translate_image(int width, int height, uint8 * data)
471    {
472            int size = width * height * g_bpp / 8;
473            uint8 *out = (uint8 *) xmalloc(size);
474            uint8 *end = out + size;
475    
476          /* XKB is the 'new' keyboard handler in x.. ( the xkb code in Xfree86 originates from SGI, years 1993 and 1995 from what I could tell. )          switch (g_server_bpp)
          * it makes it possible for people with disabilities to use rdesktop, stickykeys, bouncekeys etc. VERY MUCH useful.  
          * XFree86 has had support for it since it's earliest incarnation. I believe it is a reasonable dependency.  
          */  
         display = XkbOpenDisplay( NULL, &xkb_event, &xkb_error, &xkb_major, &xkb_minor, &xkb_reason );  
         switch(xkb_reason)  
477          {          {
478                  case XkbOD_BadLibraryVersion:                  case 24:
479                          error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");                          switch (g_bpp)
480                          break;                          {
481                  case XkbOD_ConnectionRefused:                                  case 32:
482                          error("XkbOD_ConnectionRefused\n");                                          translate24to32(data, (uint32 *) out, (uint32 *) end);
483                                            break;
484                                    case 24:
485                                            translate24to24(data, out, end);
486                                            break;
487                                    case 16:
488                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
489                                            break;
490                            }
491                          break;                          break;
492                  case XkbOD_BadServerVersion:                  case 16:
493                          error("XkbOD_BadServerVersion\n");                          switch (g_bpp)
494                            {
495                                    case 32:
496                                            translate16to32((uint16 *) data, (uint32 *) out,
497                                                            (uint32 *) end);
498                                            break;
499                                    case 24:
500                                            translate16to24((uint16 *) data, out, end);
501                                            break;
502                                    case 16:
503                                            translate16to16((uint16 *) data, (uint16 *) out,
504                                                            (uint16 *) end);
505                                            break;
506                            }
507                          break;                          break;
508                  case XkbOD_NonXkbServer:                  case 15:
509                          error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");                          switch (g_bpp)
510                            {
511                                    case 32:
512                                            translate15to32((uint16 *) data, (uint32 *) out,
513                                                            (uint32 *) end);
514                                            break;
515                                    case 24:
516                                            translate15to24((uint16 *) data, out, end);
517                                            break;
518                                    case 16:
519                                            translate15to16((uint16 *) data, (uint16 *) out,
520                                                            (uint16 *) end);
521                                            break;
522                            }
523                          break;                          break;
524                  case XkbOD_Success:                  case 8:
525                          DEBUG("XkbOD_Success: Connection established with display\n");                          switch (g_bpp)
526                            {
527                                    case 8:
528                                            translate8to8(data, out, end);
529                                            break;
530                                    case 16:
531                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
532                                            break;
533                                    case 24:
534                                            translate8to24(data, out, end);
535                                            break;
536                                    case 32:
537                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
538                                            break;
539                            }
540                          break;                          break;
541          }          }
542            return out;
543    }
544    
545          if (display == NULL)  BOOL
546    get_key_state(unsigned int state, uint32 keysym)
547    {
548            int modifierpos, key, keysymMask = 0;
549            int offset;
550    
551            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
552    
553            if (keycode == NoSymbol)
554                    return False;
555    
556            for (modifierpos = 0; modifierpos < 8; modifierpos++)
557          {          {
558                  error("Failed to open display\n");                  offset = g_mod_map->max_keypermod * modifierpos;
559    
560                    for (key = 0; key < g_mod_map->max_keypermod; key++)
561                    {
562                            if (g_mod_map->modifiermap[offset + key] == keycode)
563                                    keysymMask |= 1 << modifierpos;
564                    }
565            }
566    
567            return (state & keysymMask) ? True : False;
568    }
569    
570    BOOL
571    ui_init(void)
572    {
573            XPixmapFormatValues *pfm;
574            uint16 test;
575            int i;
576    
577            g_display = XOpenDisplay(NULL);
578            if (g_display == NULL)
579            {
580                    error("Failed to open display: %s\n", XDisplayName(NULL));
581                  return False;                  return False;
582          }          }
583    
584          x_socket = ConnectionNumber(display);          g_x_socket = ConnectionNumber(g_display);
585          screen = DefaultScreenOfDisplay(display);          g_screen = DefaultScreenOfDisplay(g_display);
586          visual = DefaultVisualOfScreen(screen);          g_visual = DefaultVisualOfScreen(g_screen);
587          depth = DefaultDepthOfScreen(screen);          g_depth = DefaultDepthOfScreen(g_screen);
588            
589          pfm = XListPixmapFormats(display, &i);          pfm = XListPixmapFormats(g_display, &i);
590          if (pfm != NULL)          if (pfm != NULL)
591          {          {
592                  /* Use maximum bpp for this depth - this is generally                  /* Use maximum bpp for this depth - this is generally
593                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
594                  while (i--)                  while (i--)
595                  {                  {
596                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
597                          {                          {
598                                  bpp = pfm[i].bits_per_pixel;                                  g_bpp = pfm[i].bits_per_pixel;
599                          }                          }
600                  }                  }
601                  XFree(pfm);                  XFree(pfm);
602          }          }
603    
604          if (bpp < 8)          if (g_bpp < 8)
605          {          {
606                  error("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
607                  XCloseDisplay(display);                  XCloseDisplay(g_display);
608                  return False;                  return False;
609          }          }
610    
611          if (depth <= 8)          if (g_owncolmap != True)
612                  owncolmap = True;          {
613          else                  g_xcolmap = DefaultColormapOfScreen(g_screen);
614                  xcolmap = DefaultColormapOfScreen(screen);                  if (g_depth <= 8)
615                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
616            }
617    
618            g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);
619    
620            if (DoesBackingStore(g_screen) != Always)
621                    g_ownbackstore = True;
622    
623          test = 1;          test = 1;
624          host_be = !(BOOL)(*(uint8 *)(&test));          g_host_be = !(BOOL) (*(uint8 *) (&test));
625          xserver_be = (ImageByteOrder(display) == MSBFirst);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
626    
627          white = WhitePixelOfScreen(screen);          if ((g_width == 0) || (g_height == 0))
628          attribs.background_pixel = BlackPixelOfScreen(screen);          {
629          attribs.backing_store = DoesBackingStore(screen);                  /* Fetch geometry from _NET_WORKAREA */
630                    uint32 x, y, cx, cy;
631    
632          if (attribs.backing_store == NotUseful)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
633                  ownbackstore = True;                  {
634                            g_width = cx;
635                            g_height = cy;
636                    }
637                    else
638                    {
639                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
640                            g_width = 800;
641                            g_height = 600;
642                    }
643            }
644    
645          if (fullscreen)          if (g_fullscreen)
646          {          {
647                  attribs.override_redirect = True;                  g_width = WidthOfScreen(g_screen);
648                  width = WidthOfScreen(screen);                  g_height = HeightOfScreen(g_screen);
                 height = HeightOfScreen(screen);  
649          }          }
650          else  
651            /* make sure width is a multiple of 4 */
652            g_width = (g_width + 3) & ~3;
653    
654            if (g_ownbackstore)
655          {          {
656                  attribs.override_redirect = False;                  g_backstore =
657                            XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,
658                                          g_depth);
659    
660                    /* clear to prevent rubbish being exposed at startup */
661                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
662                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
663          }          }
664    
665          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          g_mod_map = XGetModifierMapping(g_display);
666    
667          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          if (g_enable_compose)
668                              0, 0, width, height, 0, CopyFromParent,                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
669    
670          XStoreName(display, wnd, title);          xkeymap_init();
671            xclip_init();
672    
673            /* todo take this out when high colour is done */
674            printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth);
675    
676            return True;
677    }
678    
679    void
680    ui_deinit(void)
681    {
682            if (g_IM != NULL)
683                    XCloseIM(g_IM);
684    
685            XFreeModifiermap(g_mod_map);
686    
687            if (g_ownbackstore)
688                    XFreePixmap(g_display, g_backstore);
689    
690            XFreeGC(g_display, g_gc);
691            XCloseDisplay(g_display);
692            g_display = NULL;
693    }
694    
695    BOOL
696    ui_create_window(void)
697    {
698            XSetWindowAttributes attribs;
699            XClassHint *classhints;
700            XSizeHints *sizehints;
701            int wndwidth, wndheight;
702            long input_mask, ic_input_mask;
703            XEvent xevent;
704    
705            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
706            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
707    
708            attribs.background_pixel = BlackPixelOfScreen(g_screen);
709            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
710            attribs.override_redirect = g_fullscreen;
711    
712            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
713                                  0, CopyFromParent, InputOutput, CopyFromParent,
714                                  CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
715    
716            XStoreName(g_display, g_wnd, g_title);
717    
718            if (g_hide_decorations)
719                    mwm_hide_decorations();
720    
721          classhints = XAllocClassHint();          classhints = XAllocClassHint();
722          if (classhints != NULL)          if (classhints != NULL)
723          {          {
724                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
725                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
726                  XFree(classhints);                  XFree(classhints);
727          }          }
728    
# Line 328  ui_create_window(char *title) Line 730  ui_create_window(char *title)
730          if (sizehints)          if (sizehints)
731          {          {
732                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
733                  sizehints->min_width = sizehints->max_width = width;                  sizehints->min_width = sizehints->max_width = g_width;
734                  sizehints->min_height = sizehints->max_height = height;                  sizehints->min_height = sizehints->max_height = g_height;
735                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
736                  XFree(sizehints);                  XFree(sizehints);
737          }          }
738    
739          xkeymap_init();          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
740                    VisibilityChangeMask | FocusChangeMask;
741    
742          input_mask = KeyPressMask | KeyReleaseMask |          if (g_sendmotion)
                          ButtonPressMask | ButtonReleaseMask |  
                          EnterWindowMask | LeaveWindowMask | KeymapStateMask;  
         if (sendmotion)  
743                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
744            if (g_ownbackstore)
         if (ownbackstore)  
745                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
746            if (g_fullscreen || g_grab_keyboard)
747                    input_mask |= EnterWindowMask;
748            if (g_grab_keyboard)
749                    input_mask |= LeaveWindowMask;
750    
751          XSelectInput(display, wnd, input_mask);          if (g_IM != NULL)
752          gc = XCreateGC(display, wnd, 0, NULL);          {
753                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
754          if (ownbackstore)                                   XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
                 backstore = XCreatePixmap(display, wnd, width, height, depth);  
755    
756          XMapWindow(display, wnd);                  if ((g_IC != NULL)
757                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
758                            input_mask |= ic_input_mask;
759            }
760    
761          /* TODO: error texts... make them friendly. */          XSelectInput(g_display, g_wnd, input_mask);
762          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);          XMapWindow(g_display, g_wnd);
         if ((int)xkb == BadAlloc || xkb == NULL)  
         {  
                         error( "XkbGetKeyboard failed.\n");  
                         exit(0);  
         }  
763    
764          /* TODO: error texts... make them friendly. */          /* wait for VisibilityNotify */
765          if( XkbSelectEvents(display, xkb->device_spec, XkbAllEventsMask, XkbAllEventsMask) == False )          do
766          {          {
767                          error( "XkbSelectEvents failed.\n");                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
                         exit(0);  
768          }          }
769            while (xevent.type != VisibilityNotify);
770    
771            g_focused = False;
772            g_mouse_in_wnd = False;
773    
774            /* handle the WM_DELETE_WINDOW protocol */
775            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
776            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
777            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
778    
779          return True;          return True;
780  }  }
781    
782  void  void
783  ui_destroy_window()  ui_destroy_window(void)
784  {  {
785          if( xkb != NULL )          if (g_IC != NULL)
786                  XkbFreeKeyboard(xkb, XkbAllControlsMask, True);                  XDestroyIC(g_IC);
787    
788          if (ownbackstore)          XDestroyWindow(g_display, g_wnd);
789                  XFreePixmap(display, backstore);  }
790    
791    void
792    xwin_toggle_fullscreen(void)
793    {
794            Pixmap contents = 0;
795    
796            if (!g_ownbackstore)
797            {
798                    /* need to save contents of window */
799                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
800                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
801            }
802    
803          XFreeGC(display, gc);          ui_destroy_window();
804          XDestroyWindow(display, wnd);          g_fullscreen = !g_fullscreen;
805          XCloseDisplay(display);          ui_create_window();
806          display = NULL;  
807            XDefineCursor(g_display, g_wnd, g_current_cursor);
808    
809            if (!g_ownbackstore)
810            {
811                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
812                    XFreePixmap(g_display, contents);
813            }
814  }  }
815    
816  static void  /* Process all events in Xlib queue
817  xwin_process_events()     Returns 0 after user quit, 1 otherwise */
818    static int
819    xwin_process_events(void)
820  {  {
821          XkbEvent xkbevent;          XEvent xevent;
           
822          KeySym keysym;          KeySym keysym;
         uint8 scancode;  
823          uint16 button, flags;          uint16 button, flags;
824          uint32 ev_time;          uint32 ev_time;
825          uint32 tmpmods;          key_translation tr;
826            char str[256];
827          if (display == NULL)          Status status;
828                  return;          unsigned int state;
829            Window wdummy;
830            int dummy;
831    
832          while (XCheckMaskEvent(display, ~0, &xkbevent.core))          while (XPending(g_display) > 0)
833          {          {
834                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
835    
836                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
837                    {
838                            DEBUG_KBD(("Filtering event\n"));
839                            continue;
840                    }
841    
842                  flags = 0;                  flags = 0;
843    
844                  switch (xkbevent.type)                  switch (xevent.type)
845                  {                  {
846                          case KeymapNotify:                          case ClientMessage:
847                                  /* TODO:                                  /* the window manager told us to quit */
848                                   * read modifier status at focus in, and update the local masks, and the other end as well..                                  if ((xevent.xclient.message_type == g_protocol_atom)
849                                   * if not, we may get out of sync.                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
850                                   * xkbevent.core.xkeymap.key_vector                                          /* Quit */
851                                   * char key_vector[32];                                          return 0;
                                  */  
852                                  break;                                  break;
853    
                         case KeyRelease:  
                                 flags = KBD_FLAG_DOWN | KBD_FLAG_UP;  
                                 /* fall through */  
   
854                          case KeyPress:                          case KeyPress:
855                                  if( XkbTranslateKeyCode(xkb, xkbevent.core.xkey.keycode, xkbevent.core.xkey.state, &tmpmods, &keysym) == False )                                  g_last_gesturetime = xevent.xkey.time;
856                                    if (g_IC != NULL)
857                                            /* Multi_key compatible version */
858                                    {
859                                            XmbLookupString(g_IC,
860                                                            &xevent.xkey, str, sizeof(str), &keysym,
861                                                            &status);
862                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
863                                            {
864                                                    error("XmbLookupString failed with status 0x%x\n",
865                                                          status);
866                                                    break;
867                                            }
868                                    }
869                                    else
870                                    {
871                                            /* Plain old XLookupString */
872                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
873                                            XLookupString((XKeyEvent *) & xevent,
874                                                          str, sizeof(str), &keysym, NULL);
875                                    }
876    
877                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
878                                               get_ksname(keysym)));
879    
880                                    ev_time = time(NULL);
881                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
882                                          break;                                          break;
                                 scancode = xkeymap_translate_key(keysym, xkbevent.core.xkey.keycode, &flags);  
883    
884                                  if (scancode == 0 )                                  tr = xkeymap_translate_key(keysym,
885                                                               xevent.xkey.keycode, xevent.xkey.state);
886    
887                                    if (tr.scancode == 0)
888                                          break;                                          break;
889    
890                                  /* keep track of the modifiers -- needed for stickykeys... */                                  save_remote_modifiers(tr.scancode);
891                                  if( xkbevent.type == KeyPress )                                  ensure_remote_modifiers(ev_time, tr);
892                                          xwin_press_modifiers( &xkbevent.core.xkey, ev_time, scancode );                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
893                                    restore_remote_modifiers(ev_time, tr.scancode);
894    
895                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);                                  break;
896    
897                            case KeyRelease:
898                                    g_last_gesturetime = xevent.xkey.time;
899                                    XLookupString((XKeyEvent *) & xevent, str,
900                                                  sizeof(str), &keysym, NULL);
901    
902                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
903                                               get_ksname(keysym)));
904    
905                                  if( xkbevent.type == KeyRelease )                                  ev_time = time(NULL);
906                                          xwin_release_modifiers( &xkbevent.core.xkey, ev_time, scancode );                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
907                                            break;
908    
909                                    tr = xkeymap_translate_key(keysym,
910                                                               xevent.xkey.keycode, xevent.xkey.state);
911    
912                                    if (tr.scancode == 0)
913                                            break;
914    
915                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
916                                  break;                                  break;
917    
918                          case ButtonPress:                          case ButtonPress:
# Line 444  xwin_process_events() Line 920  xwin_process_events()
920                                  /* fall through */                                  /* fall through */
921    
922                          case ButtonRelease:                          case ButtonRelease:
923                                  button = xkeymap_translate_button(xkbevent.core.xbutton.button);                                  g_last_gesturetime = xevent.xbutton.time;
924                                    button = xkeymap_translate_button(xevent.xbutton.button);
925                                  if (button == 0)                                  if (button == 0)
926                                          break;                                          break;
927    
928                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
929                                                 flags | button,                                  if (xevent.xbutton.y < g_win_button_size)
930                                                 xkbevent.core.xbutton.x,                                  {
931                                                 xkbevent.core.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
932                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
933                                                    g_moving_wnd = False;
934    
935                                            /*  Check from right to left: */
936    
937                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
938                                            {
939                                                    /* The close button, continue */
940                                                    ;
941                                            }
942                                            else if (xevent.xbutton.x >=
943                                                     g_width - g_win_button_size * 2)
944                                            {
945                                                    /* The maximize/restore button. Do not send to
946                                                       server.  It might be a good idea to change the
947                                                       cursor or give some other visible indication
948                                                       that rdesktop inhibited this click */
949                                                    break;
950                                            }
951                                            else if (xevent.xbutton.x >=
952                                                     g_width - g_win_button_size * 3)
953                                            {
954                                                    /* The minimize button. Iconify window. */
955                                                    XIconifyWindow(g_display, g_wnd,
956                                                                   DefaultScreen(g_display));
957                                                    break;
958                                            }
959                                            else if (xevent.xbutton.x <= g_win_button_size)
960                                            {
961                                                    /* The system menu. Ignore. */
962                                                    break;
963                                            }
964                                            else
965                                            {
966                                                    /* The title bar. */
967                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
968                                                        && g_hide_decorations)
969                                                    {
970                                                            g_moving_wnd = True;
971                                                            g_move_x_offset = xevent.xbutton.x;
972                                                            g_move_y_offset = xevent.xbutton.y;
973                                                    }
974                                                    break;
975    
976                                            }
977                                    }
978    
979                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
980                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
981                                  break;                                  break;
982    
983                          case MotionNotify:                          case MotionNotify:
984                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_moving_wnd)
985                                                 MOUSE_FLAG_MOVE,                                  {
986                                                 xkbevent.core.xmotion.x,                                          XMoveWindow(g_display, g_wnd,
987                                                 xkbevent.core.xmotion.y);                                                      xevent.xmotion.x_root - g_move_x_offset,
988                                                        xevent.xmotion.y_root - g_move_y_offset);
989                                            break;
990                                    }
991    
992                                    if (g_fullscreen && !g_focused)
993                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
994                                                           CurrentTime);
995                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
996                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
997                                    break;
998    
999                            case FocusIn:
1000                                    if (xevent.xfocus.mode == NotifyGrab)
1001                                            break;
1002                                    g_focused = True;
1003                                    XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,
1004                                                  &dummy, &dummy, &state);
1005                                    reset_modifier_keys(state);
1006                                    if (g_grab_keyboard && g_mouse_in_wnd)
1007                                            XGrabKeyboard(g_display, g_wnd, True,
1008                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1009                                    break;
1010    
1011                            case FocusOut:
1012                                    if (xevent.xfocus.mode == NotifyUngrab)
1013                                            break;
1014                                    g_focused = False;
1015                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1016                                            XUngrabKeyboard(g_display, CurrentTime);
1017                                  break;                                  break;
1018    
1019                          case EnterNotify:                          case EnterNotify:
1020                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
1021                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
1022                                    g_mouse_in_wnd = True;
1023                                    if (g_fullscreen)
1024                                    {
1025                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1026                                                           CurrentTime);
1027                                            break;
1028                                    }
1029                                    if (g_focused)
1030                                            XGrabKeyboard(g_display, g_wnd, True,
1031                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1032                                  break;                                  break;
1033    
1034                          case LeaveNotify:                          case LeaveNotify:
1035                                  XUngrabKeyboard(display, CurrentTime);                                  /* we only register for this event when grab_keyboard */
1036                                    g_mouse_in_wnd = False;
1037                                    XUngrabKeyboard(g_display, CurrentTime);
1038                                  break;                                  break;
1039    
1040                          case Expose:                          case Expose:
1041                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1042                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
1043                                            xkbevent.core.xexpose.width, xkbevent.core.xexpose.height,                                            xevent.xexpose.width,
1044                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y);                                            xevent.xexpose.height,
1045                                              xevent.xexpose.x, xevent.xexpose.y);
1046                                  break;                                  break;
                 }  
         }  
 }  
   
 void  
 xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)  
 {  
         switch (scancode) {  
         case 0x2a:  
                 key_down_state &= ~DShift1Mask;  
                 break;  
         case 0x36:  
                 key_down_state &= ~DShift2Mask;  
                 break;  
         case 0x1d:  
                 key_down_state &= ~DControl1Mask;  
                 break;  
         case 0x9d:  
                 key_down_state &= ~DControl2Mask;  
                 break;  
         case 0x38:  
                 key_down_state &= ~DMod1Mask;  
                 break;  
         case 0xb8:  
                 key_down_state &= ~DMod2Mask;  
                 break;  
         }  
   
         if( !(ShiftMask & ev->state) && (key_down_state & DShift1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a, 0);  
                 key_down_state &= ~DShift1Mask;  
   
         }  
   
         if( !(ControlMask & ev->state) && (key_down_state & DControl1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d, 0);  
                 key_down_state &= ~DControl1Mask;  
   
         }  
           
         if( !(Mod1Mask & ev->state) && (key_down_state & DMod1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38, 0);  
                 key_down_state &= ~DMod1Mask;  
   
         }  
           
         if( !(Mod2Mask & ev->state) && (key_down_state & DMod2Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8, 0);  
                 key_down_state &= ~DMod2Mask;  
         }  
 }  
   
   
 void  
 xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)  
 {  
         key_modifier_state = ev->state;  
   
         switch (scancode) {  
         case 0x2a:  
                 key_down_state |= DShift1Mask;  
                 break;  
         case 0x36:  
                 key_down_state |= DShift2Mask;  
                 break;  
         case 0x1d:  
                 key_down_state |= DControl1Mask;  
                 break;  
         case 0x9d:  
                 key_down_state |= DControl2Mask;  
                 break;  
         case 0x38:  
                 key_down_state |= DMod1Mask;  
                 break;  
         case 0xb8:  
                 key_down_state |= DMod2Mask;  
                 break;  
         }  
   
         if( (ShiftMask & ev->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 & ev->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;  
1047    
1048          }                          case MappingNotify:
1049                                    /* Refresh keyboard mapping if it has changed. This is important for
1050          if( (Mod1Mask & ev->state) && !(key_down_state & DMod1Mask))                                     Xvnc, since it allocates keycodes dynamically */
1051          {                                  if (xevent.xmapping.request == MappingKeyboard
1052                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x38, 0);                                      || xevent.xmapping.request == MappingModifier)
1053                  key_down_state |= DMod1Mask;                                          XRefreshKeyboardMapping(&xevent.xmapping);
   
         }  
1054    
1055          if( (Mod2Mask & ev->state) && !(key_down_state & DMod2Mask))                                  if (xevent.xmapping.request == MappingModifier)
1056          {                                  {
1057                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0xb8, 0);                                          XFreeModifiermap(g_mod_map);
1058                  key_down_state |= DMod2Mask;                                          g_mod_map = XGetModifierMapping(g_display);
1059                                    }
1060                                    break;
1061    
1062                                    /* clipboard stuff */
1063                            case SelectionNotify:
1064                                    xclip_handle_SelectionNotify(&xevent.xselection);
1065                                    break;
1066                            case SelectionRequest:
1067                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1068                                    break;
1069                            case SelectionClear:
1070                                    xclip_handle_SelectionClear();
1071                                    break;
1072                            case PropertyNotify:
1073                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1074                                    break;
1075                    }
1076          }          }
1077            /* Keep going */
1078            return 1;
1079  }  }
1080    
1081  void  /* Returns 0 after user quit, 1 otherwise */
1082    int
1083  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1084  {  {
1085          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;
1086          fd_set rfds;          fd_set rfds, wfds;
   
         XFlush(display);  
   
         FD_ZERO(&rfds);  
1087    
1088          while (True)          while (True)
1089          {          {
1090                    /* Process any events already waiting */
1091                    if (!xwin_process_events())
1092                            /* User quit */
1093                            return 0;
1094    
1095                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1096                    FD_ZERO(&wfds);
1097                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1098                  FD_SET(x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
1099    
1100    #ifdef WITH_RDPSND
1101                    /* FIXME: there should be an API for registering fds */
1102                    if (g_dsp_busy)
1103                    {
1104                            FD_SET(g_dsp_fd, &wfds);
1105                            n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1106                    }
1107    #endif
1108    
1109                  switch (select(n, &rfds, NULL, NULL, NULL))                  switch (select(n, &rfds, &wfds, NULL, NULL))
1110                  {                  {
1111                          case -1:                          case -1:
1112                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
# Line 613  ui_select(int rdp_socket) Line 1115  ui_select(int rdp_socket)
1115                                  continue;                                  continue;
1116                  }                  }
1117    
                 if (FD_ISSET(x_socket, &rfds))  
                         xwin_process_events();  
   
1118                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1119                          return;                          return 1;
1120    
1121    #ifdef WITH_RDPSND
1122                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1123                            wave_out_play();
1124    #endif
1125          }          }
1126  }  }
1127    
1128  void  void
1129  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1130  {  {
1131          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1132  }  }
1133    
1134  HBITMAP  HBITMAP
1135  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1136  {  {
1137          XImage *image;          XImage *image;
1138          Pixmap bitmap;          Pixmap bitmap;
1139          uint8 *tdata;          uint8 *tdata;
1140    
1141          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1142          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1143          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1144                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1145    
1146          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1147    
1148          XFree(image);          XFree(image);
1149          if (!owncolmap)          if (!g_owncolmap)
1150                  xfree(tdata);                  xfree(tdata);
1151          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1152  }  }
1153    
1154  void  void
1155  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)  
1156  {  {
1157          XImage *image;          XImage *image;
1158          uint8 *tdata;          uint8 *tdata;
1159            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1160            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1161                                 (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1162    
1163          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)  
1164          {          {
1165                  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);
1166                  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);
1167          }          }
1168          else          else
1169          {          {
1170                  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);
1171          }          }
1172    
1173          XFree(image);          XFree(image);
1174          if (!owncolmap)          if (!g_owncolmap)
1175                  xfree(tdata);                  xfree(tdata);
1176  }  }
1177    
1178  void  void
1179  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1180  {  {
1181          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1182  }  }
1183    
1184  HGLYPH  HGLYPH
1185  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1186  {  {
1187          XImage *image;          XImage *image;
1188          Pixmap bitmap;          Pixmap bitmap;
# Line 689  ui_create_glyph(int width, int height, u Line 1191  ui_create_glyph(int width, int height, u
1191    
1192          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1193    
1194          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1195          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(g_display, bitmap, 0, NULL);
1196    
1197          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1198                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1199          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1200          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1201          XInitImage(image);          XInitImage(image);
1202    
1203          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1204    
1205          XFree(image);          XFree(image);
1206          XFreeGC(display, gc);          XFreeGC(g_display, gc);
1207          return (HGLYPH)bitmap;          return (HGLYPH) bitmap;
1208  }  }
1209    
1210  void  void
1211  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1212  {  {
1213          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1214  }  }
1215    
1216  HCURSOR  HCURSOR
1217  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1218                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1219  {  {
1220          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1221          XColor bg, fg;          XColor bg, fg;
# Line 727  ui_create_cursor(unsigned int x, unsigne Line 1229  ui_create_cursor(unsigned int x, unsigne
1229          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1230          offset = scanline * height;          offset = scanline * height;
1231    
1232          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1233          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1234    
1235          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1236          memset(mask, 0, offset);          memset(mask, 0, offset);
1237    
1238          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 770  ui_create_cursor(unsigned int x, unsigne Line 1272  ui_create_cursor(unsigned int x, unsigne
1272    
1273          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1274          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1275            
1276          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
1277                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1278                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1279    
1280          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1281          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
1282          xfree(mask);          xfree(mask);
1283          xfree(cursor);          xfree(cursor);
1284          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1285  }  }
1286    
1287  void  void
1288  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1289  {  {
1290          XDefineCursor(display, wnd, (Cursor)cursor);          g_current_cursor = (Cursor) cursor;
1291            XDefineCursor(g_display, g_wnd, g_current_cursor);
1292  }  }
1293    
1294  void  void
1295  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1296  {  {
1297          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(g_display, (Cursor) cursor);
1298  }  }
1299    
1300  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 799  ui_destroy_cursor(HCURSOR cursor) Line 1303  ui_destroy_cursor(HCURSOR cursor)
1303                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1304                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1305    
1306    
1307  HCOLOURMAP  HCOLOURMAP
1308  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
1309  {  {
1310          COLOURENTRY *entry;          COLOURENTRY *entry;
1311          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1312            if (!g_owncolmap)
         if (owncolmap)  
1313          {          {
1314                  XColor *xcolours, *xentry;                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1315                  Colormap map;                  XColor xentry;
1316                    XColor xc_cache[256];
1317                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  uint32 colour;
1318                    int colLookup = 256;
1319                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1320                  {                  {
1321                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1322                          xentry = &xcolours[i];                          MAKE_XCOLOR(&xentry, entry);
1323                          xentry->pixel = i;  
1324                          MAKE_XCOLOR(xentry, entry);                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1325                  }                          {
1326                                    /* Allocation failed, find closest match. */
1327                                    int j = 256;
1328                                    int nMinDist = 3 * 256 * 256;
1329                                    long nDist = nMinDist;
1330    
1331                  map = XCreateColormap(display, wnd, visual, AllocAll);                                  /* only get the colors once */
1332                  XStoreColors(display, map, xcolours, ncolours);                                  while (colLookup--)
1333                                    {
1334                                            xc_cache[colLookup].pixel = colLookup;
1335                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1336                                                    xc_cache[colLookup].blue = 0;
1337                                            xc_cache[colLookup].flags = 0;
1338                                            XQueryColor(g_display,
1339                                                        DefaultColormap(g_display,
1340                                                                        DefaultScreen(g_display)),
1341                                                        &xc_cache[colLookup]);
1342                                    }
1343                                    colLookup = 0;
1344    
1345                  xfree(xcolours);                                  /* approximate the pixel */
1346                  return (HCOLOURMAP)map;                                  while (j--)
1347                                    {
1348                                            if (xc_cache[j].flags)
1349                                            {
1350                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1351                                                             (long) (xentry.red >> 8)) *
1352                                                            ((long) (xc_cache[j].red >> 8) -
1353                                                             (long) (xentry.red >> 8)) +
1354                                                            ((long) (xc_cache[j].green >> 8) -
1355                                                             (long) (xentry.green >> 8)) *
1356                                                            ((long) (xc_cache[j].green >> 8) -
1357                                                             (long) (xentry.green >> 8)) +
1358                                                            ((long) (xc_cache[j].blue >> 8) -
1359                                                             (long) (xentry.blue >> 8)) *
1360                                                            ((long) (xc_cache[j].blue >> 8) -
1361                                                             (long) (xentry.blue >> 8));
1362                                            }
1363                                            if (nDist < nMinDist)
1364                                            {
1365                                                    nMinDist = nDist;
1366                                                    xentry.pixel = j;
1367                                            }
1368                                    }
1369                            }
1370                            colour = xentry.pixel;
1371    
1372                            /* update our cache */
1373                            if (xentry.pixel < 256)
1374                            {
1375                                    xc_cache[xentry.pixel].red = xentry.red;
1376                                    xc_cache[xentry.pixel].green = xentry.green;
1377                                    xc_cache[xentry.pixel].blue = xentry.blue;
1378    
1379                            }
1380    
1381    
1382                            /* byte swap here to make translate_image faster */
1383                            map[i] = translate_colour(colour);
1384                    }
1385                    return map;
1386          }          }
1387          else          else
1388          {          {
1389                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  XColor *xcolours, *xentry;
1390                  XColor xentry;                  Colormap map;
                 uint32 colour;  
1391    
1392                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1393                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1394                  {                  {
1395                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1396                          MAKE_XCOLOR(&xentry, entry);                          xentry = &xcolours[i];
1397                            xentry->pixel = i;
1398                          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);  
1399                  }                  }
1400    
1401                  return map;                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1402                    XStoreColors(g_display, map, xcolours, ncolours);
1403    
1404                    xfree(xcolours);
1405                    return (HCOLOURMAP) map;
1406          }          }
1407  }  }
1408    
1409  void  void
1410  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1411  {  {
1412          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1413                  xfree(map);                  xfree(map);
1414            else
1415                    XFreeColormap(g_display, (Colormap) map);
1416  }  }
1417    
1418  void  void
1419  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1420  {  {
1421          if (owncolmap)          if (!g_owncolmap)
1422                  XSetWindowColormap(display, wnd, (Colormap)map);          {
1423                    if (g_colmap)
1424                            xfree(g_colmap);
1425    
1426                    g_colmap = (uint32 *) map;
1427            }
1428          else          else
1429                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1430  }  }
1431    
1432  void  void
# Line 876  ui_set_clip(int x, int y, int cx, int cy Line 1438  ui_set_clip(int x, int y, int cx, int cy
1438          rect.y = y;          rect.y = y;
1439          rect.width = cx;          rect.width = cx;
1440          rect.height = cy;          rect.height = cy;
1441          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1442  }  }
1443    
1444  void  void
1445  ui_reset_clip()  ui_reset_clip(void)
1446  {  {
1447          XRectangle rect;          XRectangle rect;
1448    
1449          rect.x = 0;          rect.x = 0;
1450          rect.y = 0;          rect.y = 0;
1451          rect.width = width;          rect.width = g_width;
1452          rect.height = height;          rect.height = g_height;
1453          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1454  }  }
1455    
1456  void  void
1457  ui_bell()  ui_bell(void)
1458  {  {
1459          XBell(display, 0);          XBell(g_display, 0);
1460  }  }
1461    
1462  void  void
# Line 906  ui_destblt(uint8 opcode, Line 1468  ui_destblt(uint8 opcode,
1468          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1469  }  }
1470    
1471    static uint8 hatch_patterns[] = {
1472            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1473            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1474            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1475            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1476            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1477            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1478    };
1479    
1480  void  void
1481  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1482            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1483            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1484  {  {
1485          Pixmap fill;          Pixmap fill;
1486            uint8 i, ipattern[8];
1487    
1488          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1489    
# Line 922  ui_patblt(uint8 opcode, Line 1494  ui_patblt(uint8 opcode,
1494                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1495                          break;                          break;
1496    
1497                    case 2: /* Hatch */
1498                            fill = (Pixmap) ui_create_glyph(8, 8,
1499                                                            hatch_patterns + brush->pattern[0] * 8);
1500                            SET_FOREGROUND(bgcolour);
1501                            SET_BACKGROUND(fgcolour);
1502                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1503                            XSetStipple(g_display, g_gc, fill);
1504                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1505                            FILL_RECTANGLE(x, y, cx, cy);
1506                            XSetFillStyle(g_display, g_gc, FillSolid);
1507                            XSetTSOrigin(g_display, g_gc, 0, 0);
1508                            ui_destroy_glyph((HGLYPH) fill);
1509                            break;
1510    
1511                  case 3: /* Pattern */                  case 3: /* Pattern */
1512                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
1513                                    ipattern[7 - i] = brush->pattern[i];
1514                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1515    
1516                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1517                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
1518                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1519                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
1520                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1521    
1522                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1523    
1524                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
1525                          ui_destroy_glyph((HGLYPH)fill);                          XSetTSOrigin(g_display, g_gc, 0, 0);
1526                            ui_destroy_glyph((HGLYPH) fill);
1527                          break;                          break;
1528    
1529                  default:                  default:
# Line 950  ui_screenblt(uint8 opcode, Line 1539  ui_screenblt(uint8 opcode,
1539               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1540  {  {
1541          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1542          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);
1543          if (ownbackstore)          if (g_ownbackstore)
1544                  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);  
1545          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1546  }  }
1547    
# Line 963  ui_memblt(uint8 opcode, Line 1551  ui_memblt(uint8 opcode,
1551            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1552  {  {
1553          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1554          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);
1555          if (ownbackstore)          if (g_ownbackstore)
1556                  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);  
1557          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1558  }  }
1559    
# Line 974  void Line 1561  void
1561  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1562            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1563            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1564            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1565  {  {
1566          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1567             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 983  ui_triblt(uint8 opcode, Line 1570  ui_triblt(uint8 opcode,
1570          {          {
1571                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1572                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1573                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1574                          break;                          break;
1575    
1576                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1577                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1578                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1579                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1580                          break;                          break;
1581    
1582                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1583                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1584                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1585                          break;                          break;
1586    
1587                  default:                  default:
# Line 1010  ui_triblt(uint8 opcode, Line 1593  ui_triblt(uint8 opcode,
1593  void  void
1594  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1595          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1596          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1597  {  {
1598          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1599          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
1600          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1601          if (ownbackstore)          if (g_ownbackstore)
1602                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1603          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1604  }  }
1605    
# Line 1029  ui_rect( Line 1612  ui_rect(
1612          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1613  }  }
1614    
1615    /* warning, this function only draws on wnd or backstore, not both */
1616  void  void
1617  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1618                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1619                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1620                int fgcolour)                int bgcolour, int fgcolour)
1621  {  {
1622          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1623          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1624    
1625          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
1626                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1627          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
1628          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
1629    
1630          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1631    
1632          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
1633  }  }
1634    
1635  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
# Line 1057  ui_draw_glyph(int mixmode, Line 1641  ui_draw_glyph(int mixmode,
1641        if ((xyoffset & 0x80))\        if ((xyoffset & 0x80))\
1642          {\          {\
1643            if (flags & TEXT2_VERTICAL) \            if (flags & TEXT2_VERTICAL) \
1644              y += ttext[++idx] | (ttext[++idx] << 8);\              y += ttext[idx+1] | (ttext[idx+2] << 8);\
1645            else\            else\
1646              x += ttext[++idx] | (ttext[++idx] << 8);\              x += ttext[idx+1] | (ttext[idx+2] << 8);\
1647              idx += 2;\
1648          }\          }\
1649        else\        else\
1650          {\          {\
# Line 1071  ui_draw_glyph(int mixmode, Line 1656  ui_draw_glyph(int mixmode,
1656      }\      }\
1657    if (glyph != NULL)\    if (glyph != NULL)\
1658      {\      {\
1659        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        ui_draw_glyph (mixmode, x + glyph->offset,\
1660                       y + (short) glyph->baseline,\                       y + glyph->baseline,\
1661                       glyph->width, glyph->height,\                       glyph->width, glyph->height,\
1662                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1663        if (flags & TEXT2_IMPLICIT_X)\        if (flags & TEXT2_IMPLICIT_X)\
# Line 1082  ui_draw_glyph(int mixmode, Line 1667  ui_draw_glyph(int mixmode,
1667    
1668  void  void
1669  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,
1670               int clipx, int clipy, int clipcx, int clipcy, int boxx,               int clipx, int clipy, int clipcx, int clipcy,
1671               int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1672               int fgcolour, uint8 * text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1673  {  {
1674          FONTGLYPH *glyph;          FONTGLYPH *glyph;
# Line 1094  ui_draw_text(uint8 font, uint8 flags, in Line 1679  ui_draw_text(uint8 font, uint8 flags, in
1679    
1680          if (boxcx > 1)          if (boxcx > 1)
1681          {          {
1682                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1683          }          }
1684          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1685          {          {
1686                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1687          }          }
1688    
1689          /* Paint text, character by character */          /* Paint text, character by character */
1690          for (i = 0; i < length;) {          for (i = 0; i < length;)
1691                  switch (text[i]) {          {
1692                  case 0xff:                  switch (text[i])
1693                          if (i + 2 < length)                  {
1694                                  cache_put_text(text[i + 1], text, text[i + 2]);                          case 0xff:
1695                          else {                                  if (i + 2 < length)
1696                                  error("this shouldn't be happening\n");                                          cache_put_text(text[i + 1], text, text[i + 2]);
1697                                    else
1698                                    {
1699                                            error("this shouldn't be happening\n");
1700                                            exit(1);
1701                                    }
1702                                    /* this will move pointer from start to first character after FF command */
1703                                    length -= i + 3;
1704                                    text = &(text[i + 3]);
1705                                    i = 0;
1706                                  break;                                  break;
                         }  
                         /* this will move pointer from start to first character after FF command */  
                         length -= i + 3;  
                         text = &(text[i + 3]);  
                         i = 0;  
                         break;  
1707    
1708                  case 0xfe:                          case 0xfe:
1709                          entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
1710                          if (entry != NULL) {                                  if (entry != NULL)
1711                                  if ((((uint8 *) (entry->data))[1] == 0)                                  {
1712                                      && (!(flags & TEXT2_IMPLICIT_X))) {                                          if ((((uint8 *) (entry->data))[1] ==
1713                                          if (flags & TEXT2_VERTICAL)                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1714                                                  y += text[i + 2];                                          {
1715                                          else                                                  if (flags & TEXT2_VERTICAL)
1716                                                  x += text[i + 2];                                                          y += text[i + 2];
1717                                                    else
1718                                                            x += text[i + 2];
1719                                            }
1720                                            for (j = 0; j < entry->size; j++)
1721                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1722                                  }                                  }
1723                                  if (i + 2 < length)                                  if (i + 2 < length)
1724                                          i += 3;                                          i += 3;
1725                                  else                                  else
1726                                          i += 2;                                          i += 2;
1727                                  length -= i;                                  length -= i;
1728                                  /* this will move pointer from start to first character after FE command */                                  /* this will move pointer from start to first character after FE command */
1729                                  text = &(text[i]);                                  text = &(text[i]);
1730                                  i = 0;                                  i = 0;
1731                                  for (j = 0; j < entry->size; j++)                                  break;
                                         DO_GLYPH(((uint8 *) (entry->data)), j);  
                         }  
                         break;  
1732    
1733                  default:                          default:
1734                          DO_GLYPH(text, i);                                  DO_GLYPH(text, i);
1735                          i++;                                  i++;
1736                          break;                                  break;
1737                  }                  }
1738          }          }
1739            if (g_ownbackstore)
1740            {
1741                    if (boxcx > 1)
1742                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1743                                      boxy, boxcx, boxcy, boxx, boxy);
1744                    else
1745                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1746                                      clipy, clipcx, clipcy, clipx, clipy);
1747            }
1748  }  }
1749    
1750  void  void
# Line 1156  ui_desktop_save(uint32 offset, int x, in Line 1753  ui_desktop_save(uint32 offset, int x, in
1753          Pixmap pix;          Pixmap pix;
1754          XImage *image;          XImage *image;
1755    
1756          if (ownbackstore)          if (g_ownbackstore)
1757          {          {
1758                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1759          }          }
1760          else          else
1761          {          {
1762                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1763                  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);
1764                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1765                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
1766          }          }
1767    
1768          offset *= bpp/8;          offset *= g_bpp / 8;
1769          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);  
1770    
1771          XDestroyImage(image);          XDestroyImage(image);
1772  }  }
# Line 1183  ui_desktop_restore(uint32 offset, int x, Line 1777  ui_desktop_restore(uint32 offset, int x,
1777          XImage *image;          XImage *image;
1778          uint8 *data;          uint8 *data;
1779    
1780          offset *= bpp/8;          offset *= g_bpp / 8;
1781          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1782          if (data == NULL)          if (data == NULL)
1783                  return;                  return;
1784    
1785          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1786                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * bpp/8);  
1787    
1788          if (ownbackstore)          if (g_ownbackstore)
1789          {          {
1790                  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);
1791                  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);
1792          }          }
1793          else          else
1794          {          {
1795                  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);
1796          }          }
1797    
1798          XFree(image);          XFree(image);

Legend:
Removed from v.52  
changed lines
  Added in v.478

  ViewVC Help
Powered by ViewVC 1.1.26