/[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 42 by matthewc, Sun Apr 7 09:42:54 2002 UTC revision 415 by forsberg, Fri Jun 6 11:10:48 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
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 23  Line 23 
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    
 extern char keymapname[16];  
 extern int keylayout;  
28  extern int width;  extern int width;
29  extern int height;  extern int height;
30  extern BOOL sendmotion;  extern BOOL sendmotion;
31  extern BOOL fullscreen;  extern BOOL fullscreen;
32    extern BOOL grab_keyboard;
33    extern BOOL hide_decorations;
34    extern char title[];
35    extern int server_bpp;
36    extern int win_button_size;
37    BOOL enable_compose = False;
38    BOOL focused;
39    BOOL mouse_in_wnd;
40    
41  static Display *display;  Display *display;
42    Time last_gesturetime;
43  static int x_socket;  static int x_socket;
44  static Window wnd;  static Screen *screen;
45    Window wnd;
46  static GC gc;  static GC gc;
47  static Visual *visual;  static Visual *visual;
48  static int depth;  static int depth;
49  static int bpp;  static int bpp;
50    static XIM IM;
51    static XIC IC;
52    static XModifierKeymap *mod_map;
53    static Cursor current_cursor;
54    static Atom protocol_atom, kill_atom;
55    static long input_mask;         /* Needs to be global since we access it in
56                                       both ui_create_window and the PropertyNotify
57                                       callback functions */
58    
59  /* endianness */  /* endianness */
60  static BOOL host_be;  static BOOL host_be;
# Line 47  static BOOL xserver_be; Line 64  static BOOL xserver_be;
64  static BOOL ownbackstore;  static BOOL ownbackstore;
65  static Pixmap backstore;  static Pixmap backstore;
66    
67    /* Moving in single app mode */
68    static BOOL moving_wnd;
69    static int move_x_offset = 0;
70    static int move_y_offset = 0;
71    
72    /* MWM decorations */
73    #define MWM_HINTS_DECORATIONS   (1L << 1)
74    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
75    typedef struct
76    {
77            uint32 flags;
78            uint32 functions;
79            uint32 decorations;
80            sint32 inputMode;
81            uint32 status;
82    }
83    PropMotifWmHints;
84    
85    typedef struct
86    {
87            uint32 red;
88            uint32 green;
89            uint32 blue;
90    }
91    PixelColour;
92    
93    struct _PropNotifyCb;
94    
95    typedef struct _PropNotifyCb
96    {
97            Window wnd;
98            Atom atom;
99            void (*callback) (XPropertyEvent *);
100            struct _PropNotifyCb *next;
101    }
102    PropNotifyCb;
103    
104    
105    static PropNotifyCb *propnotify_callbacks = NULL;
106    
107    
108  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
109  { \  { \
110          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(display, wnd, gc, x, y, cx, cy); \
# Line 54  static Pixmap backstore; Line 112  static Pixmap backstore;
112                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \
113  }  }
114    
115    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
116    { \
117            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
118    }
119    
120  /* colour maps */  /* colour maps */
121  static BOOL owncolmap;  BOOL owncolmap = False;
122  static Colormap xcolmap;  static Colormap xcolmap;
 static uint32 white;  
123  static uint32 *colmap;  static uint32 *colmap;
124    
125  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
126  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
127  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
128    
# Line 87  static int rop2_map[] = { Line 149  static int rop2_map[] = {
149  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
150    
151  static void  static void
152  translate8(uint8 *data, uint8 *out, uint8 *end)  mwm_hide_decorations(void)
153    {
154            PropMotifWmHints motif_hints;
155            Atom hintsatom;
156    
157            /* setup the property */
158            motif_hints.flags = MWM_HINTS_DECORATIONS;
159            motif_hints.decorations = 0;
160    
161            /* get the atom for the property */
162            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
163            if (!hintsatom)
164            {
165                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
166                    return;
167            }
168    
169            XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
170                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
171    }
172    
173    static PixelColour
174    split_colour15(uint32 colour)
175    {
176            PixelColour rv;
177            rv.red = (colour & 0x7c00) >> 10;
178            rv.red = (rv.red * 0xff) / 0x1f;
179            rv.green = (colour & 0x03e0) >> 5;
180            rv.green = (rv.green * 0xff) / 0x1f;
181            rv.blue = (colour & 0x1f);
182            rv.blue = (rv.blue * 0xff) / 0x1f;
183            return rv;
184    }
185    
186    static PixelColour
187    split_colour16(uint32 colour)
188    {
189            PixelColour rv;
190            rv.red = (colour & 0xf800) >> 11;
191            rv.red = (rv.red * 0xff) / 0x1f;
192            rv.green = (colour & 0x07e0) >> 5;
193            rv.green = (rv.green * 0xff) / 0x3f;
194            rv.blue = (colour & 0x001f);
195            rv.blue = (rv.blue * 0xff) / 0x1f;
196            return rv;
197    }
198    
199    static PixelColour
200    split_colour24(uint32 colour)
201    {
202            PixelColour rv;
203            rv.blue = (colour & 0xff0000) >> 16;
204            rv.green = (colour & 0xff00) >> 8;
205            rv.red = (colour & 0xff);
206            return rv;
207    }
208    
209    static uint32
210    make_colour16(PixelColour pc)
211    {
212            pc.red = (pc.red * 0x1f) / 0xff;
213            pc.green = (pc.green * 0x3f) / 0xff;
214            pc.blue = (pc.blue * 0x1f) / 0xff;
215            return (pc.red << 11) | (pc.green << 5) | pc.blue;
216    }
217    
218    static uint32
219    make_colour24(PixelColour pc)
220    {
221            return (pc.red << 16) | (pc.green << 8) | pc.blue;
222    }
223    
224    static uint32
225    make_colour32(PixelColour pc)
226    {
227            return (pc.red << 16) | (pc.green << 8) | pc.blue;
228    }
229    
230    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
231    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
232    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
233                            x = (x << 16) | (x >> 16); }
234    
235    static uint32
236    translate_colour(uint32 colour)
237    {
238            switch (server_bpp)
239            {
240                    case 15:
241                            switch (bpp)
242                            {
243                                    case 16:
244                                            colour = make_colour16(split_colour15(colour));
245                                            break;
246                                    case 24:
247                                            colour = make_colour24(split_colour15(colour));
248                                            break;
249                                    case 32:
250                                            colour = make_colour32(split_colour15(colour));
251                                            break;
252                            }
253                            break;
254                    case 16:
255                            switch (bpp)
256                            {
257                                    case 16:
258                                            break;
259                                    case 24:
260                                            colour = make_colour24(split_colour16(colour));
261                                            break;
262                                    case 32:
263                                            colour = make_colour32(split_colour16(colour));
264                                            break;
265                            }
266                            break;
267                    case 24:
268                            switch (bpp)
269                            {
270                                    case 16:
271                                            colour = make_colour16(split_colour24(colour));
272                                            break;
273                                    case 24:
274                                            break;
275                                    case 32:
276                                            colour = make_colour32(split_colour24(colour));
277                                            break;
278                            }
279                            break;
280            }
281            switch (bpp)
282            {
283                    case 16:
284                            if (host_be != xserver_be)
285                                    BSWAP16(colour);
286                            break;
287    
288                    case 24:
289                            if (xserver_be)
290                                    BSWAP24(colour);
291                            break;
292    
293                    case 32:
294                            if (host_be != xserver_be)
295                                    BSWAP32(colour);
296                            break;
297            }
298    
299            return colour;
300    }
301    
302    static void
303    translate8to8(uint8 * data, uint8 * out, uint8 * end)
304  {  {
305          while (out < end)          while (out < end)
306                  *(out++) = (uint8)colmap[*(data++)];                  *(out++) = (uint8) colmap[*(data++)];
307  }  }
308    
309  static void  static void
310  translate16(uint8 *data, uint16 *out, uint16 *end)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
311  {  {
312          while (out < end)          while (out < end)
313                  *(out++) = (uint16)colmap[*(data++)];                  *(out++) = (uint16) colmap[*(data++)];
314  }  }
315    
316  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
317  static void  static void
318  translate24(uint8 *data, uint8 *out, uint8 *end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
319  {  {
320          uint32 value;          uint32 value;
321    
# Line 116  translate24(uint8 *data, uint8 *out, uin Line 329  translate24(uint8 *data, uint8 *out, uin
329  }  }
330    
331  static void  static void
332  translate32(uint8 *data, uint32 *out, uint32 *end)  translate8to32(uint8 * data, uint32 * out, uint32 * end)
333  {  {
334          while (out < end)          while (out < end)
335                  *(out++) = colmap[*(data++)];                  *(out++) = colmap[*(data++)];
336  }  }
337    
338  static uint8 *  /* todo the remaining translate function might need some big endian check ?? */
339  translate_image(int width, int height, uint8 *data)  
340    static void
341    translate15to16(uint16 * data, uint16 * out, uint16 * end)
342  {  {
343          int size = width * height * bpp/8;          while (out < end)
344          uint8 *out = xmalloc(size);                  *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
345          uint8 *end = out + size;  }
346    
347          switch (bpp)  static void
348    translate15to24(uint16 * data, uint8 * out, uint8 * end)
349    {
350            uint32 value;
351    
352            while (out < end)
353          {          {
354                  case 8:                  value = make_colour24(split_colour15(*(data++)));
355                          translate8(data, out, end);                  *(out++) = value;
356                          break;                  *(out++) = value >> 8;
357                    *(out++) = value >> 16;
358            }
359    }
360    
361                  case 16:  static void
362                          translate16(data, (uint16 *)out, (uint16 *)end);  translate15to32(uint16 * data, uint32 * out, uint32 * end)
363                          break;  {
364            while (out < end)
365                    *(out++) = make_colour32(split_colour15(*(data++)));
366    }
367    
368                  case 24:  static void
369                          translate24(data, out, end);  translate16to16(uint16 * data, uint16 * out, uint16 * end)
370                          break;  {
371            while (out < end)
372                    *(out++) = (uint16) (*(data++));
373    }
374    
375                  case 32:  
376                          translate32(data, (uint32 *)out, (uint32 *)end);  static void
377                          break;  translate16to24(uint16 * data, uint8 * out, uint8 * end)
378    {
379            uint32 value;
380    
381            while (out < end)
382            {
383                    value = make_colour24(split_colour16(*(data++)));
384                    *(out++) = value;
385                    *(out++) = value >> 8;
386                    *(out++) = value >> 16;
387          }          }
388    }
389    
390          return out;  static void
391    translate16to32(uint16 * data, uint32 * out, uint32 * end)
392    {
393            while (out < end)
394                    *(out++) = make_colour32(split_colour16(*(data++)));
395  }  }
396    
397  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  static void
398  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  translate24to16(uint8 * data, uint16 * out, uint16 * end)
399  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  {
400                          x = (x << 16) | (x >> 16); }          uint32 pixel = 0;
401            while (out < end)
402            {
403                    pixel = *(data++) << 16;
404                    pixel |= *(data++) << 8;
405                    pixel |= *(data++);
406                    *(out++) = (uint16) make_colour16(split_colour24(pixel));
407            }
408    }
409    
410  static uint32  static void
411  translate_colour(uint32 colour)  translate24to24(uint8 * data, uint8 * out, uint8 * end)
412  {  {
413          switch (bpp)          while (out < end)
414          {          {
415                  case 16:                  *(out++) = (*(data++));
416                          if (host_be != xserver_be)          }
417                                  BSWAP16(colour);  }
                         break;  
418    
419    static void
420    translate24to32(uint8 * data, uint32 * out, uint32 * end)
421    {
422            uint32 pixel = 0;
423            while (out < end)
424            {
425                    pixel = *(data++);
426                    pixel |= *(data++) << 8;
427                    pixel |= *(data++) << 16;
428                    *(out++) = pixel;
429            }
430    }
431    
432    static uint8 *
433    translate_image(int width, int height, uint8 * data)
434    {
435            int size = width * height * bpp / 8;
436            uint8 *out = (uint8 *) xmalloc(size);
437            uint8 *end = out + size;
438    
439            switch (server_bpp)
440            {
441                  case 24:                  case 24:
442                          if (xserver_be)                          switch (bpp)
443                                  BSWAP24(colour);                          {
444                                    case 32:
445                                            translate24to32(data, (uint32 *) out, (uint32 *) end);
446                                            break;
447                                    case 24:
448                                            translate24to24(data, out, end);
449                                            break;
450                                    case 16:
451                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
452                                            break;
453                            }
454                          break;                          break;
455                    case 16:
456                  case 32:                          switch (bpp)
457                          if (host_be != xserver_be)                          {
458                                  BSWAP32(colour);                                  case 32:
459                                            translate16to32((uint16 *) data, (uint32 *) out,
460                                                            (uint32 *) end);
461                                            break;
462                                    case 24:
463                                            translate16to24((uint16 *) data, out, end);
464                                            break;
465                                    case 16:
466                                            translate16to16((uint16 *) data, (uint16 *) out,
467                                                            (uint16 *) end);
468                                            break;
469                            }
470                            break;
471                    case 15:
472                            switch (bpp)
473                            {
474                                    case 32:
475                                            translate15to32((uint16 *) data, (uint32 *) out,
476                                                            (uint32 *) end);
477                                            break;
478                                    case 24:
479                                            translate15to24((uint16 *) data, out, end);
480                                            break;
481                                    case 16:
482                                            translate15to16((uint16 *) data, (uint16 *) out,
483                                                            (uint16 *) end);
484                                            break;
485                            }
486                            break;
487                    case 8:
488                            switch (bpp)
489                            {
490                                    case 8:
491                                            translate8to8(data, out, end);
492                                            break;
493                                    case 16:
494                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
495                                            break;
496                                    case 24:
497                                            translate8to24(data, out, end);
498                                            break;
499                                    case 32:
500                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
501                                            break;
502                            }
503                          break;                          break;
504          }          }
505            return out;
506    }
507    
508          return colour;  BOOL
509    get_key_state(unsigned int state, uint32 keysym)
510    {
511            int modifierpos, key, keysymMask = 0;
512            int offset;
513    
514            KeyCode keycode = XKeysymToKeycode(display, keysym);
515    
516            if (keycode == NoSymbol)
517                    return False;
518    
519            for (modifierpos = 0; modifierpos < 8; modifierpos++)
520            {
521                    offset = mod_map->max_keypermod * modifierpos;
522    
523                    for (key = 0; key < mod_map->max_keypermod; key++)
524                    {
525                            if (mod_map->modifiermap[offset + key] == keycode)
526                                    keysymMask |= 1 << modifierpos;
527                    }
528            }
529    
530            return (state & keysymMask) ? True : False;
531  }  }
532    
533  BOOL  BOOL
534  ui_create_window(char *title)  ui_init(void)
535  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
536          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
         Screen *screen;  
