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

Legend:
Removed from v.9  
changed lines
  Added in v.328

  ViewVC Help
Powered by ViewVC 1.1.26