/[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 25 by matty, Sat Jan 6 03:47:04 2001 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-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2000     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.
19  */  */
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23  #include <time.h>  #include <time.h>
24    #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    #include "xproto.h"
27    
28  extern int width;  extern int width;
29  extern int height;  extern int height;
30  extern BOOL motion;  extern BOOL sendmotion;
31    extern BOOL fullscreen;
32  static Display *display;  extern BOOL grab_keyboard;
33  static Window wnd;  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    Display *display;
42    Time last_gesturetime;
43    static int x_socket;
44    static Screen *screen;
45    Window wnd;
46  static GC gc;  static GC gc;
47  static Visual *visual;  static Visual *visual;
48    static int depth;
49    static int bpp;
50  static XIM IM;  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 */
60    static BOOL host_be;
61    static BOOL xserver_be;
62    
63    /* software backing store */
64    static BOOL ownbackstore;
65    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)\
109    { \
110            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
111            if (ownbackstore) \
112                    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 */
121    BOOL owncolmap = False;
122    static Colormap xcolmap;
123    static uint32 *colmap;
124    
125    #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));
127    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
128    
129    static int rop2_map[] = {
130            GXclear,                /* 0 */
131            GXnor,                  /* DPon */
132            GXandInverted,          /* DPna */
133            GXcopyInverted,         /* Pn */
134            GXandReverse,           /* PDna */
135            GXinvert,               /* Dn */
136            GXxor,                  /* DPx */
137            GXnand,                 /* DPan */
138            GXand,                  /* DPa */
139            GXequiv,                /* DPxn */
140            GXnoop,                 /* D */
141            GXorInverted,           /* DPno */
142            GXcopy,                 /* P */
143            GXorReverse,            /* PDno */
144            GXor,                   /* DPo */
145            GXset                   /* 1 */
146    };
147    
148    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
149    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
150    
151    static void
152    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)
306                    *(out++) = (uint8) colmap[*(data++)];
307    }
308    
309    static void
310    translate8to16(uint8 * data, uint16 * out, uint16 * end)
311    {
312            while (out < end)
313                    *(out++) = (uint16) colmap[*(data++)];
314    }
315    
316    /* little endian - conversion happens when colourmap is built */
317    static void
318    translate8to24(uint8 * data, uint8 * out, uint8 * end)
319    {
320            uint32 value;
321    
322            while (out < end)
323            {
324                    value = colmap[*(data++)];
325                    *(out++) = value;
326                    *(out++) = value >> 8;
327                    *(out++) = value >> 16;
328            }
329    }
330    
331    static void
332    translate8to32(uint8 * data, uint32 * out, uint32 * end)
333    {
334            while (out < end)
335                    *(out++) = colmap[*(data++)];
336    }
337    
338    /* todo the remaining translate function might need some big endian check ?? */
339    
340    static void
341    translate15to16(uint16 * data, uint16 * out, uint16 * end)
342    {
343            while (out < end)
344                    *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
345    }
346    
347    static void
348    translate15to24(uint16 * data, uint8 * out, uint8 * end)
349    {
350            uint32 value;
351    
352            while (out < end)
353            {
354                    value = make_colour24(split_colour15(*(data++)));
355                    *(out++) = value;
356                    *(out++) = value >> 8;
357                    *(out++) = value >> 16;
358            }
359    }
360    
361    static void
362    translate15to32(uint16 * data, uint32 * out, uint32 * end)
363    {
364            while (out < end)
365                    *(out++) = make_colour32(split_colour15(*(data++)));
366    }
367    
368    static void
369    translate16to16(uint16 * data, uint16 * out, uint16 * end)
370    {
371            while (out < end)
372                    *(out++) = (uint16) (*(data++));
373    }
374    
375    
376    static void
377    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    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    static void
398    translate24to16(uint8 * data, uint16 * out, uint16 * end)
399    {
400            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 void
411    translate24to24(uint8 * data, uint8 * out, uint8 * end)
412    {
413            while (out < end)
414            {
415                    *(out++) = (*(data++));
416            }
417    }
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:
442                            switch (bpp)
443                            {
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;
455                    case 16:
456                            switch (bpp)
457                            {
458                                    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;
504            }
505            return out;
506    }
507    
508  BOOL  BOOL
509  ui_create_window(char *title)  get_key_state(unsigned int state, uint32 keysym)
510  {  {
511          Screen *screen;          int modifierpos, key, keysymMask = 0;
512          XSetWindowAttributes attribs;          int offset;
513          unsigned long input_mask;  
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
534    ui_init(void)
535    {
536            XPixmapFormatValues *pfm;
537            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    
547          /* Check the screen supports 8-bit depth. */          x_socket = ConnectionNumber(display);
548          screen = DefaultScreenOfDisplay(display);          screen = DefaultScreenOfDisplay(display);
549          for (i = 0; i < screen->ndepths; i++)          visual = DefaultVisualOfScreen(screen);
550                  if (screen->depths[i].depth == 8)          depth = DefaultDepthOfScreen(screen);
                         break;  
551    
552          if (i >= screen->ndepths)          pfm = XListPixmapFormats(display, &i);
553            if (pfm != NULL)
554          {          {
555                  ERROR("8-bit depth required (in this version).\n");                  /* Use maximum bpp for this depth - this is generally
556                       desirable, e.g. 24 bits->32 bits. */
557                    while (i--)
558                    {
559                            if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
560                            {
561                                    bpp = pfm[i].bits_per_pixel;
562                            }
563                    }
564                    XFree(pfm);
565            }
566    
567            if (bpp < 8)
568            {
569                    error("Less than 8 bpp not currently supported.\n");
570                  XCloseDisplay(display);                  XCloseDisplay(display);
571                  return False;                  return False;
572          }          }
573    
574          visual = DefaultVisual(display, DefaultScreen(display));          if (owncolmap != True)
575            {
576                    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          attribs.background_pixel =          gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
                 BlackPixel(display, DefaultScreen(display));  
         attribs.backing_store = Always;  
         wnd = XCreateWindow(display, DefaultRootWindow(display),  
                             0, 0, width, height, 0, 8, InputOutput, visual,  
                             CWBackingStore | CWBackPixel, &attribs);  
582    
583          XStoreName(display, wnd, title);          if (DoesBackingStore(screen) != Always)
584          XMapWindow(display, wnd);                  ownbackstore = True;
585    
586            test = 1;
587            host_be = !(BOOL) (*(uint8 *) (&test));
588            xserver_be = (ImageByteOrder(display) == MSBFirst);
589    
590            if ((width == 0) || (height == 0))
591            {
592                    /* Fetch geometry from _NET_WORKAREA */
593                    uint32 x, y, cx, cy;
594    
595                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
596                    {
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)
609            {
610                    width = WidthOfScreen(screen);
611                    height = HeightOfScreen(screen);
612            }
613    
614            /* make sure width is a multiple of 4 */
615            width = (width + 3) & ~3;
616    
617            if (ownbackstore)
618            {
619                    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            mod_map = XGetModifierMapping(display);
628    
629            if (enable_compose)
630                    IM = XOpenIM(display, NULL, NULL, NULL);
631    
632            xkeymap_init();
633    
634            /* todo take this out when high colour is done */
635            printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
636    
         input_mask = KeyPressMask | KeyReleaseMask;  
         input_mask |= ButtonPressMask | ButtonReleaseMask;  
         if (motion)  
                 input_mask |= PointerMotionMask;  
637    
         XSelectInput(display, wnd, input_mask);  
         gc = XCreateGC(display, wnd, 0, NULL);  
638    
         IM = XOpenIM(display, NULL, NULL, NULL);  
639          return True;          return True;
640  }  }
641    
642  void  void
643  ui_destroy_window()  ui_deinit(void)
644  {  {
645          XCloseIM(IM);          if (IM != NULL)
646                    XCloseIM(IM);
647    
648            XFreeModifiermap(mod_map);
649    
650            if (ownbackstore)
651                    XFreePixmap(display, backstore);
652    
653          XFreeGC(display, gc);          XFreeGC(display, gc);
         XDestroyWindow(display, wnd);  
654          XCloseDisplay(display);          XCloseDisplay(display);
655            display = NULL;
656  }  }
657    
658  static uint8  BOOL
659  xwin_translate_key(unsigned long key)  ui_create_window(void)
660  {  {
661          DEBUG("KEY(code=0x%lx)\n", key);          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          if ((key > 8) && (key <= 0x60))          XStoreName(display, wnd, title);
                 return (key - 8);  
680    
681          switch (key)          if (hide_decorations)
682                    mwm_hide_decorations();
683    
684            classhints = XAllocClassHint();
685            if (classhints != NULL)
686          {          {
687                  case 0x62:      /* left arrow */                  classhints->res_name = classhints->res_class = "rdesktop";
688                          return 0x48;                  XSetClassHint(display, wnd, classhints);
689                  case 0x64:      /* up arrow */                  XFree(classhints);
                         return 0x4b;  
                 case 0x66:      /* down arrow */  
                         return 0x4d;  
                 case 0x68:      /* right arrow */  
                         return 0x50;  
                 case 0x73:      /* Windows key */  
                         DEBUG("CHECKPOINT\n");  
690          }          }
691    
692          return 0;          sizehints = XAllocSizeHints();
693            if (sizehints)
694            {
695                    sizehints->flags = PMinSize | PMaxSize;
696                    sizehints->min_width = sizehints->max_width = width;
697                    sizehints->min_height = sizehints->max_height = height;
698                    XSetWMNormalHints(display, wnd, sizehints);
699                    XFree(sizehints);
700            }
701    
702            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
703                    VisibilityChangeMask | FocusChangeMask;
704    
705            if (sendmotion)
706                    input_mask |= PointerMotionMask;
707            if (ownbackstore)
708                    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);
725            XMapWindow(display, wnd);
726    
727            /* wait for VisibilityNotify */
728            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    
742            return True;
743    }
744    
745    void
746    ui_destroy_window(void)
747    {
748            if (IC != NULL)
749                    XDestroyIC(IC);
750    
751            XDestroyWindow(display, wnd);
752  }  }
753    
754  static uint16  void
755  xwin_translate_mouse(unsigned long button)  xwin_toggle_fullscreen(void)
756  {  {
757          switch (button)          Pixmap contents = 0;
758    
759            if (!ownbackstore)
760          {          {
761                  case Button1:   /* left */                  /* need to save contents of window */
762                          return MOUSE_FLAG_BUTTON1;                  contents = XCreatePixmap(display, wnd, width, height, depth);
763                  case Button2:   /* middle */                  XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
764          }          }
765    
766          return 0;          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  void  static void
780  ui_process_events()  xwin_process_propertynotify(XPropertyEvent * xev)
781  {  {
782          XEvent event;          PropNotifyCb *this = propnotify_callbacks;
783          uint8 scancode;          while (NULL != this)
784          uint16 button;          {
785          uint32 ev_time;                  if (xev->window == this->wnd && xev->atom == this->atom)
786                    {
787                            this->callback(xev);
788                    }
789                    this = this->next;
790            }
791    }
792    
         if (display == NULL)  
                 return;  
793    
794          while (XCheckWindowEvent(display, wnd, 0xffffffff, &event))  /* 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;
801            uint16 button, flags;
802            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            while (XPending(display) > 0)
811          {          {
812                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
813    
814                    if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
815                    {
816                            DEBUG_KBD(("Filtering event\n"));
817                            continue;
818                    }
819    
820                    flags = 0;
821    
822                  switch (event.type)                  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                                  scancode =                                  last_gesturetime = ((XKeyEvent *) & xevent)->time;
834                                          xwin_translate_key(event.                                  if (IC != NULL)
835                                                             xkey.keycode);                                          /* Multi_key compatible version */
836                                  if (scancode == 0)                                  {
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                                  scancode =                                  last_gesturetime = ((XKeyEvent *) & xevent)->time;
875                                          xwin_translate_key(event.                                  XLookupString((XKeyEvent *) & xevent, str,
876                                                             xkey.keycode);                                                sizeof(str), &keysym, NULL);
877                                  if (scancode == 0)  
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);
887                                                 scancode, 0);  
888                                    if (tr.scancode == 0)
889                                            break;
890    
891                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
892                                  break;                                  break;
893    
894                          case ButtonPress:                          case ButtonPress:
895                                  button =                                  last_gesturetime = ((XButtonEvent *) & xevent)->time;
896                                          xwin_translate_mouse(event.                                  flags = MOUSE_FLAG_DOWN;
897                                                               xbutton.button);                                  /* fall through */
898    
899                            case ButtonRelease:
900                                    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 | MOUSE_FLAG_DOWN,                                  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 ButtonRelease:                          case MotionNotify:
959                                  button =                                  if (moving_wnd)
960                                          xwin_translate_mouse(event.                                  {
961                                                               xbutton.button);                                          XMoveWindow(display, wnd,
962                                  if (button == 0)                                                      xevent.xmotion.x_root - move_x_offset,
963                                                        xevent.xmotion.y_root - move_y_offset);
964                                          break;                                          break;
965                                    }
966    
967                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (fullscreen && !focused)
968                                                 button,                                          XSetInputFocus(display, wnd, RevertToPointerRoot,
969                                                 event.xbutton.x,                                                         CurrentTime);
970                                                 event.xbutton.y);                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
971                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
972                                  break;                                  break;
973    
974                          case MotionNotify:                          case FocusIn:
975                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (xevent.xfocus.mode == NotifyGrab)
976                                                 MOUSE_FLAG_MOVE,                                          break;
977                                                 event.xmotion.x,                                  focused = True;
978                                                 event.xmotion.y);                                  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;
993    
994                            case EnterNotify:
995                                    /* we only register for this event when in fullscreen mode */
996                                    /* 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;
1008    
1009                            case LeaveNotify:
1010                                    /* we only register for this event when grab_keyboard */
1011                                    mouse_in_wnd = False;
1012                                    XUngrabKeyboard(display, CurrentTime);
1013                                    break;
1014    
1015                            case Expose:
1016                                    XCopyArea(display, backstore, wnd, gc,
1017                                              xevent.xexpose.x, xevent.xexpose.y,
1018                                              xevent.xexpose.width,
1019                                              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;
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    /* Returns 0 after user quit, 1 otherwise */
1060    int
1061    ui_select(int rdp_socket)
1062    {
1063            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1064            fd_set rfds;
1065    
1066            FD_ZERO(&rfds);
1067    
1068            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);
1076                    FD_SET(rdp_socket, &rfds);
1077                    FD_SET(x_socket, &rfds);
1078    
1079                    switch (select(n, &rfds, NULL, NULL, NULL))
1080                    {
1081                            case -1:
1082                                    error("select: %s\n", strerror(errno));
1083    
1084                            case 0:
1085                                    continue;
1086                  }                  }
1087    
1088                    if (FD_ISSET(rdp_socket, &rfds))
1089                            return 1;
1090          }          }
1091  }  }
1092    
# Line 217  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;
1104            uint8 *tdata;
1105    
1106          bitmap = XCreatePixmap(display, wnd, width, height, 8);          tdata = (owncolmap ? data : translate_image(width, height, data));
1107            bitmap = XCreatePixmap(display, wnd, width, height, depth);
1108            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1109                                 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1110    
         image = XCreateImage(display, visual, 8, ZPixmap, 0,  
                              data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
1111          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
         XFree(image);  
1112    
1113            XFree(image);
1114            if (!owncolmap)
1115                    xfree(tdata);
1116          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
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;
1124            tdata = (owncolmap ? data : translate_image(width, height, data));
1125            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1126                                 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1127    
1128            if (ownbackstore)
1129            {
1130                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1131                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1132            }
1133            else
1134            {
1135                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1136            }
1137    
         image = XCreateImage(display, visual, 8, ZPixmap, 0,  
                              data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
1138          XFree(image);          XFree(image);
1139            if (!owncolmap)
1140                    xfree(tdata);
1141  }  }
1142    
1143  void  void
# Line 253  ui_destroy_bitmap(HBITMAP bmp) Line 1147  ui_destroy_bitmap(HBITMAP 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 265  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);
1167    
         XSetFunction(display, gc, GXcopy);  