537          uint16 test;          uint16 test;
538          int i;          int i;
539    
540          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
541          if (display == NULL)          if (display == NULL)
542          {          {
543                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
544                  return False;                  return False;
545          }          }
546    
# Line 211  ui_create_window(char *title) Line 556  ui_create_window(char *title)
556                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
557                  while (i--)                  while (i--)
558                  {                  {
559                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
560                          {                          {
561                                  bpp = pfm[i].bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
562                          }                          }
# Line 227  ui_create_window(char *title) Line 571  ui_create_window(char *title)
571                  return False;                  return False;
572          }          }
573    
574          if (depth <= 8)          if (owncolmap != True)
575                  owncolmap = True;          {
         else  
576                  xcolmap = DefaultColormapOfScreen(screen);                  xcolmap = DefaultColormapOfScreen(screen);
577                    if (depth <= 8)
578                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
579            }
580    
581            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
582    
583            if (DoesBackingStore(screen) != Always)
584                    ownbackstore = True;
585    
586          test = 1;          test = 1;
587          host_be = !(BOOL)(*(uint8 *)(&test));          host_be = !(BOOL) (*(uint8 *) (&test));
588          xserver_be = (ImageByteOrder(display) == MSBFirst);          xserver_be = (ImageByteOrder(display) == MSBFirst);
589    
590          white = WhitePixelOfScreen(screen);          if ((width == 0) || (height == 0))
591          attribs.background_pixel = BlackPixelOfScreen(screen);          {
592          attribs.backing_store = DoesBackingStore(screen);                  /* Fetch geometry from _NET_WORKAREA */
593                    uint32 x, y, cx, cy;
594    
595          if (attribs.backing_store == NotUseful)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
596                  ownbackstore = True;                  {
597                            width = cx;
598                            height = cy;
599                    }
600                    else
601                    {
602                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
603                            width = 800;
604                            height = 600;
605                    }
606            }
607    
608          if (fullscreen)          if (fullscreen)
609          {          {
                 attribs.override_redirect = True;  
610                  width = WidthOfScreen(screen);                  width = WidthOfScreen(screen);
611                  height = HeightOfScreen(screen);                  height = HeightOfScreen(screen);
612          }          }
613          else  
614            /* make sure width is a multiple of 4 */
615            width = (width + 3) & ~3;
616    
617            if (ownbackstore)
618          {          {
619                  attribs.override_redirect = False;                  backstore =
620                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
621    
622                    /* clear to prevent rubbish being exposed at startup */
623                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
624                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
625          }          }
626    
627          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          mod_map = XGetModifierMapping(display);
628    
629            if (enable_compose)
630                    IM = XOpenIM(display, NULL, NULL, NULL);
631    
632            xkeymap_init();
633    
634          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          /* todo take this out when high colour is done */
635                              0, 0, width, height, 0, CopyFromParent,          printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
636                              InputOutput, CopyFromParent,  
637                              CWBackingStore | CWBackPixel | CWOverrideRedirect,  
638                              &attribs);  
639            return True;
640    }
641    
642    void
643    ui_deinit(void)
644    {
645            if (IM != NULL)
646                    XCloseIM(IM);
647    
648            XFreeModifiermap(mod_map);
649    
650            if (ownbackstore)
651                    XFreePixmap(display, backstore);
652    
653            XFreeGC(display, gc);
654            XCloseDisplay(display);
655            display = NULL;
656    }
657    
658    BOOL
659    ui_create_window(void)
660    {
661            XSetWindowAttributes attribs;
662            XClassHint *classhints;
663            XSizeHints *sizehints;
664            int wndwidth, wndheight;
665            long ic_input_mask;
666            XEvent xevent;
667    
668            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
669            wndheight = fullscreen ? HeightOfScreen(screen) : height;
670    
671            attribs.background_pixel = BlackPixelOfScreen(screen);
672            attribs.backing_store = ownbackstore ? NotUseful : Always;
673            attribs.override_redirect = fullscreen;
674    
675            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
676                                0, CopyFromParent, InputOutput, CopyFromParent,
677                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
678    
679          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
680    
681            if (hide_decorations)
682                    mwm_hide_decorations();
683    
684          classhints = XAllocClassHint();          classhints = XAllocClassHint();
685          if (classhints != NULL)          if (classhints != NULL)
686          {          {
# Line 282  ui_create_window(char *title) Line 699  ui_create_window(char *title)
699                  XFree(sizehints);                  XFree(sizehints);
700          }          }
701    
702          xkeymap_init(display);          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
703                    VisibilityChangeMask | FocusChangeMask;
         input_mask = KeyPressMask | KeyReleaseMask  
                         | ButtonPressMask | ButtonReleaseMask  
                         | EnterWindowMask | LeaveWindowMask;  
704    
705          if (sendmotion)          if (sendmotion)
706                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
   
707          if (ownbackstore)          if (ownbackstore)
708                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
709            if (fullscreen || grab_keyboard)
710                    input_mask |= EnterWindowMask;
711            if (grab_keyboard)
712                    input_mask |= LeaveWindowMask;
713    
714            if (IM != NULL)
715            {
716                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
717                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
718    
719                    if ((IC != NULL)
720                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
721                            input_mask |= ic_input_mask;
722            }
723    
724          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
725          gc = XCreateGC(display, wnd, 0, NULL);          XMapWindow(display, wnd);
726    
727          if (ownbackstore)          /* wait for VisibilityNotify */
728                  backstore = XCreatePixmap(display, wnd, width, height, depth);          do
729            {
730                    XMaskEvent(display, VisibilityChangeMask, &xevent);
731            }
732            while (xevent.type != VisibilityNotify);
733    
734            focused = False;
735            mouse_in_wnd = False;
736    
737            /* handle the WM_DELETE_WINDOW protocol */
738            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
739            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
740            XSetWMProtocols(display, wnd, &kill_atom, 1);
741    
         XMapWindow(display, wnd);  
742          return True;          return True;
743  }  }
744    
745  void  void
746  ui_destroy_window()  ui_destroy_window(void)
747  {  {
748          if (ownbackstore)          if (IC != NULL)
749                  XFreePixmap(display, backstore);                  XDestroyIC(IC);
750    
         XFreeGC(display, gc);  
751          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
752          XCloseDisplay(display);  }
753          display = NULL;  
754    void
755    xwin_toggle_fullscreen(void)
756    {
757            Pixmap contents = 0;
758    
759            if (!ownbackstore)
760            {
761                    /* need to save contents of window */
762                    contents = XCreatePixmap(display, wnd, width, height, depth);
763                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
764            }
765    
766            ui_destroy_window();
767            fullscreen = !fullscreen;
768            ui_create_window();
769    
770            XDefineCursor(display, wnd, current_cursor);
771    
772            if (!ownbackstore)
773            {
774                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
775                    XFreePixmap(display, contents);
776            }
777  }  }
778    
779  static void  static void
780  xwin_process_events()  xwin_process_propertynotify(XPropertyEvent * xev)
781  {  {
782          XEvent event;          PropNotifyCb *this = propnotify_callbacks;
783            while (NULL != this)
784            {
785                    if (xev->window == this->wnd && xev->atom == this->atom)
786                    {
787                            this->callback(xev);
788                    }
789                    this = this->next;
790            }
791    }
792    
793    
794    /* Process all events in Xlib queue
795       Returns 0 after user quit, 1 otherwise */
796    static int
797    xwin_process_events(void)
798    {
799            XEvent xevent;
800          KeySym keysym;          KeySym keysym;
801          uint8 scancode;          uint16 button, flags;
         uint16 button;  
802          uint32 ev_time;          uint32 ev_time;
803            key_translation tr;
804            char str[256];
805            Status status;
806            unsigned int state;
807            Window wdummy;
808            int dummy;
809    
810          if (display == NULL)          while (XPending(display) > 0)
                 return;  
   
         while (XCheckMaskEvent(display, ~0, &event))  
811          {          {
812                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
813    
814                  switch (event.type)                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
815                  {                  {
816                            DEBUG_KBD(("Filtering event\n"));
817                            continue;
818                    }
819    
820                    flags = 0;
821    
822                    switch (xevent.type)
823                    {
824                            case ClientMessage:
825                                    /* the window manager told us to quit */
826                                    if ((xevent.xclient.message_type == protocol_atom)
827                                        && ((Atom) xevent.xclient.data.l[0] == kill_atom))
828                                            /* Quit */
829                                            return 0;
830                                    break;
831    
832                          case KeyPress:                          case KeyPress:
833                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);                                  last_gesturetime = ((XKeyEvent *) & xevent)->time;
834                                  scancode = xkeymap_translate_key(keysym, event.xkey.keycode);                                  if (IC != NULL)
835                                  if (scancode == 0)                                          /* Multi_key compatible version */
836                                    {
837                                            XmbLookupString(IC,
838                                                            (XKeyPressedEvent *) &
839                                                            xevent, str, sizeof(str), &keysym, &status);
840                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
841                                            {
842                                                    error("XmbLookupString failed with status 0x%x\n",
843                                                          status);
844                                                    break;
845                                            }
846                                    }
847                                    else
848                                    {
849                                            /* Plain old XLookupString */
850                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
851                                            XLookupString((XKeyEvent *) & xevent,
852                                                          str, sizeof(str), &keysym, NULL);
853                                    }
854    
855                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
856                                               get_ksname(keysym)));
857    
858                                    ev_time = time(NULL);
859                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
860                                            break;
861    
862                                    tr = xkeymap_translate_key(keysym,
863                                                               xevent.xkey.keycode, xevent.xkey.state);
864    
865                                    if (tr.scancode == 0)
866                                          break;                                          break;
867    
868                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  ensure_remote_modifiers(ev_time, tr);
869                                                 scancode, 0);  
870                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
871                                  break;                                  break;
872    
873                          case KeyRelease:                          case KeyRelease:
874                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);                                  last_gesturetime = ((XKeyEvent *) & xevent)->time;
875                                  scancode = xkeymap_translate_key(keysym, event.xkey.keycode);                                  XLookupString((XKeyEvent *) & xevent, str,
876                                  if (scancode == 0)                                                sizeof(str), &keysym, NULL);
877    
878                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
879                                               get_ksname(keysym)));
880    
881                                    ev_time = time(NULL);
882                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
883                                          break;                                          break;
884    
885                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
886                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
887    
888                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xkeymap_translate_button(event.xbutton.button);  
                                 if (button == 0)  
