/[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 7 by matty, Fri Jul 7 09:40:03 2000 UTC revision 309 by jsorg71, Tue Feb 4 05:32:13 2003 UTC
# Line 1  Line 1 
1  /*  /*
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 "includes.h"  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23    #include <time.h>
24    #include <errno.h>
25    #include "rdesktop.h"
26    
27    extern int width;
28    extern int height;
29    extern BOOL sendmotion;
30    extern BOOL fullscreen;
31    extern BOOL grab_keyboard;
32    extern BOOL hide_decorations;
33    extern char title[];
34    extern int server_bpp;
35    BOOL enable_compose = False;
36    BOOL focused;
37    BOOL mouse_in_wnd;
38    
39    Display *display;
40    static int x_socket;
41    static Screen *screen;
42    static Window wnd;
43    static GC gc;
44    static Visual *visual;
45    static int depth;
46    static int bpp;
47    static XIM IM;
48    static XIC IC;
49    static XModifierKeymap *mod_map;
50    static Cursor current_cursor;
51    static Atom protocol_atom, kill_atom;
52    
53    /* endianness */
54    static BOOL host_be;
55    static BOOL xserver_be;
56    
57    /* software backing store */
58    static BOOL ownbackstore;
59    static Pixmap backstore;
60    
61    /* MWM decorations */
62    #define MWM_HINTS_DECORATIONS   (1L << 1)
63    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
64    typedef struct
65    {
66            uint32 flags;
67            uint32 functions;
68            uint32 decorations;
69            sint32 inputMode;
70            uint32 status;
71    }
72    PropMotifWmHints;
73    
74  HWINDOW ui_create_window(int width, int height)  
75    #define FILL_RECTANGLE(x,y,cx,cy)\
76    { \
77            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
78            if (ownbackstore) \
79                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
80    }
81    
82    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
83    { \
84            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
85    }
86    
87    /* colour maps */
88    BOOL owncolmap = False;
89    static Colormap xcolmap;
90    static uint32 *colmap;
91    
92    #define TRANSLATE(col)          ( server_bpp != 8 ? col : owncolmap ? col : translate_colour(colmap[col]) )
93    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
94    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
95    
96    static int rop2_map[] = {
97            GXclear,                /* 0 */
98            GXnor,                  /* DPon */
99            GXandInverted,          /* DPna */
100            GXcopyInverted,         /* Pn */
101            GXandReverse,           /* PDna */
102            GXinvert,               /* Dn */
103            GXxor,                  /* DPx */
104            GXnand,                 /* DPan */
105            GXand,                  /* DPa */
106            GXequiv,                /* DPxn */
107            GXnoop,                 /* D */
108            GXorInverted,           /* DPno */
109            GXcopy,                 /* P */
110            GXorReverse,            /* PDno */
111            GXor,                   /* DPo */
112            GXset                   /* 1 */
113    };
114    
115    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
116    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
117    
118    void
119    mwm_hide_decorations(void)
120  {  {
121          struct window *wnd;          PropMotifWmHints motif_hints;
122          Display *display;          Atom hintsatom;
123          Window window;  
124          int black;          /* setup the property */
125          GC gc;          motif_hints.flags = MWM_HINTS_DECORATIONS;
126            motif_hints.decorations = 0;
127    
128            /* get the atom for the property */
129            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
130            if (!hintsatom)
131            {
132                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
133                    return;
134            }
135    
136            XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
137                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
138    }
139    
140    static void
141    translate8(uint8 * data, uint8 * out, uint8 * end)
142    {
143            while (out < end)
144                    *(out++) = (uint8) colmap[*(data++)];
145    }
146    
147    static void
148    translate16(uint8 * data, uint16 * out, uint16 * end)
149    {
150            while (out < end)
151                    *(out++) = (uint16) colmap[*(data++)];
152    }
153    
154    /* little endian - conversion happens when colourmap is built */
155    static void
156    translate24(uint8 * data, uint8 * out, uint8 * end)
157    {
158            uint32 value;
159    
160            while (out < end)
161            {
162                    value = colmap[*(data++)];
163                    *(out++) = value;
164                    *(out++) = value >> 8;
165                    *(out++) = value >> 16;
166            }
167    }
168    
169    static void
170    translate32(uint8 * data, uint32 * out, uint32 * end)
171    {
172            while (out < end)
173                    *(out++) = colmap[*(data++)];
174    }
175    
176    static uint8 *
177    translate_image(int width, int height, uint8 * data)
178    {
179            int size = width * height * bpp / 8;
180            uint8 *out = xmalloc(size);
181            uint8 *end = out + size;
182    
183            switch (bpp)
184            {
185                    case 8:
186                            translate8(data, out, end);
187                            break;
188    
189                    case 16:
190                            translate16(data, (uint16 *) out, (uint16 *) end);
191                            break;
192    
193                    case 24:
194                            translate24(data, out, end);
195                            break;
196    
197                    case 32:
198                            translate32(data, (uint32 *) out, (uint32 *) end);
199                            break;
200            }
201    
202            return out;
203    }
204    
205    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
206    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
207    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
208                            x = (x << 16) | (x >> 16); }
209    
210    static uint32
211    translate_colour(uint32 colour)
212    {
213            switch (bpp)
214            {
215                    case 16:
216                            if (host_be != xserver_be)
217                                    BSWAP16(colour);
218                            break;
219    
220                    case 24:
221                            if (xserver_be)
222                                    BSWAP24(colour);
223                            break;
224    
225                    case 32:
226                            if (host_be != xserver_be)
227                                    BSWAP32(colour);
228                            break;
229            }
230    
231            return colour;
232    }
233    
234    BOOL
235    get_key_state(unsigned int state, uint32 keysym)
236    {
237            int modifierpos, key, keysymMask = 0;
238            int offset;
239    
240            KeyCode keycode = XKeysymToKeycode(display, keysym);
241    
242            if (keycode == NoSymbol)
243                    return False;
244    
245            for (modifierpos = 0; modifierpos < 8; modifierpos++)
246            {
247                    offset = mod_map->max_keypermod * modifierpos;
248    
249                    for (key = 0; key < mod_map->max_keypermod; key++)
250                    {
251                            if (mod_map->modifiermap[offset + key] == keycode)
252                                    keysymMask |= 1 << modifierpos;
253                    }
254            }
255    
256            return (state & keysymMask) ? True : False;
257    }
258    
259    BOOL
260    ui_init(void)
261    {
262            XPixmapFormatValues *pfm;
263            uint16 test;
264            int i;
265    
266          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
267          if (display == NULL)          if (display == NULL)
268                  return NULL;          {
269                    error("Failed to open display: %s\n", XDisplayName(NULL));
270                    return False;
271            }
272    
273          black = BlackPixel(display, DefaultScreen(display));          x_socket = ConnectionNumber(display);
274          window = XCreateSimpleWindow(display, DefaultRootWindow(display),          screen = DefaultScreenOfDisplay(display);
275                                  0, 0, width, height, 0, black, black);          visual = DefaultVisualOfScreen(screen);
276            depth = DefaultDepthOfScreen(screen);
277    
278          XMapWindow(display, window);          pfm = XListPixmapFormats(display, &i);
279          XSync(display, True);          if (pfm != NULL)
280            {
281                    /* Use maximum bpp for this depth - this is generally
282                       desirable, e.g. 24 bits->32 bits. */
283                    while (i--)
284                    {
285                            if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
286                            {
287                                    bpp = pfm[i].bits_per_pixel;
288                            }
289                    }
290                    XFree(pfm);
291            }
292    
293          gc = XCreateGC(display, window, 0, NULL);          if (bpp < 8)
294            {
295                    error("Less than 8 bpp not currently supported.\n");
296                    XCloseDisplay(display);
297                    return False;
298            }
299    
300          wnd = xmalloc(sizeof(struct window));          if (owncolmap != True)
301          wnd->display = display;          {
302          wnd->wnd = window;                  xcolmap = DefaultColormapOfScreen(screen);
303          wnd->gc = gc;                  if (depth <= 8)
304          wnd->visual = DefaultVisual(wnd->display, DefaultScreen(wnd->display));                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
305            }
306    
307            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
308    
309            if (DoesBackingStore(screen) != Always)
310                    ownbackstore = True;
311    
312            test = 1;
313            host_be = !(BOOL) (*(uint8 *) (&test));
314            xserver_be = (ImageByteOrder(display) == MSBFirst);
315    
316            if ((width == 0) || (height == 0))
317            {
318                    /* Fetch geometry from _NET_WORKAREA */
319                    uint32 x, y, cx, cy;
320    
321                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
322                    {
323                            width = cx;
324                            height = cy;
325                    }
326                    else
327                    {
328                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
329                            width = 800;
330                            height = 600;
331                    }
332            }
333    
334            if (fullscreen)
335            {
336                    width = WidthOfScreen(screen);
337                    height = HeightOfScreen(screen);
338            }
339    
340            /* make sure width is a multiple of 4 */
341            width = (width + 3) & ~3;
342    
343            if (ownbackstore)
344            {
345                    backstore =
346                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
347    
348                    /* clear to prevent rubbish being exposed at startup */
349                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
350                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
351            }
352    
353            mod_map = XGetModifierMapping(display);
354    
355          return wnd;          if (enable_compose)
356                    IM = XOpenIM(display, NULL, NULL, NULL);
357    
358            xkeymap_init();
359            return True;
360  }  }
361    
362  void ui_destroy_window(HWINDOW wnd)  void
363    ui_deinit(void)
364  {  {
365          XFreeGC(wnd->display, wnd->gc);          if (IM != NULL)
366          XDestroyWindow(wnd->display, wnd->wnd);                  XCloseIM(IM);
367          XCloseDisplay(wnd->display);  
368            XFreeModifiermap(mod_map);
369    
370            if (ownbackstore)
371                    XFreePixmap(display, backstore);
372    
373            XFreeGC(display, gc);
374            XCloseDisplay(display);
375            display = NULL;
376  }  }
377    
378  HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)  BOOL
379    ui_create_window(void)
380    {
381            XSetWindowAttributes attribs;
382            XClassHint *classhints;
383            XSizeHints *sizehints;
384            int wndwidth, wndheight;
385            long input_mask, ic_input_mask;
386            XEvent xevent;
387    
388            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
389            wndheight = fullscreen ? HeightOfScreen(screen) : height;
390    
391            attribs.background_pixel = BlackPixelOfScreen(screen);
392            attribs.backing_store = ownbackstore ? NotUseful : Always;
393            attribs.override_redirect = fullscreen;
394    
395            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
396                                0, CopyFromParent, InputOutput, CopyFromParent,
397                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
398    
399            XStoreName(display, wnd, title);
400    
401            if (hide_decorations)
402                    mwm_hide_decorations();
403    
404            classhints = XAllocClassHint();
405            if (classhints != NULL)
406            {
407                    classhints->res_name = classhints->res_class = "rdesktop";
408                    XSetClassHint(display, wnd, classhints);
409                    XFree(classhints);
410            }
411    
412            sizehints = XAllocSizeHints();
413            if (sizehints)
414            {
415                    sizehints->flags = PMinSize | PMaxSize;
416                    sizehints->min_width = sizehints->max_width = width;
417                    sizehints->min_height = sizehints->max_height = height;
418                    XSetWMNormalHints(display, wnd, sizehints);
419                    XFree(sizehints);
420            }
421    
422            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
423                    VisibilityChangeMask | FocusChangeMask;
424    
425            if (sendmotion)
426                    input_mask |= PointerMotionMask;
427            if (ownbackstore)
428                    input_mask |= ExposureMask;
429            if (fullscreen || grab_keyboard)
430                    input_mask |= EnterWindowMask;
431            if (grab_keyboard)
432                    input_mask |= LeaveWindowMask;
433    
434            if (IM != NULL)
435            {
436                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
437                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
438    
439                    if ((IC != NULL)
440                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
441                            input_mask |= ic_input_mask;
442            }
443    
444            XSelectInput(display, wnd, input_mask);
445            XMapWindow(display, wnd);
446    
447            /* wait for VisibilityNotify */
448            do
449            {
450                    XMaskEvent(display, VisibilityChangeMask, &xevent);
451            }
452            while (xevent.type != VisibilityNotify);
453    
454            focused = False;
455            mouse_in_wnd = False;
456    
457            /* handle the WM_DELETE_WINDOW protocol */
458            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
459            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
460            XSetWMProtocols(display, wnd, &kill_atom, 1);
461    
462            return True;
463    }
464    
465    void
466    ui_destroy_window(void)
467    {
468            if (IC != NULL)
469                    XDestroyIC(IC);
470    
471            XDestroyWindow(display, wnd);
472    }
473    
474    void
475    xwin_toggle_fullscreen(void)
476    {
477            Pixmap contents = 0;
478    
479            if (!ownbackstore)
480            {
481                    /* need to save contents of window */
482                    contents = XCreatePixmap(display, wnd, width, height, depth);
483                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
484            }
485    
486            ui_destroy_window();
487            fullscreen = !fullscreen;
488            ui_create_window();
489    
490            XDefineCursor(display, wnd, current_cursor);
491    
492            if (!ownbackstore)
493            {
494                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
495                    XFreePixmap(display, contents);
496            }
497    }
498    
499    /* Process all events in Xlib queue
500       Returns 0 after user quit, 1 otherwise */
501    static int
502    xwin_process_events(void)
503    {
504            XEvent xevent;
505            KeySym keysym;
506            uint16 button, flags;
507            uint32 ev_time;
508            key_translation tr;
509            char str[256];
510            Status status;
511            unsigned int state;
512            Window wdummy;
513            int dummy;
514    
515            while (XPending(display) > 0)
516            {
517                    XNextEvent(display, &xevent);
518    
519                    if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
520                    {
521                            DEBUG_KBD(("Filtering event\n"));
522                            continue;
523                    }
524    
525                    flags = 0;
526    
527                    switch (xevent.type)
528                    {
529                            case ClientMessage:
530                                    /* the window manager told us to quit */
531                                    if ((xevent.xclient.message_type == protocol_atom)
532                                        && (xevent.xclient.data.l[0] == kill_atom))
533                                            /* Quit */
534                                            return 0;
535                                    break;
536    
537                            case KeyPress:
538                                    if (IC != NULL)
539                                            /* Multi_key compatible version */
540                                    {
541                                            XmbLookupString(IC,
542                                                            (XKeyPressedEvent *) &
543                                                            xevent, str, sizeof(str), &keysym, &status);
544                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
545                                            {
546                                                    error("XmbLookupString failed with status 0x%x\n",
547                                                          status);
548                                                    break;
549                                            }
550                                    }
551                                    else
552                                    {
553                                            /* Plain old XLookupString */
554                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
555                                            XLookupString((XKeyEvent *) & xevent,
556                                                          str, sizeof(str), &keysym, NULL);
557                                    }
558    
559                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
560                                               get_ksname(keysym)));
561    
562                                    ev_time = time(NULL);
563                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
564                                            break;
565    
566                                    tr = xkeymap_translate_key(keysym,
567                                                               xevent.xkey.keycode, xevent.xkey.state);
568    
569                                    if (tr.scancode == 0)
570                                            break;
571    
572                                    ensure_remote_modifiers(ev_time, tr);
573    
574                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
575                                    break;
576    
577                            case KeyRelease:
578                                    XLookupString((XKeyEvent *) & xevent, str,
579                                                  sizeof(str), &keysym, NULL);
580    
581                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
582                                               get_ksname(keysym)));
583    
584                                    ev_time = time(NULL);
585                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
586                                            break;
587    
588                                    tr = xkeymap_translate_key(keysym,
589                                                               xevent.xkey.keycode, xevent.xkey.state);
590    
591                                    if (tr.scancode == 0)
592                                            break;
593    
594                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
595                                    break;
596    
597                            case ButtonPress:
598                                    flags = MOUSE_FLAG_DOWN;
599                                    /* fall through */
600    
601                            case ButtonRelease:
602                                    button = xkeymap_translate_button(xevent.xbutton.button);
603                                    if (button == 0)
604                                            break;
605    
606                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
607                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
608                                    break;
609    
610                            case MotionNotify:
611                                    if (fullscreen && !focused)
612                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
613                                                           CurrentTime);
614                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
615                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
616                                    break;
617    
618                            case FocusIn:
619                                    if (xevent.xfocus.mode == NotifyGrab)
620                                            break;
621                                    focused = True;
622                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
623                                                  &dummy, &dummy, &state);
624                                    reset_modifier_keys(state);
625                                    if (grab_keyboard && mouse_in_wnd)
626                                            XGrabKeyboard(display, wnd, True,
627                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
628                                    break;
629    
630                            case FocusOut:
631                                    if (xevent.xfocus.mode == NotifyUngrab)
632                                            break;
633                                    focused = False;
634                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
635                                            XUngrabKeyboard(display, CurrentTime);
636                                    break;
637    
638                            case EnterNotify:
639                                    /* we only register for this event when in fullscreen mode */
640                                    /* or grab_keyboard */
641                                    mouse_in_wnd = True;
642                                    if (fullscreen)
643                                    {
644                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
645                                                           CurrentTime);
646                                            break;
647                                    }
648                                    if (focused)
649                                            XGrabKeyboard(display, wnd, True,
650                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
651                                    break;
652    
653                            case LeaveNotify:
654                                    /* we only register for this event when grab_keyboard */
655                                    mouse_in_wnd = False;
656                                    XUngrabKeyboard(display, CurrentTime);
657                                    break;
658    
659                            case Expose:
660                                    XCopyArea(display, backstore, wnd, gc,
661                                              xevent.xexpose.x, xevent.xexpose.y,
662                                              xevent.xexpose.width,
663                                              xevent.xexpose.height,
664                                              xevent.xexpose.x, xevent.xexpose.y);
665                                    break;
666    
667                            case MappingNotify:
668                                    /* Refresh keyboard mapping if it has changed. This is important for
669                                       Xvnc, since it allocates keycodes dynamically */
670                                    if (xevent.xmapping.request == MappingKeyboard
671                                        || xevent.xmapping.request == MappingModifier)
672                                            XRefreshKeyboardMapping(&xevent.xmapping);
673    
674                                    if (xevent.xmapping.request == MappingModifier)
675                                    {
676                                            XFreeModifiermap(mod_map);
677                                            mod_map = XGetModifierMapping(display);
678                                    }
679                                    break;
680    
681                    }
682            }
683            /* Keep going */
684            return 1;
685    }
686    
687    /* Returns 0 after user quit, 1 otherwise */
688    int
689    ui_select(int rdp_socket)
690    {
691            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
692            fd_set rfds;
693    
694            FD_ZERO(&rfds);
695    
696            while (True)
697            {
698                    /* Process any events already waiting */
699                    if (!xwin_process_events())
700                            /* User quit */
701                            return 0;
702    
703                    FD_ZERO(&rfds);
704                    FD_SET(rdp_socket, &rfds);
705                    FD_SET(x_socket, &rfds);
706    
707                    switch (select(n, &rfds, NULL, NULL, NULL))
708                    {
709                            case -1:
710                                    error("select: %s\n", strerror(errno));
711    
712                            case 0:
713                                    continue;
714                    }
715    
716                    if (FD_ISSET(rdp_socket, &rfds))
717                            return 1;
718            }
719    }
720    
721    void
722    ui_move_pointer(int x, int y)
723    {
724            XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
725    }
726    
727    HBITMAP
728    ui_create_bitmap(int width, int height, uint8 * data)
729  {  {
730          XImage *image;          XImage *image;
731            Pixmap bitmap;
732            uint8 *tdata;
733    
734            tdata = (owncolmap ? data : translate_image(width, height, data));
735            bitmap = XCreatePixmap(display, wnd, width, height, depth);
736            image = XCreateImage(display, visual, depth, ZPixmap, 0,
737                                 (char *) tdata, width, height, 8, 0);
738    
739            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
740    
741            XFree(image);
742            if (!owncolmap)
743                    xfree(tdata);
744            return (HBITMAP) bitmap;
745    }
746    
747    void
748    ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
749    {
750            XImage *image;
751            uint8 *tdata;
752    
753            if (server_bpp == 16)
754            {
755                    image = XCreateImage(display, visual, depth, ZPixmap, 0,
756                                         (char *) data, width, height, 16, 0);
757    
758                    if (ownbackstore)
759                    {
760                            XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
761                            XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
762                    }
763                    else
764                    {
765                            XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
766                    }
767    
768                    XFree(image);
769                    return;
770            }
771            tdata = (owncolmap ? data : translate_image(width, height, data));
772            image = XCreateImage(display, visual, depth, ZPixmap, 0,
773                                 (char *) tdata, width, height, 8, 0);
774    
775            if (ownbackstore)
776            {
777                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
778                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
779            }
780            else
781            {
782                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
783            }
784    
785            XFree(image);
786            if (!owncolmap)
787                    xfree(tdata);
788    }
789    
790    void
791    ui_destroy_bitmap(HBITMAP bmp)
792    {
793            XFreePixmap(display, (Pixmap) bmp);
794    }
795    
796    HGLYPH
797    ui_create_glyph(int width, int height, uint8 * data)
798    {
799            XImage *image;
800            Pixmap bitmap;
801            int scanline;
802            GC gc;
803    
804            scanline = (width + 7) / 8;
805    
806            bitmap = XCreatePixmap(display, wnd, width, height, 1);
807            gc = XCreateGC(display, bitmap, 0, NULL);
808    
809            image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
810                                 width, height, 8, scanline);
811            image->byte_order = MSBFirst;
812            image->bitmap_bit_order = MSBFirst;
813            XInitImage(image);
814    
815            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
816    
817            XFree(image);
818            XFreeGC(display, gc);
819            return (HGLYPH) bitmap;
820    }
821    
822    void
823    ui_destroy_glyph(HGLYPH glyph)
824    {
825            XFreePixmap(display, (Pixmap) glyph);
826    }
827    
828    HCURSOR
829    ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
830                     uint8 * andmask, uint8 * xormask)
831    {
832            HGLYPH maskglyph, cursorglyph;
833            XColor bg, fg;
834            Cursor xcursor;
835            uint8 *cursor, *pcursor;
836            uint8 *mask, *pmask;
837            uint8 nextbit;
838            int scanline, offset;
839            int i, j;
840    
841            scanline = (width + 7) / 8;
842            offset = scanline * height;
843    
844            cursor = xmalloc(offset);
845            memset(cursor, 0, offset);
846    
847            mask = xmalloc(offset);
848            memset(mask, 0, offset);
849    
850            /* approximate AND and XOR masks with a monochrome X pointer */
851            for (i = 0; i < height; i++)
852            {
853                    offset -= scanline;
854                    pcursor = &cursor[offset];
855                    pmask = &mask[offset];
856    
857                    for (j = 0; j < scanline; j++)
858                    {
859                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
860                            {
861                                    if (xormask[0] || xormask[1] || xormask[2])
862                                    {
863                                            *pcursor |= (~(*andmask) & nextbit);
864                                            *pmask |= nextbit;
865                                    }
866                                    else
867                                    {
868                                            *pcursor |= ((*andmask) & nextbit);
869                                            *pmask |= (~(*andmask) & nextbit);
870                                    }
871    
872                                    xormask += 3;
873                            }
874    
875                            andmask++;
876                            pcursor++;
877                            pmask++;
878                    }
879            }
880    
881            fg.red = fg.blue = fg.green = 0xffff;
882            bg.red = bg.blue = bg.green = 0x0000;
883            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
884    
885            cursorglyph = ui_create_glyph(width, height, cursor);
886            maskglyph = ui_create_glyph(width, height, mask);
887    
888            xcursor =
889                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
890                                        (Pixmap) maskglyph, &fg, &bg, x, y);
891    
892            ui_destroy_glyph(maskglyph);
893            ui_destroy_glyph(cursorglyph);
894            xfree(mask);
895            xfree(cursor);
896            return (HCURSOR) xcursor;
897    }
898    
899    void
900    ui_set_cursor(HCURSOR cursor)
901    {
902            current_cursor = (Cursor) cursor;
903            XDefineCursor(display, wnd, current_cursor);
904    }
905    
906    void
907    ui_destroy_cursor(HCURSOR cursor)
908    {
909            XFreeCursor(display, (Cursor) cursor);
910    }
911    
912    #define MAKE_XCOLOR(xc,c) \
913                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
914                    (xc)->green = ((c)->green << 8) | (c)->green; \
915                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
916                    (xc)->flags = DoRed | DoGreen | DoBlue;
917    
918    
919    HCOLOURMAP
920    ui_create_colourmap(COLOURMAP * colours)
921    {
922            COLOURENTRY *entry;
923            int i, ncolours = colours->ncolours;
924            if (!owncolmap)
925            {
926                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
927                    XColor xentry;
928                    XColor xc_cache[256];
929                    uint32 colour;
930                    int colLookup = 256;
931                    for (i = 0; i < ncolours; i++)
932                    {
933                            entry = &colours->colours[i];
934                            MAKE_XCOLOR(&xentry, entry);
935    
936                            if (XAllocColor(display, xcolmap, &xentry) == 0)
937                            {
938                                    /* Allocation failed, find closest match. */
939                                    int j = 256;
940                                    int nMinDist = 3 * 256 * 256;
941                                    long nDist = nMinDist;
942    
943                                    /* only get the colors once */
944                                    while (colLookup--)
945                                    {
946                                            xc_cache[colLookup].pixel = colLookup;
947                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
948                                                    xc_cache[colLookup].blue = 0;
949                                            xc_cache[colLookup].flags = 0;
950                                            XQueryColor(display,
951                                                        DefaultColormap(display,
952                                                                        DefaultScreen(display)),
953                                                        &xc_cache[colLookup]);
954                                    }
955                                    colLookup = 0;
956    
957                                    /* approximate the pixel */
958                                    while (j--)
959                                    {
960                                            if (xc_cache[j].flags)
961                                            {
962                                                    nDist = ((long) (xc_cache[j].red >> 8) -
963                                                             (long) (xentry.red >> 8)) *
964                                                            ((long) (xc_cache[j].red >> 8) -
965                                                             (long) (xentry.red >> 8)) +
966                                                            ((long) (xc_cache[j].green >> 8) -
967                                                             (long) (xentry.green >> 8)) *
968                                                            ((long) (xc_cache[j].green >> 8) -
969                                                             (long) (xentry.green >> 8)) +
970                                                            ((long) (xc_cache[j].blue >> 8) -
971                                                             (long) (xentry.blue >> 8)) *
972                                                            ((long) (xc_cache[j].blue >> 8) -
973                                                             (long) (xentry.blue >> 8));
974                                            }
975                                            if (nDist < nMinDist)
976                                            {
977                                                    nMinDist = nDist;
978                                                    xentry.pixel = j;
979                                            }
980                                    }
981                            }
982                            colour = xentry.pixel;
983    
984                            /* update our cache */
985                            if (xentry.pixel < 256)
986                            {
987                                    xc_cache[xentry.pixel].red = xentry.red;
988                                    xc_cache[xentry.pixel].green = xentry.green;
989                                    xc_cache[xentry.pixel].blue = xentry.blue;
990    
991                            }
992    
993    
994                            /* byte swap here to make translate_image faster */
995                            map[i] = translate_colour(colour);
996                    }
997                    return map;
998            }
999            else
1000            {
1001                    XColor *xcolours, *xentry;
1002                    Colormap map;
1003    
1004                    xcolours = xmalloc(sizeof(XColor) * ncolours);
1005                    for (i = 0; i < ncolours; i++)
1006                    {
1007                            entry = &colours->colours[i];
1008                            xentry = &xcolours[i];
1009                            xentry->pixel = i;
1010                            MAKE_XCOLOR(xentry, entry);
1011                    }
1012    
1013          image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,                  map = XCreateColormap(display, wnd, visual, AllocAll);
1014                                  data, width, height, 32, width);                  XStoreColors(display, map, xcolours, ncolours);
1015    
1016          return (HBITMAP)image;                  xfree(xcolours);
1017                    return (HCOLOURMAP) map;
1018            }
1019  }  }
1020    
1021  void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)  void
1022    ui_destroy_colourmap(HCOLOURMAP map)
1023  {  {
1024          XDestroyImage((XImage *)bmp);          if (!owncolmap)
1025                    xfree(map);
1026            else
1027                    XFreeColormap(display, (Colormap) map);
1028  }  }
1029    
1030  void ui_paint_bitmap(HWINDOW wnd, HBITMAP bmp, int x, int y)  void
1031    ui_set_colourmap(HCOLOURMAP map)
1032  {  {
1033          XImage *image = (XImage *)bmp;          if (!owncolmap)
1034                    colmap = map;
1035            else
1036                    XSetWindowColormap(display, wnd, (Colormap) map);
1037    }
1038    
1039          XPutImage(wnd->display, wnd->wnd, wnd->gc, image,  void
1040                          0, 0, x, y, image->width, image->height);  ui_set_clip(int x, int y, int cx, int cy)
1041    {
1042            XRectangle rect;
1043    
1044          XSync(wnd->display, True);          rect.x = x;
1045            rect.y = y;
1046            rect.width = cx;
1047            rect.height = cy;
1048            XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1049  }  }
1050    
1051  HCOLORMAP ui_create_colormap(HWINDOW wnd, COLORMAP *colors)  void
1052    ui_reset_clip(void)
1053  {  {
1054          COLORENTRY *entry;          XRectangle rect;
1055          XColor *xcolors, *xentry;  
1056          Colormap map;          rect.x = 0;
1057          int i, ncolors = colors->ncolors;          rect.y = 0;
1058            rect.width = width;
1059            rect.height = height;
1060            XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1061    }
1062    
1063    void
1064    ui_bell(void)
1065    {
1066            XBell(display, 0);
1067    }
1068    
1069    void
1070    ui_destblt(uint8 opcode,
1071               /* dest */ int x, int y, int cx, int cy)
1072    {
1073            SET_FUNCTION(opcode);
1074            FILL_RECTANGLE(x, y, cx, cy);
1075            RESET_FUNCTION(opcode);
1076    }
1077    
1078    void
1079    ui_patblt(uint8 opcode,
1080              /* dest */ int x, int y, int cx, int cy,
1081              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1082    {
1083            Pixmap fill;
1084            uint8 i, ipattern[8];
1085    
1086            SET_FUNCTION(opcode);
1087    
1088          xcolors = malloc(sizeof(XColor) * ncolors);          switch (brush->style)
         for (i = 0; i < ncolors; i++)  
1089          {          {
1090                  entry = &colors->colors[i];                  case 0: /* Solid */
1091                  xentry = &xcolors[i];                          SET_FOREGROUND(fgcolour);
1092                            FILL_RECTANGLE(x, y, cx, cy);
1093                            break;
1094    
1095                    case 3: /* Pattern */
1096                            for (i = 0; i != 8; i++)
1097                                    ipattern[7 - i] = brush->pattern[i];
1098                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1099    
1100                            SET_FOREGROUND(bgcolour);
1101                            SET_BACKGROUND(fgcolour);
1102                            XSetFillStyle(display, gc, FillOpaqueStippled);
1103                            XSetStipple(display, gc, fill);
1104                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1105    
1106                            FILL_RECTANGLE(x, y, cx, cy);
1107    
1108                            XSetFillStyle(display, gc, FillSolid);
1109                            XSetTSOrigin(display, gc, 0, 0);
1110                            ui_destroy_glyph((HGLYPH) fill);
1111                            break;
1112    
1113                  xentry->pixel = i;                  default:
1114                  xentry->red = entry->red << 8;                          unimpl("brush %d\n", brush->style);
                 xentry->blue = entry->blue << 8;  
                 xentry->green = entry->green << 8;  
                 xentry->flags = DoRed | DoBlue | DoGreen;  
1115          }          }
1116    
1117          map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);          RESET_FUNCTION(opcode);
1118          XStoreColors(wnd->display, map, xcolors, ncolors);  }
1119    
1120    void
1121    ui_screenblt(uint8 opcode,
1122                 /* dest */ int x, int y, int cx, int cy,
1123                 /* src */ int srcx, int srcy)
1124    {
1125            SET_FUNCTION(opcode);
1126            XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1127            if (ownbackstore)
1128                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1129            RESET_FUNCTION(opcode);
1130    }
1131    
1132    void
1133    ui_memblt(uint8 opcode,
1134              /* dest */ int x, int y, int cx, int cy,
1135              /* src */ HBITMAP src, int srcx, int srcy)
1136    {
1137            SET_FUNCTION(opcode);
1138            XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1139            if (ownbackstore)
1140                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1141            RESET_FUNCTION(opcode);
1142    }
1143    
1144    void
1145    ui_triblt(uint8 opcode,
1146              /* dest */ int x, int y, int cx, int cy,
1147              /* src */ HBITMAP src, int srcx, int srcy,
1148              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1149    {
1150            /* This is potentially difficult to do in general. Until someone
1151               comes up with a more efficient way of doing it I am using cases. */
1152    
1153          free(xcolors);          switch (opcode)
1154          return (HCOLORMAP)map;          {
1155                    case 0x69:      /* PDSxxn */
1156                            ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1157                            ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1158                            break;
1159    
1160                    case 0xb8:      /* PSDPxax */
1161                            ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1162                            ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1163                            ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1164                            break;
1165    
1166                    case 0xc0:      /* PSa */
1167                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1168                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1169                            break;
1170    
1171                    default:
1172                            unimpl("triblt 0x%x\n", opcode);
1173                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1174            }
1175  }  }
1176    
1177  void ui_destroy_colormap(HWINDOW wnd, HCOLORMAP map)  void
1178    ui_line(uint8 opcode,
1179            /* dest */ int startx, int starty, int endx, int endy,
1180            /* pen */ PEN * pen)
1181  {  {
1182          XFreeColormap(wnd->display, (Colormap)map);          SET_FUNCTION(opcode);
1183            SET_FOREGROUND(pen->colour);
1184            XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1185            if (ownbackstore)
1186                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1187            RESET_FUNCTION(opcode);
1188  }  }
1189    
1190  void ui_set_colormap(HWINDOW wnd, HCOLORMAP map)  void
1191    ui_rect(
1192                   /* dest */ int x, int y, int cx, int cy,
1193                   /* brush */ int colour)
1194  {  {
1195          XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);          SET_FOREGROUND(colour);
1196            FILL_RECTANGLE(x, y, cx, cy);
1197  }  }
1198    
1199  void ui_draw_rectangle(HWINDOW wnd, int x, int y, int width, int height)  /* warning, this function only draws on wnd or backstore, not both */
1200    void
1201    ui_draw_glyph(int mixmode,
1202                  /* dest */ int x, int y, int cx, int cy,
1203                  /* src */ HGLYPH glyph, int srcx, int srcy,
1204                  int bgcolour, int fgcolour)
1205  {  {
1206          static int white = 0;          SET_FOREGROUND(fgcolour);
1207            SET_BACKGROUND(bgcolour);
1208    
1209            XSetFillStyle(display, gc,
1210                          (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1211            XSetStipple(display, gc, (Pixmap) glyph);
1212            XSetTSOrigin(display, gc, x, y);
1213    
1214          XSetForeground(wnd->display, wnd->gc, white);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
         XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, width, height);  
1215    
1216          white++;          XSetFillStyle(display, gc, FillSolid);
1217  }  }
1218    
1219  void ui_move_pointer(HWINDOW wnd, int x, int y)  #define DO_GLYPH(ttext,idx) \
1220    {\
1221      glyph = cache_get_font (font, ttext[idx]);\
1222      if (!(flags & TEXT2_IMPLICIT_X))\
1223        {\
1224          xyoffset = ttext[++idx];\
1225          if ((xyoffset & 0x80))\
1226            {\
1227              if (flags & TEXT2_VERTICAL) \
1228                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1229              else\
1230                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1231              idx += 2;\
1232            }\
1233          else\
1234            {\
1235              if (flags & TEXT2_VERTICAL) \
1236                y += xyoffset;\
1237              else\
1238                x += xyoffset;\
1239            }\
1240        }\
1241      if (glyph != NULL)\
1242        {\
1243          ui_draw_glyph (mixmode, x + glyph->offset,\
1244                         y + glyph->baseline,\
1245                         glyph->width, glyph->height,\
1246                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1247          if (flags & TEXT2_IMPLICIT_X)\
1248            x += glyph->width;\
1249        }\
1250    }
1251    
1252    void
1253    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1254                 int clipx, int clipy, int clipcx, int clipcy,
1255                 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1256                 int fgcolour, uint8 * text, uint8 length)
1257  {  {
1258          XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);          FONTGLYPH *glyph;
1259            int i, j, xyoffset;
1260            DATABLOB *entry;
1261    
1262            SET_FOREGROUND(bgcolour);
1263    
1264            if (boxcx > 1)
1265            {
1266                    FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1267            }
1268            else if (mixmode == MIX_OPAQUE)
1269            {
1270                    FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1271            }
1272    
1273            /* Paint text, character by character */
1274            for (i = 0; i < length;)
1275            {
1276                    switch (text[i])
1277                    {
1278                            case 0xff:
1279                                    if (i + 2 < length)
1280                                            cache_put_text(text[i + 1], text, text[i + 2]);
1281                                    else
1282                                    {
1283                                            error("this shouldn't be happening\n");
1284                                            exit(1);
1285                                    }
1286                                    /* this will move pointer from start to first character after FF command */
1287                                    length -= i + 3;
1288                                    text = &(text[i + 3]);
1289                                    i = 0;
1290                                    break;
1291    
1292                            case 0xfe:
1293                                    entry = cache_get_text(text[i + 1]);
1294                                    if (entry != NULL)
1295                                    {
1296                                            if ((((uint8 *) (entry->data))[1] ==
1297                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
1298                                            {
1299                                                    if (flags & TEXT2_VERTICAL)
1300                                                            y += text[i + 2];
1301                                                    else
1302                                                            x += text[i + 2];
1303                                            }
1304                                            for (j = 0; j < entry->size; j++)
1305                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1306                                    }
1307                                    if (i + 2 < length)
1308                                            i += 3;
1309                                    else
1310                                            i += 2;
1311                                    length -= i;
1312                                    /* this will move pointer from start to first character after FE command */
1313                                    text = &(text[i]);
1314                                    i = 0;
1315                                    break;
1316    
1317                            default:
1318                                    DO_GLYPH(text, i);
1319                                    i++;
1320                                    break;
1321                    }
1322            }
1323            if (ownbackstore)
1324            {
1325                    if (boxcx > 1)
1326                            XCopyArea(display, backstore, wnd, gc, boxx,
1327                                      boxy, boxcx, boxcy, boxx, boxy);
1328                    else
1329                            XCopyArea(display, backstore, wnd, gc, clipx,
1330                                      clipy, clipcx, clipcy, clipx, clipy);
1331            }
1332    }
1333    
1334    void
1335    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1336    {
1337            Pixmap pix;
1338            XImage *image;
1339    
1340            if (ownbackstore)
1341            {
1342                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1343            }
1344            else
1345            {
1346                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1347                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1348                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1349                    XFreePixmap(display, pix);
1350            }
1351    
1352            offset *= bpp / 8;
1353            cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1354    
1355            XDestroyImage(image);
1356    }
1357    
1358    void
1359    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1360    {
1361            XImage *image;
1362            uint8 *data;
1363    
1364            offset *= bpp / 8;
1365            data = cache_get_desktop(offset, cx, cy, bpp / 8);
1366            if (data == NULL)
1367                    return;
1368    
1369            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1370                                 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1371    
1372            if (ownbackstore)
1373            {
1374                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1375                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1376            }
1377            else
1378            {
1379                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1380            }
1381    
1382            XFree(image);
1383  }  }

Legend:
Removed from v.7  
changed lines
  Added in v.309

  ViewVC Help
Powered by ViewVC 1.1.26