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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26