1168          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1169    
1170          XFree(image);          XFree(image);
1171          XFreeGC(display, gc);          XFreeGC(display, gc);
   
1172          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1173  }  }
1174    
# Line 285  ui_destroy_glyph(HGLYPH glyph) Line 1178  ui_destroy_glyph(HGLYPH glyph)
1178          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(display, (Pixmap) glyph);
1179  }  }
1180    
1181    HCURSOR
1182    ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1183                     uint8 * andmask, uint8 * xormask)
1184    {
1185            HGLYPH maskglyph, cursorglyph;
1186            XColor bg, fg;
1187            Cursor xcursor;
1188            uint8 *cursor, *pcursor;
1189            uint8 *mask, *pmask;
1190            uint8 nextbit;
1191            int scanline, offset;
1192            int i, j;
1193    
1194            scanline = (width + 7) / 8;
1195            offset = scanline * height;
1196    
1197            cursor = (uint8 *) xmalloc(offset);
1198            memset(cursor, 0, offset);
1199    
1200            mask = (uint8 *) xmalloc(offset);
1201            memset(mask, 0, offset);
1202    
1203            /* approximate AND and XOR masks with a monochrome X pointer */
1204            for (i = 0; i < height; i++)
1205            {
1206                    offset -= scanline;
1207                    pcursor = &cursor[offset];
1208                    pmask = &mask[offset];
1209    
1210                    for (j = 0; j < scanline; j++)
1211                    {
1212                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1213                            {
1214                                    if (xormask[0] || xormask[1] || xormask[2])
1215                                    {
1216                                            *pcursor |= (~(*andmask) & nextbit);
1217                                            *pmask |= nextbit;
1218                                    }
1219                                    else
1220                                    {
1221                                            *pcursor |= ((*andmask) & nextbit);
1222                                            *pmask |= (~(*andmask) & nextbit);
1223                                    }
1224    
1225                                    xormask += 3;
1226                            }
1227    
1228                            andmask++;
1229                            pcursor++;
1230                            pmask++;
1231                    }
1232            }
1233    
1234            fg.red = fg.blue = fg.green = 0xffff;
1235            bg.red = bg.blue = bg.green = 0x0000;
1236            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1237    
1238            cursorglyph = ui_create_glyph(width, height, cursor);
1239            maskglyph = ui_create_glyph(width, height, mask);
1240    
1241            xcursor =
1242                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1243                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1244    
1245            ui_destroy_glyph(maskglyph);
1246            ui_destroy_glyph(cursorglyph);
1247            xfree(mask);
1248            xfree(cursor);
1249            return (HCURSOR) xcursor;
1250    }
1251    
1252    void
1253    ui_set_cursor(HCURSOR cursor)
1254    {
1255            current_cursor = (Cursor) cursor;
1256            XDefineCursor(display, wnd, current_cursor);
1257    }
1258    
1259    void
1260    ui_destroy_cursor(HCURSOR cursor)
1261    {
1262            XFreeCursor(display, (Cursor) cursor);
1263    }
1264    
1265    #define MAKE_XCOLOR(xc,c) \
1266                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
1267                    (xc)->green = ((c)->green << 8) | (c)->green; \
1268                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1269                    (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;
         XColor *xcolours, *xentry;  
         Colormap map;  
1276          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1277            if (!owncolmap)
         xcolours = xmalloc(sizeof(XColor) * ncolours);  
         for (i = 0; i < ncolours; i++)  
1278          {          {
1279                  entry = &colours->colours[i];                  uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);
1280                  xentry = &xcolours[i];                  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                                    /* 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                  xentry->pixel = i;                          }
1345                  xentry->red = entry->red << 8;  
1346                  xentry->blue = entry->blue << 8;  
1347                  xentry->green = entry->green << 8;                          /* byte swap here to make translate_image faster */
1348                  xentry->flags = DoRed | DoBlue | DoGreen;                          map[i] = translate_colour(colour);
1349                    }
1350                    return map;
1351          }          }
1352            else
1353            {
1354                    XColor *xcolours, *xentry;
1355                    Colormap map;
1356    
1357          map = XCreateColormap(display, wnd, visual, AllocAll);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1358          XStoreColors(display, map, xcolours, ncolours);                  for (i = 0; i < ncolours; i++)
1359                    {
1360                            entry = &colours->colours[i];
1361                            xentry = &xcolours[i];
1362                            xentry->pixel = i;
1363                            MAKE_XCOLOR(xentry, entry);
1364                    }
1365    
1366          xfree(xcolours);                  map = XCreateColormap(display, wnd, visual, AllocAll);
1367          return (HCOLOURMAP) map;                  XStoreColors(display, map, xcolours, ncolours);
1368    
1369                    xfree(xcolours);
1370                    return (HCOLOURMAP) map;
1371            }
1372  }  }
1373    
1374  void  void
1375  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1376  {  {
1377          XFreeColormap(display, (Colormap) map);          if (!owncolmap)
1378                    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          XSetWindowColormap(display, wnd, (Colormap) map);          if (!owncolmap)
1387                    colmap = (uint32 *) map;
1388            else
1389                    XSetWindowColormap(display, wnd, (Colormap) map);
1390  }  }
1391    
1392  void  void
# Line 338  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 350  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  }  }
1421    
 static int rop2_map[] = {  
         GXclear,                /* 0 */  
         GXnor,                  /* DPon */  
         GXandInverted,          /* DPna */  
         GXcopyInverted,         /* Pn */  
         GXandReverse,           /* PDna */  
         GXinvert,               /* Dn */  
         GXxor,                  /* DPx */  
         GXnand,                 /* DPan */  
         GXand,                  /* DPa */  
         GXequiv,                /* DPxn */  
         GXnoop,                 /* D */  
         GXorInverted,           /* DPno */  
         GXcopy,                 /* P */  
         GXorReverse,            /* PDno */  
         GXor,                   /* DPo */  
         GXset                   /* 1 */  
 };  
   
 static void  
 xwin_set_function(uint8 rop2)  
 {  
         XSetFunction(display, gc, rop2_map[rop2]);  
 }  
   