889                                          break;                                          break;
890    
891                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
892                                  break;                                  break;
893    
894                            case ButtonPress:
895                                    last_gesturetime = ((XButtonEvent *) & xevent)->time;
896                                    flags = MOUSE_FLAG_DOWN;
897                                    /* fall through */
898    
899                          case ButtonRelease:                          case ButtonRelease:
900                                  button = xkeymap_translate_button(event.xbutton.button);                                  last_gesturetime = ((XButtonEvent *) & xevent)->time;
901                                    button = xkeymap_translate_button(xevent.xbutton.button);
902                                  if (button == 0)                                  if (button == 0)
903                                          break;                                          break;
904    
905                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
906                                                 button,                                  if (xevent.xbutton.y < win_button_size)
907                                                 event.xbutton.x,                                  {
908                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
909                                            if (moving_wnd && (xevent.type == ButtonRelease))
910                                                    moving_wnd = False;
911    
912                                            /*  Check from right to left: */
913    
914                                            if (xevent.xbutton.x >= width - win_button_size)
915                                            {
916                                                    /* The close button, continue */
917                                                    ;
918                                            }
919                                            else if (xevent.xbutton.x >= width - win_button_size * 2)
920                                            {
921                                                    /* The maximize/restore button. Do not send to
922                                                       server.  It might be a good idea to change the
923                                                       cursor or give some other visible indication
924                                                       that rdesktop inhibited this click */
925                                                    break;
926                                            }
927                                            else if (xevent.xbutton.x >= width - win_button_size * 3)
928                                            {
929                                                    /* The minimize button. Iconify window. */
930                                                    XIconifyWindow(display, wnd,
931                                                                   DefaultScreen(display));
932                                                    break;
933                                            }
934                                            else if (xevent.xbutton.x <= win_button_size)
935                                            {
936                                                    /* The system menu. Ignore. */
937                                                    break;
938                                            }
939                                            else
940                                            {
941                                                    /* The title bar. */
942                                                    if ((xevent.type == ButtonPress) && !fullscreen
943                                                        && hide_decorations)
944                                                    {
945                                                            moving_wnd = True;
946                                                            move_x_offset = xevent.xbutton.x;
947                                                            move_y_offset = xevent.xbutton.y;
948                                                    }
949                                                    break;
950    
951                                            }
952                                    }
953    
954                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
955                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
956                                  break;                                  break;
957    
958                          case MotionNotify:                          case MotionNotify:
959                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (moving_wnd)
960                                                 MOUSE_FLAG_MOVE,                                  {
961                                                 event.xmotion.x,                                          XMoveWindow(display, wnd,
962                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - move_x_offset,
963                                                        xevent.xmotion.y_root - move_y_offset);
964                                            break;
965                                    }
966    
967                                    if (fullscreen && !focused)
968                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
969                                                           CurrentTime);
970                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
971                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
972                                    break;
973    
974                            case FocusIn:
975                                    if (xevent.xfocus.mode == NotifyGrab)
976                                            break;
977                                    focused = True;
978                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
979                                                  &dummy, &dummy, &state);
980                                    reset_modifier_keys(state);
981                                    if (grab_keyboard && mouse_in_wnd)
982                                            XGrabKeyboard(display, wnd, True,
983                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
984                                    break;
985    
986                            case FocusOut:
987                                    if (xevent.xfocus.mode == NotifyUngrab)
988                                            break;
989                                    focused = False;
990                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
991                                            XUngrabKeyboard(display, CurrentTime);
992                                  break;                                  break;
993    
994                          case EnterNotify:                          case EnterNotify:
995                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
996                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
997                                    mouse_in_wnd = True;
998                                    if (fullscreen)
999                                    {
1000                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
1001                                                           CurrentTime);
1002                                            break;
1003                                    }
1004                                    if (focused)
1005                                            XGrabKeyboard(display, wnd, True,
1006                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1007                                  break;                                  break;
1008    
1009                          case LeaveNotify:                          case LeaveNotify:
1010                                    /* we only register for this event when grab_keyboard */
1011                                    mouse_in_wnd = False;
1012                                  XUngrabKeyboard(display, CurrentTime);                                  XUngrabKeyboard(display, CurrentTime);
1013                                  break;                                  break;
1014    
1015                          case Expose:                          case Expose:
1016                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(display, backstore, wnd, gc,
1017                                            event.xexpose.x, event.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
1018                                            event.xexpose.width, event.xexpose.height,                                            xevent.xexpose.width,
1019                                            event.xexpose.x, event.xexpose.y);                                            xevent.xexpose.height,
1020                                              xevent.xexpose.x, xevent.xexpose.y);
1021                                    break;
1022    
1023                            case MappingNotify:
1024                                    /* Refresh keyboard mapping if it has changed. This is important for
1025                                       Xvnc, since it allocates keycodes dynamically */
1026                                    if (xevent.xmapping.request == MappingKeyboard
1027                                        || xevent.xmapping.request == MappingModifier)
1028                                            XRefreshKeyboardMapping(&xevent.xmapping);
1029    
1030                                    if (xevent.xmapping.request == MappingModifier)
1031                                    {
1032                                            XFreeModifiermap(mod_map);
1033                                            mod_map = XGetModifierMapping(display);
1034                                    }
1035                                    break;
1036                                    /* Clipboard stuff */
1037                            case SelectionClear:
1038                                    cliprdr_handle_SelectionClear();
1039                                  break;                                  break;
1040                            case SelectionNotify:
1041                                    cliprdr_handle_SelectionNotify((XSelectionEvent *) & xevent);
1042                                    break;
1043                            case SelectionRequest:
1044                                    cliprdr_handle_SelectionRequest((XSelectionRequestEvent *) &
1045                                                                    xevent);
1046                                    break;
1047    
1048                            case PropertyNotify:
1049                                    xwin_process_propertynotify((XPropertyEvent *) & xevent);
1050                                    break;
1051    
1052    
1053                  }                  }
1054          }          }
1055            /* Keep going */
1056            return 1;
1057  }  }
1058    
1059  void  /* Returns 0 after user quit, 1 otherwise */
1060    int
1061  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1062  {  {
1063          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1064          fd_set rfds;          fd_set rfds;
1065    
         XFlush(display);  
   
1066          FD_ZERO(&rfds);          FD_ZERO(&rfds);
1067    
1068          while (True)          while (True)
1069          {          {
1070                    /* Process any events already waiting */
1071                    if (!xwin_process_events())
1072                            /* User quit */
1073                            return 0;
1074    
1075                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1076                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1077                  FD_SET(x_socket, &rfds);                  FD_SET(x_socket, &rfds);
# Line 428  ui_select(int rdp_socket) Line 1085  ui_select(int rdp_socket)
1085                                  continue;                                  continue;
1086                  }                  }
1087    
                 if (FD_ISSET(x_socket, &rfds))  
                         xwin_process_events();  
   
1088                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1089                          return;                          return 1;
1090          }          }
1091  }  }
1092    
# Line 443  ui_move_pointer(int x, int y) Line 1097  ui_move_pointer(int x, int y)
1097  }  }
1098    
1099  HBITMAP  HBITMAP
1100  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1101  {  {
1102          XImage *image;          XImage *image;
1103          Pixmap bitmap;          Pixmap bitmap;
# Line 451  ui_create_bitmap(int width, int height, Line 1105  ui_create_bitmap(int width, int height,
1105    
1106          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1107          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
1108          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1109                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1110    
1111          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1112    
# Line 463  ui_create_bitmap(int width, int height, Line 1117  ui_create_bitmap(int width, int height,
1117  }  }
1118    
1119  void  void
1120  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)  
1121  {  {
1122          XImage *image;          XImage *image;
1123          uint8 *tdata;          uint8 *tdata;
   
1124          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1125          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1126                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1127    
1128          if (ownbackstore)          if (ownbackstore)
1129          {          {
# Line 491  ui_paint_bitmap(int x, int y, int cx, in Line 1143  ui_paint_bitmap(int x, int y, int cx, in
1143  void  void
1144  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1145  {  {
1146          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
1147  }  }
1148    
1149  HGLYPH  HGLYPH
1150  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1151  {  {
1152          XImage *image;          XImage *image;
1153          Pixmap bitmap;          Pixmap bitmap;
# Line 507  ui_create_glyph(int width, int height, u Line 1159  ui_create_glyph(int width, int height, u
1159          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
1160          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
1161    
1162          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1163                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1164          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1165          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1166          XInitImage(image);          XInitImage(image);
# Line 517  ui_create_glyph(int width, int height, u Line 1169  ui_create_glyph(int width, int height, u
1169    
1170          XFree(image);          XFree(image);
1171          XFreeGC(display, gc);          XFreeGC(display, gc);
1172          return (HGLYPH)bitmap;          return (HGLYPH) bitmap;
1173  }  }
1174    
1175  void  void
1176  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1177  {  {
1178          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap) glyph);
1179  }  }
1180    
1181  HCURSOR  HCURSOR
1182  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1183                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1184  {  {
1185          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1186          XColor bg, fg;          XColor bg, fg;
# Line 542  ui_create_cursor(unsigned int x, unsigne Line 1194  ui_create_cursor(unsigned int x, unsigne
1194          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1195          offset = scanline * height;          offset = scanline * height;
1196    
1197          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1198          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1199    
1200          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1201          memset(mask, 0, offset);          memset(mask, 0, offset);
1202    
1203          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 585  ui_create_cursor(unsigned int x, unsigne Line 1237  ui_create_cursor(unsigned int x, unsigne
1237    
1238          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1239          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1240            
1241          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
1242                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1243                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1244    
1245          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1246          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
1247          xfree(mask);          xfree(mask);
1248          xfree(cursor);          xfree(cursor);
1249          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1250  }  }
1251    
1252  void  void
1253  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1254  {  {
1255          XDefineCursor(display, wnd, (Cursor)cursor);          current_cursor = (Cursor) cursor;
1256            XDefineCursor(display, wnd, current_cursor);
1257  }  }
1258    
1259  void  void
1260  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1261  {  {
1262          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(display, (Cursor) cursor);
1263  }  }
1264    
1265  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 614  ui_destroy_cursor(HCURSOR cursor) Line 1268  ui_destroy_cursor(HCURSOR cursor)
1268                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1269                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1270    
1271    
1272  HCOLOURMAP  HCOLOURMAP
1273  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
1274  {  {
1275          COLOURENTRY *entry;          COLOURENTRY *entry;
1276          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1277            if (!owncolmap)
1278            {
1279                    uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);
1280                    XColor xentry;
1281                    XColor xc_cache[256];
1282                    uint32 colour;
1283                    int colLookup = 256;
1284                    for (i = 0; i < ncolours; i++)
1285                    {
1286                            entry = &colours->colours[i];
1287                            MAKE_XCOLOR(&xentry, entry);
1288    
1289                            if (XAllocColor(display, xcolmap, &xentry) == 0)
1290                            {
1291                                    /* Allocation failed, find closest match. */
1292                                    int j = 256;
1293                                    int nMinDist = 3 * 256 * 256;
1294                                    long nDist = nMinDist;
1295    
1296          if (owncolmap)                                  /* only get the colors once */
1297                                    while (colLookup--)
1298                                    {
1299                                            xc_cache[colLookup].pixel = colLookup;
1300                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1301                                                    xc_cache[colLookup].blue = 0;
1302                                            xc_cache[colLookup].flags = 0;
1303                                            XQueryColor(display,
1304                                                        DefaultColormap(display,
1305                                                                        DefaultScreen(display)),
1306                                                        &xc_cache[colLookup]);
1307                                    }
1308                                    colLookup = 0;
1309    
1310                                    /* approximate the pixel */
1311                                    while (j--)
1312                                    {
1313                                            if (xc_cache[j].flags)
1314                                            {
1315                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1316                                                             (long) (xentry.red >> 8)) *
1317                                                            ((long) (xc_cache[j].red >> 8) -
1318                                                             (long) (xentry.red >> 8)) +
1319                                                            ((long) (xc_cache[j].green >> 8) -
1320                                                             (long) (xentry.green >> 8)) *
1321                                                            ((long) (xc_cache[j].green >> 8) -
1322                                                             (long) (xentry.green >> 8)) +
1323                                                            ((long) (xc_cache[j].blue >> 8) -
1324                                                             (long) (xentry.blue >> 8)) *
1325                                                            ((long) (xc_cache[j].blue >> 8) -
1326                                                             (long) (xentry.blue >> 8));
1327                                            }
1328                                            if (nDist < nMinDist)
1329                                            {
1330                                                    nMinDist = nDist;
1331                                                    xentry.pixel = j;
1332                                            }
1333                                    }
1334                            }
1335                            colour = xentry.pixel;
1336    
1337                            /* update our cache */
1338                            if (xentry.pixel < 256)
1339                            {
1340                                    xc_cache[xentry.pixel].red = xentry.red;
1341                                    xc_cache[xentry.pixel].green = xentry.green;
1342                                    xc_cache[xentry.pixel].blue = xentry.blue;
1343    
1344                            }
1345    
1346    
1347                            /* byte swap here to make translate_image faster */
1348                            map[i] = translate_colour(colour);
1349                    }
1350                    return map;
1351            }
1352            else
1353          {          {
1354                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1355                  Colormap map;                  Colormap map;
1356    
1357                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1358                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1359                  {                  {
1360                          entry = &colours->colours[i];                          entry = &colours->colours[i];
# Line 638  ui_create_colourmap(COLOURMAP *colours) Line 1367  ui_create_colourmap(COLOURMAP *colours)
1367                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(display, map, xcolours, ncolours);
1368    
1369                  xfree(xcolours);                  xfree(xcolours);
1370                  return (HCOLOURMAP)map;                  return (HCOLOURMAP) map;
         }  
         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;  
1371          }          }
1372  }  }
1373    
1374  void  void
1375  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1376  {  {
1377          if (owncolmap)          if (!owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1378                  xfree(map);                  xfree(map);
1379            else
1380                    XFreeColormap(display, (Colormap) map);
1381  }  }
1382    
1383  void  void
1384  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1385  {  {
1386          if (owncolmap)          if (!owncolmap)
1387                  XSetWindowColormap(display, wnd, (Colormap)map);                  colmap = (uint32 *) map;
1388          else          else
1389                  colmap = map;                  XSetWindowColormap(display, wnd, (Colormap) map);
1390  }  }
1391    
1392  void  void
# Line 695  ui_set_clip(int x, int y, int cx, int cy Line 1402  ui_set_clip(int x, int y, int cx, int cy
1402  }  }
1403    
1404  void  void
1405  ui_reset_clip()  ui_reset_clip(void)
1406  {  {
1407          XRectangle rect;          XRectangle rect;
1408    
# Line 707  ui_reset_clip() Line 1414  ui_reset_clip()
1414  }  }
1415    
1416  void  void
1417  ui_bell()  ui_bell(void)
1418  {  {
1419          XBell(display, 0);          XBell(display, 0);
1420  }  }
# Line 721  ui_destblt(uint8 opcode, Line 1428  ui_destblt(uint8 opcode,
1428          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1429  }  }
1430    
1431    static uint8 hatch_patterns[] = {
1432            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1433            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1434            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1435            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1436            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1437            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1438    };
1439    
1440  void  void
1441  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1442            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1443            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1444  {  {
1445          Pixmap fill;          Pixmap fill;
1446            uint8 i, ipattern[8];
1447    
1448          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1449    
# Line 737  ui_patblt(uint8 opcode, Line 1454  ui_patblt(uint8 opcode,
1454                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1455                          break;                          break;
1456    
1457                    case 2: /* Hatch */
1458                            fill = (Pixmap) ui_create_glyph(8, 8,
1459                                                            hatch_patterns + brush->pattern[0] * 8);
1460                            SET_FOREGROUND(bgcolour);
1461                            SET_BACKGROUND(fgcolour);
1462                            XSetFillStyle(display, gc, FillOpaqueStippled);
1463                            XSetStipple(display, gc, fill);
1464                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1465                            FILL_RECTANGLE(x, y, cx, cy);
1466                            XSetFillStyle(display, gc, FillSolid);
1467                            XSetTSOrigin(display, gc, 0, 0);
1468                            ui_destroy_glyph((HGLYPH) fill);
1469                            break;
1470    
1471                  case 3: /* Pattern */                  case 3: /* Pattern */
1472                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
1473                                    ipattern[7 - i] = brush->pattern[i];
1474                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1475    
1476                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1477                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
# Line 749  ui_patblt(uint8 opcode, Line 1482  ui_patblt(uint8 opcode,
1482                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1483    
1484                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1485                          ui_destroy_glyph((HGLYPH)fill);                          XSetTSOrigin(display, gc, 0, 0);
1486                            ui_destroy_glyph((HGLYPH) fill);
1487                          break;                          break;
1488    
1489                  default:                  default:
# Line 767  ui_screenblt(uint8 opcode, Line 1501  ui_screenblt(uint8 opcode,
1501          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1502          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1503          if (ownbackstore)          if (ownbackstore)
1504                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1505          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1506  }  }
1507    
# Line 778  ui_memblt(uint8 opcode, Line 1511  ui_memblt(uint8 opcode,
1511            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1512  {  {
1513          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1514          XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1515          if (ownbackstore)          if (ownbackstore)
1516                  XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1517          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1518  }  }
1519    
# Line 789  void Line 1521  void
1521  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1522            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1523            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1524            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1525  {  {
1526          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1527             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 798  ui_triblt(uint8 opcode, Line 1530  ui_triblt(uint8 opcode,
1530          {          {
1531                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1532                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1533                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1534                          break;                          break;
1535    
1536                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1537                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1538                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1539                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1540                          break;                          break;
1541    
1542                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1543                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1544                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1545                          break;                          break;
1546    
1547                  default:                  default:
# Line 825  ui_triblt(uint8 opcode, Line 1553  ui_triblt(uint8 opcode,
1553  void  void
1554  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1555          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1556          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1557  {  {
1558          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1559          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
# Line 844  ui_rect( Line 1572  ui_rect(
1572          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1573  }  }
1574    
1575    /* warning, this function only draws on wnd or backstore, not both */
1576  void  void
1577  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1578                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1579                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1580                int fgcolour)                int bgcolour, int fgcolour)
1581  {  {
1582          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1583          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1584    
1585          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(display, gc,
1586                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1587          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(display, gc, (Pixmap) glyph);
1588          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(display, gc, x, y);
1589    
1590          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1591    
1592          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1593  }  }
1594    
1595    #define DO_GLYPH(ttext,idx) \
1596    {\
1597      glyph = cache_get_font (font, ttext[idx]);\
1598      if (!(flags & TEXT2_IMPLICIT_X))\
1599        {\
1600          xyoffset = ttext[++idx];\
1601          if ((xyoffset & 0x80))\
1602            {\
1603              if (flags & TEXT2_VERTICAL) \
1604                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1605              else\
1606                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1607              idx += 2;\
1608            }\
1609          else\
1610            {\
1611              if (flags & TEXT2_VERTICAL) \
1612                y += xyoffset;\
1613              else\
1614                x += xyoffset;\
1615            }\
1616        }\
1617      if (glyph != NULL)\
1618        {\
1619          ui_draw_glyph (mixmode, x + glyph->offset,\
1620                         y + glyph->baseline,\
1621                         glyph->width, glyph->height,\
1622                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1623          if (flags & TEXT2_IMPLICIT_X)\
1624            x += glyph->width;\
1625        }\
1626    }
1627    
1628  void  void
1629  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,
1630               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1631               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1632               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1633  {  {
1634          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1635          int i, offset;          int i, j, xyoffset;
1636            DATABLOB *entry;
1637    
1638          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
1639    
1640          if (boxcx > 1)          if (boxcx > 1)
1641          {          {
1642                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1643          }          }
1644          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1645          {          {
1646                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1647          }          }
1648    
1649          /* Paint text, character by character */          /* Paint text, character by character */
1650          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1651          {          {
1652                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
1653                  {                  {
1654                          offset = text[++i];                          case 0xff:
1655                          if (offset & 0x80)                                  if (i + 2 < length)
1656                                  offset = ((offset & 0x7f) << 8) | text[++i];                                          cache_put_text(text[i + 1], text, text[i + 2]);
1657                                    else
1658                          if (flags & TEXT2_VERTICAL)                                  {
1659                                  y += offset;                                          error("this shouldn't be happening\n");
1660                          else                                          exit(1);
1661                                  x += offset;                                  }
1662                  }                                  /* this will move pointer from start to first character after FF command */
1663                                    length -= i + 3;
1664                                    text = &(text[i + 3]);
1665                                    i = 0;
1666                                    break;
1667    
1668                  if (glyph != NULL)                          case 0xfe:
1669                  {                                  entry = cache_get_text(text[i + 1]);
1670                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  if (entry != NULL)
1671                                        y + (short) glyph->baseline,                                  {
1672                                        glyph->width, glyph->height,                                          if ((((uint8 *) (entry->data))[1] ==
1673                                        glyph->pixmap, 0, 0,                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1674                                        bgcolour, fgcolour);                                          {
1675                                                    if (flags & TEXT2_VERTICAL)
1676                                                            y += text[i + 2];
1677                                                    else
1678                                                            x += text[i + 2];
1679                                            }
1680                                            for (j = 0; j < entry->size; j++)
1681                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1682                                    }
1683                                    if (i + 2 < length)
1684                                            i += 3;
1685                                    else
1686                                            i += 2;
1687                                    length -= i;
1688                                    /* this will move pointer from start to first character after FE command */
1689                                    text = &(text[i]);
1690                                    i = 0;
1691                                    break;
1692    
1693                          if (flags & TEXT2_IMPLICIT_X)                          default:
1694                                  x += glyph->width;                                  DO_GLYPH(text, i);
1695                                    i++;
1696                                    break;
1697                  }                  }
1698          }          }
1699            if (ownbackstore)
1700            {
1701                    if (boxcx > 1)
1702                            XCopyArea(display, backstore, wnd, gc, boxx,
1703                                      boxy, boxcx, boxcy, boxx, boxy);
1704                    else
1705                            XCopyArea(display, backstore, wnd, gc, clipx,
1706                                      clipy, clipcx, clipcy, clipx, clipy);
1707            }
1708  }  }
1709    
1710  void  void
# Line 922  ui_desktop_save(uint32 offset, int x, in Line 1715  ui_desktop_save(uint32 offset, int x, in
1715    
1716          if (ownbackstore)          if (ownbackstore)
1717          {          {
1718                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1719          }          }
1720          else          else
1721          {          {
1722                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(display, wnd, cx, cy, depth);
1723                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1724                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1725                  XFreePixmap(display, pix);                  XFreePixmap(display, pix);
1726          }          }
1727    
1728          offset *= bpp/8;          offset *= bpp / 8;
1729          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
                           bpp/8, (uint8 *)image->data);  
1730    
1731          XDestroyImage(image);          XDestroyImage(image);
1732  }  }
# Line 947  ui_desktop_restore(uint32 offset, int x, Line 1737  ui_desktop_restore(uint32 offset, int x,
1737          XImage *image;          XImage *image;
1738          uint8 *data;          uint8 *data;
1739    
1740          offset *= bpp/8;          offset *= bpp / 8;
1741          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1742          if (data == NULL)          if (data == NULL)
1743                  return;                  return;
1744    
1745          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1746                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
                              cx * bpp/8);  
1747    
1748          if (ownbackstore)          if (ownbackstore)
1749          {          {
# Line 968  ui_desktop_restore(uint32 offset, int x, Line 1757  ui_desktop_restore(uint32 offset, int x,
1757    
1758          XFree(image);          XFree(image);
1759  }  }
1760    
1761    
1762    void
1763    xwin_register_propertynotify(Window event_wnd, Atom atom,
1764                                 void (*propertycallback) (XPropertyEvent *))
1765    {
1766            PropNotifyCb *this;
1767            int window_already_registrered = 0;
1768            if (NULL != propnotify_callbacks)
1769            {
1770                    this = propnotify_callbacks;
1771                    if (event_wnd == this->wnd)
1772                    {
1773                            window_already_registrered = 1;
1774                            if (atom == this->atom)
1775                                    return;
1776                    }
1777                    while (NULL != this->next)
1778                    {
1779                            if (event_wnd == this->wnd)
1780                            {
1781                                    window_already_registrered = 1;
1782                                    if (atom == this->atom)
1783                                            return;
1784                                    /* Find last entry in list */
1785                            }
1786                            this = this->next;
1787                    }
1788                    this->next = xmalloc(sizeof(PropNotifyCb));
1789                    this->next->next = NULL;
1790                    this = this->next;
1791    
1792            }
1793            else
1794            {
1795                    this = xmalloc(sizeof(PropNotifyCb));
1796                    this->next = NULL;
1797                    propnotify_callbacks = this;
1798            }
1799            if (!window_already_registrered)
1800            {
1801                    if (wnd == event_wnd)
1802                            XSelectInput(display, wnd, input_mask | PropertyChangeMask);
1803                    else
1804                            XSelectInput(display, event_wnd, PropertyChangeMask);
1805            }
1806            this->wnd = event_wnd;
1807            this->atom = atom;
1808            this->callback = propertycallback;
1809    }
1810    
1811    
1812    void
1813    xwin_deregister_propertynotify(Window event_wnd, Atom atom)
1814    {
1815            PropNotifyCb *this = propnotify_callbacks;
1816            PropNotifyCb *prev;
1817            int window_needed = 0;
1818            prev = this;
1819            while (NULL != this)
1820            {
1821                    if (event_wnd == this->wnd)
1822                    {
1823                            if (atom == this->atom)
1824                            {
1825                                    if (prev == this)
1826                                    {
1827                                            propnotify_callbacks = this->next;
1828                                    }
1829                                    else
1830                                    {
1831                                            prev->next = this->next;
1832                                    }
1833                                    xfree(this);
1834                                    continue;
1835                            }
1836                            else
1837                            {
1838                                    window_needed = 1;
1839                            }
1840                    }
1841                    prev = this;
1842                    this = this->next;
1843            }
1844            if (!window_needed)
1845            {
1846                    if (wnd != event_wnd)
1847                    {
1848                            XSelectInput(display, event_wnd, NoEventMask);
1849                    }
1850                    else
1851                    {
1852                            XSelectInput(display, wnd, input_mask);
1853                    }
1854            }
1855    }

Legend:
Removed from v.42  
changed lines
  Added in v.415

  ViewVC Help
Powered by ViewVC 1.1.26