1422  void  void
1423  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
1424             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
1425  {  {
1426          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1427            FILL_RECTANGLE(x, y, cx, cy);
1428          XFillRectangle(display, wnd, gc, x, y, cx, cy);          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  {  {
         Display *dpy = display;  
1445          Pixmap fill;          Pixmap fill;
1446            uint8 i, ipattern[8];
1447    
1448          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1449    
1450          switch (brush->style)          switch (brush->style)
1451          {          {
1452                  case 0: /* Solid */                  case 0: /* Solid */
1453                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(fgcolour);
1454                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1455                          break;                          break;
1456    
1457                  case 3: /* Pattern */                  case 2: /* Hatch */
1458                          fill = (Pixmap) ui_create_glyph(8, 8, brush->pattern);                          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                          XSetForeground(dpy, gc, fgcolour);                  case 3: /* Pattern */
1472                          XSetBackground(dpy, gc, bgcolour);                          for (i = 0; i != 8; i++)
1473                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                                  ipattern[7 - i] = brush->pattern[i];
1474                          XSetStipple(dpy, gc, fill);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1475    
1476                            SET_FOREGROUND(bgcolour);
1477                            SET_BACKGROUND(fgcolour);
1478                            XSetFillStyle(display, gc, FillOpaqueStippled);
1479                            XSetStipple(display, gc, fill);
1480                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1481    
1482                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1483    
1484                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1485                            XSetTSOrigin(display, gc, 0, 0);
1486                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1487                          break;                          break;
1488    
1489                  default:                  default:
1490                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
1491          }          }
1492    
1493            RESET_FUNCTION(opcode);
1494  }  }
1495    
1496  void  void
# Line 430  ui_screenblt(uint8 opcode, Line 1498  ui_screenblt(uint8 opcode,
1498               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
1499               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1500  {  {
1501          xwin_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)
1504                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1505            RESET_FUNCTION(opcode);
1506  }  }
1507    
1508  void  void
# Line 440  ui_memblt(uint8 opcode, Line 1510  ui_memblt(uint8 opcode,
1510            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1511            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1512  {  {
1513          xwin_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)
1516                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1517            RESET_FUNCTION(opcode);
1518  }  }
1519    
1520  void  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 458  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);
1540                                    brush, bgcolour, fgcolour);                          break;
1541    
1542                    case 0xc0:      /* PSa */
1543                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1544                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1545                          break;                          break;
1546    
1547                  default:                  default:
1548                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1549                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1550          }          }
1551  }  }
# Line 479  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          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1559            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, pen->colour);  
1560          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1561            if (ownbackstore)
1562                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1563            RESET_FUNCTION(opcode);
1564  }  }
1565    
1566  void  void
# Line 492  ui_rect( Line 1568  ui_rect(
1568                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1569                 /* brush */ int colour)                 /* brush */ int colour)
1570  {  {
1571          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1572            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, colour);  
         XFillRectangle(display, wnd, gc, 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          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1583            SET_BACKGROUND(bgcolour);
         xwin_set_function(ROP2_COPY);  
   
         XSetForeground(display, gc, fgcolour);  
1584    
1585          switch (mixmode)          XSetFillStyle(display, gc,
1586          {                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1587                  case MIX_TRANSPARENT:          XSetStipple(display, gc, (Pixmap) glyph);
1588                          XSetStipple(display, gc, pixmap);          XSetTSOrigin(display, gc, x, y);
1589                          XSetFillStyle(display, gc, FillStippled);  
1590                          XSetTSOrigin(display, gc, x, y);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1591                          XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1592                          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1593                          break;  }
1594    
1595                  case MIX_OPAQUE:  #define DO_GLYPH(ttext,idx) \
1596                          XSetBackground(display, gc, bgcolour);  {\
1597                          XCopyPlane(display, pixmap, wnd, gc,    glyph = cache_get_font (font, ttext[idx]);\
1598                                     srcx, srcy, cx, cy, x, y, 1);    if (!(flags & TEXT2_IMPLICIT_X))\
1599                          break;      {\
1600          xyoffset = ttext[++idx];\
1601                  default:        if ((xyoffset & 0x80))\
1602                          NOTIMP("mix %d\n", mixmode);          {\
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;          int i, j, xyoffset;
1636            DATABLOB *entry;
1637    
1638            SET_FOREGROUND(bgcolour);
1639    
1640          if (boxcx > 1)          if (boxcx > 1)
1641          {          {
1642                  ui_rect(boxx, boxy, boxcx, boxcy, bgcolour);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1643          }          }
1644          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1645          {          {
1646                  ui_rect(clipx, clipy, clipcx, clipcy, bgcolour);                  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))  
                         x += text[++i];  
   
                 if (glyph != NULL)  
1653                  {                  {
1654                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                          case 0xff:
1655                                        y + (short) glyph->baseline,                                  if (i + 2 < length)
1656                                        glyph->width, glyph->height,                                          cache_put_text(text[i + 1], text, text[i + 2]);
1657                                        glyph->pixmap, 0, 0,                                  else
1658                                        bgcolour, fgcolour);                                  {
1659                                            error("this shouldn't be happening\n");
1660                                            exit(1);
1661                                    }
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                            case 0xfe:
1669                                    entry = cache_get_text(text[i + 1]);
1670                                    if (entry != NULL)
1671                                    {
1672                                            if ((((uint8 *) (entry->data))[1] ==
1673                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
1674                                            {
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
1711  ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)  ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1712  {  {
1713            Pixmap pix;
1714          XImage *image;          XImage *image;
1715    
1716          image = XGetImage(display, wnd, x, y, cx, cy, 0xffffffff, ZPixmap);          if (ownbackstore)
1717          cache_put_desktop(offset, cx, cy, image->bytes_per_line, image->data);          {
1718          XFree(image->data);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1719          XFree(image);          }
1720            else
1721            {
1722                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1723                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1724                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1725                    XFreePixmap(display, pix);
1726            }
1727    
1728            offset *= bpp / 8;
1729            cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1730    
1731            XDestroyImage(image);
1732  }  }
1733    
1734  void  void
# Line 588  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          data = cache_get_desktop(offset, cx, cy);          offset *= bpp / 8;
1741            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, 8, ZPixmap, 0,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1746                               data, cx, cy, 32, cx);                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1747          XSetFunction(display, gc, GXcopy);  
1748          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);          if (ownbackstore)
1749            {
1750                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1751                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1752            }
1753            else
1754            {
1755                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1756            }
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.25  
changed lines
  Added in v.415

  ViewVC Help
Powered by ViewVC 1.1.26