/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/xwin.c

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

sourceforge.net/trunk/rdesktop/xwin.c revision 1302 by ossman_, Thu Oct 26 09:47:17 2006 UTC sourceforge.net/rdesktop/trunk/xwin.c revision 1488 by astrand, Fri May 15 08:18:08 2009 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2005     Copyright (C) Matthew Chapman 1999-2008
5       Copyright 2007-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
6    
7     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 20  Line 21 
21    
22  #include <X11/Xlib.h>  #include <X11/Xlib.h>
23  #include <X11/Xutil.h>  #include <X11/Xutil.h>
24    #include <X11/Xproto.h>
25  #include <unistd.h>  #include <unistd.h>
26  #include <sys/time.h>  #include <sys/time.h>
27  #include <time.h>  #include <time.h>
# Line 28  Line 30 
30  #include "rdesktop.h"  #include "rdesktop.h"
31  #include "xproto.h"  #include "xproto.h"
32    
 /* We can't include Xproto.h because of conflicting defines for BOOL */  
 #define X_ConfigureWindow              12  
   
33  extern int g_width;  extern int g_width;
34  extern int g_height;  extern int g_height;
35  extern int g_xpos;  extern int g_xpos;
36  extern int g_ypos;  extern int g_ypos;
37  extern int g_pos;  extern int g_pos;
38  extern BOOL g_sendmotion;  extern RD_BOOL g_sendmotion;
39  extern BOOL g_fullscreen;  extern RD_BOOL g_fullscreen;
40  extern BOOL g_grab_keyboard;  extern RD_BOOL g_grab_keyboard;
41  extern BOOL g_hide_decorations;  extern RD_BOOL g_hide_decorations;
42  extern char g_title[];  extern char g_title[];
43  /* Color depth of the RDP session.  /* Color depth of the RDP session.
44     As of RDP 5.1, it may be 8, 15, 16 or 24. */     As of RDP 5.1, it may be 8, 15, 16 or 24. */
# Line 71  typedef struct _seamless_window Line 70  typedef struct _seamless_window
70          unsigned int desktop;          unsigned int desktop;
71          struct timeval *position_timer;          struct timeval *position_timer;
72    
73          BOOL outstanding_position;          RD_BOOL outstanding_position;
74          unsigned int outpos_serial;          unsigned int outpos_serial;
75          int outpos_xoffset, outpos_yoffset;          int outpos_xoffset, outpos_yoffset;
76          int outpos_width, outpos_height;          int outpos_width, outpos_height;
77    
78            unsigned int icon_size;
79            unsigned int icon_offset;
80            char icon_buffer[32 * 32 * 4];
81    
82          struct _seamless_window *next;          struct _seamless_window *next;
83  } seamless_window;  } seamless_window;
84  static seamless_window *g_seamless_windows = NULL;  static seamless_window *g_seamless_windows = NULL;
85  static unsigned long g_seamless_focused = 0;  static unsigned long g_seamless_focused = 0;
86  static BOOL g_seamless_started = False; /* Server end is up and running */  static RD_BOOL g_seamless_started = False;      /* Server end is up and running */
87  static BOOL g_seamless_active = False;  /* We are currently in seamless mode */  static RD_BOOL g_seamless_active = False;       /* We are currently in seamless mode */
88  static BOOL g_seamless_hidden = False;  /* Desktop is hidden on server */  static RD_BOOL g_seamless_hidden = False;       /* Desktop is hidden on server */
89  extern BOOL g_seamless_rdp;  static RD_BOOL g_seamless_broken_restack = False;       /* WM does not properly restack */
90    extern RD_BOOL g_seamless_rdp;
91    
92  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
93  BOOL g_enable_compose = False;  RD_BOOL g_enable_compose = False;
94  BOOL g_Unobscured;              /* used for screenblt */  RD_BOOL g_Unobscured;           /* used for screenblt */
95  static GC g_gc = NULL;  static GC g_gc = NULL;
96  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
97  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
# Line 104  static int g_bpp; Line 108  static int g_bpp;
108  static XIM g_IM;  static XIM g_IM;
109  static XIC g_IC;  static XIC g_IC;
110  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
111    /* Maps logical (xmodmap -pp) pointing device buttons (0-based) back
112       to physical (1-based) indices. */
113    static unsigned char g_pointer_log_to_phys_map[32];
114  static Cursor g_current_cursor;  static Cursor g_current_cursor;
115  static HCURSOR g_null_cursor = NULL;  static RD_HCURSOR g_null_cursor = NULL;
116  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
117  extern Atom g_net_wm_state_atom;  extern Atom g_net_wm_state_atom;
118  extern Atom g_net_wm_desktop_atom;  extern Atom g_net_wm_desktop_atom;
119  static BOOL g_focused;  static RD_BOOL g_focused;
120  static BOOL g_mouse_in_wnd;  static RD_BOOL g_mouse_in_wnd;
121  /* Indicates that:  /* Indicates that:
122     1) visual has 15, 16 or 24 depth and the same color channel masks     1) visual has 15, 16 or 24 depth and the same color channel masks
123        as its RDP equivalent (implies X server is LE),        as its RDP equivalent (implies X server is LE),
124     2) host is LE     2) host is LE
125     This will trigger an optimization whose real value is questionable.     This will trigger an optimization whose real value is questionable.
126  */  */
127  static BOOL g_compatible_arch;  static RD_BOOL g_compatible_arch;
128  /* Indicates whether RDP's bitmaps and our XImages have the same  /* Indicates whether RDP's bitmaps and our XImages have the same
129     binary format. If so, we can avoid an expensive translation.     binary format. If so, we can avoid an expensive translation.
130     Note that this can be true when g_compatible_arch is false,     Note that this can be true when g_compatible_arch is false,
# Line 128  static BOOL g_compatible_arch; Line 135  static BOOL g_compatible_arch;
135     ('host' is the machine running rdesktop; the host simply memcpy's     ('host' is the machine running rdesktop; the host simply memcpy's
136      so its endianess doesn't matter)      so its endianess doesn't matter)
137   */   */
138  static BOOL g_no_translate_image = False;  static RD_BOOL g_no_translate_image = False;
139    
140  /* endianness */  /* endianness */
141  static BOOL g_host_be;  static RD_BOOL g_host_be;
142  static BOOL g_xserver_be;  static RD_BOOL g_xserver_be;
143  static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;  static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
144  static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;  static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
145    
146  /* software backing store */  /* software backing store */
147  extern BOOL g_ownbackstore;  extern RD_BOOL g_ownbackstore;
148  static Pixmap g_backstore = 0;  static Pixmap g_backstore = 0;
149    
150  /* Moving in single app mode */  /* Moving in single app mode */
151  static BOOL g_moving_wnd;  static RD_BOOL g_moving_wnd;
152  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
153  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
154  static BOOL g_using_full_workarea = False;  static RD_BOOL g_using_full_workarea = False;
155    
156  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
157  extern int g_dsp_fd;  extern RD_BOOL g_rdpsnd;
 extern BOOL g_dsp_busy;  
 extern BOOL g_rdpsnd;  
158  #endif  #endif
159    
160  /* MWM decorations */  /* MWM decorations */
# Line 250  seamless_XDrawLines(Drawable d, XPoint * Line 255  seamless_XDrawLines(Drawable d, XPoint *
255  }  }
256    
257  /* colour maps */  /* colour maps */
258  extern BOOL g_owncolmap;  extern RD_BOOL g_owncolmap;
259  static Colormap g_xcolmap;  static Colormap g_xcolmap;
260  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
261    
# Line 474  sw_handle_restack(seamless_window * sw) Line 479  sw_handle_restack(seamless_window * sw)
479    
480    
481  static seamless_group *  static seamless_group *
482  sw_find_group(unsigned long id, BOOL dont_create)  sw_find_group(unsigned long id, RD_BOOL dont_create)
483  {  {
484          seamless_window *sw;          seamless_window *sw;
485          seamless_group *sg;          seamless_group *sg;
# Line 525  mwm_hide_decorations(Window wnd) Line 530  mwm_hide_decorations(Window wnd)
530    
531  }  }
532    
533    typedef struct _sw_configurenotify_context
534    {
535            Window window;
536            unsigned long serial;
537    } sw_configurenotify_context;
538    
539    /* Predicate procedure for sw_wait_configurenotify */
540    static Bool
541    sw_configurenotify_p(Display * display, XEvent * xevent, XPointer arg)
542    {
543            sw_configurenotify_context *context = (sw_configurenotify_context *) arg;
544            if (xevent->xany.type == ConfigureNotify
545                && xevent->xconfigure.window == context->window
546                && xevent->xany.serial >= context->serial)
547                    return True;
548    
549            return False;
550    }
551    
552    /* Wait for a ConfigureNotify, with a equal or larger serial, on the
553       specified window. The event will be removed from the queue. We
554       could use XMaskEvent(StructureNotifyMask), but we would then risk
555       throwing away crucial events like DestroyNotify.
556    
557       After a ConfigureWindow, according to ICCCM section 4.1.5, we
558       should recieve a ConfigureNotify, either a real or synthetic
559       one. This indicates that the configure has been "completed".
560       However, some WMs such as several versions of Metacity fails to
561       send synthetic events. See bug
562       http://bugzilla.gnome.org/show_bug.cgi?id=322840. We need to use a
563       timeout to avoid a hang. Tk uses the same approach. */
564    static void
565    sw_wait_configurenotify(Window wnd, unsigned long serial)
566    {
567            XEvent xevent;
568            sw_configurenotify_context context;
569            struct timeval now;
570            struct timeval nextsecond;
571            RD_BOOL got = False;
572    
573            context.window = wnd;
574            context.serial = serial;
575    
576            gettimeofday(&nextsecond, NULL);
577            nextsecond.tv_sec += 1;
578    
579            do
580            {
581                    if (XCheckIfEvent(g_display, &xevent, sw_configurenotify_p, (XPointer) & context))
582                    {
583                            got = True;
584                            break;
585                    }
586                    usleep(100000);
587                    gettimeofday(&now, NULL);
588            }
589            while (timercmp(&now, &nextsecond, <));
590    
591            if (!got)
592            {
593                    warning("Broken Window Manager: Timeout while waiting for ConfigureNotify\n");
594            }
595    }
596    
597    /* Get the toplevel window, in case of reparenting */
598    static Window
599    sw_get_toplevel(Window wnd)
600    {
601            Window root, parent;
602            Window *child_list;
603            unsigned int num_children;
604    
605            while (1)
606            {
607                    XQueryTree(g_display, wnd, &root, &parent, &child_list, &num_children);
608                    if (root == parent)
609                    {
610                            break;
611                    }
612                    else if (!parent)
613                    {
614                            warning("Internal error: sw_get_toplevel called with root window\n");
615                    }
616    
617                    wnd = parent;
618            }
619    
620            return wnd;
621    }
622    
623    
624    /* Check if wnd is already behind a window wrt stacking order */
625    static RD_BOOL
626    sw_window_is_behind(Window wnd, Window behind)
627    {
628            Window dummy1, dummy2;
629            Window *child_list;
630            unsigned int num_children;
631            unsigned int i;
632            RD_BOOL found_behind = False;
633            RD_BOOL found_wnd = False;
634    
635            wnd = sw_get_toplevel(wnd);
636            behind = sw_get_toplevel(behind);
637    
638            XQueryTree(g_display, RootWindowOfScreen(g_screen), &dummy1, &dummy2, &child_list,
639                       &num_children);
640    
641            for (i = num_children - 1; i >= 0; i--)
642            {
643                    if (child_list[i] == behind)
644                    {
645                            found_behind = True;
646                    }
647                    else if (child_list[i] == wnd)
648                    {
649                            found_wnd = True;
650                            break;
651                    }
652            }
653    
654            if (child_list)
655                    XFree(child_list);
656    
657            if (!found_wnd)
658            {
659                    warning("sw_window_is_behind: Unable to find window 0x%lx\n", wnd);
660    
661                    if (!found_behind)
662                    {
663                            warning("sw_window_is_behind: Unable to find behind window 0x%lx\n",
664                                    behind);
665                    }
666            }
667    
668            return found_behind;
669    }
670    
671    
672    /* Test if the window manager correctly handles window restacking. In
673       particular, we are testing if it's possible to place a window
674       between two other windows. Many WMs such as Metacity can only stack
675       windows on the top or bottom. The window creation should mostly
676       match ui_seamless_create_window. */
677    static void
678    seamless_restack_test()
679    {
680            /* The goal is to have the middle window between top and
681               bottom.  The middle window is initially at the top,
682               though. */
683            Window wnds[3];         /* top, middle and bottom */
684            int i;
685            XEvent xevent;
686            XWindowChanges values;
687            unsigned long restack_serial;
688    
689            for (i = 0; i < 3; i++)
690            {
691                    char name[64];
692                    wnds[i] =
693                            XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, 20, 20,
694                                                0, 0, 0);
695                    snprintf(name, sizeof(name), "SeamlessRDP restack test - window %d", i);
696                    XStoreName(g_display, wnds[i], name);
697                    ewmh_set_wm_name(wnds[i], name);
698    
699                    /* Hide decorations. Often this means that no
700                       reparenting will be done, which makes the restack
701                       easier. Besides, we want to mimic our other
702                       seamless windows as much as possible. We must still
703                       handle the case with reparenting, though. */
704                    mwm_hide_decorations(wnds[i]);
705    
706                    /* Prevent windows from appearing in task bar */
707                    XSetTransientForHint(g_display, wnds[i], RootWindowOfScreen(g_screen));
708                    ewmh_set_window_popup(wnds[i]);
709    
710                    /* We need to catch MapNotify/ConfigureNotify */
711                    XSelectInput(g_display, wnds[i], StructureNotifyMask);
712            }
713    
714            /* Map Windows. Currently, we assume that XMapRaised places
715               the window on the top of the stack. Should be fairly safe;
716               the window is configured before it's mapped. */
717            XMapRaised(g_display, wnds[2]); /* bottom */
718            do
719            {
720                    XWindowEvent(g_display, wnds[2], StructureNotifyMask, &xevent);
721            }
722            while (xevent.type != MapNotify);
723            XMapRaised(g_display, wnds[0]); /* top */
724            do
725            {
726                    XWindowEvent(g_display, wnds[0], StructureNotifyMask, &xevent);
727            }
728            while (xevent.type != MapNotify);
729            XMapRaised(g_display, wnds[1]); /* middle */
730            do
731            {
732                    XWindowEvent(g_display, wnds[1], StructureNotifyMask, &xevent);
733            }
734            while (xevent.type != MapNotify);
735    
736            /* The stacking order should now be 1 - 0 - 2 */
737            if (!sw_window_is_behind(wnds[0], wnds[1]) || !sw_window_is_behind(wnds[2], wnds[1]))
738            {
739                    /* Ok, technically a WM is allowed to stack windows arbitrarily, but... */
740                    warning("Broken Window Manager: Unable to test window restacking\n");
741                    g_seamless_broken_restack = True;
742                    for (i = 0; i < 3; i++)
743                            XDestroyWindow(g_display, wnds[i]);
744                    return;
745            }
746    
747            /* Restack, using XReconfigureWMWindow, which should correctly
748               handle reparented windows as well as nonreparenting WMs. */
749            values.stack_mode = Below;
750            values.sibling = wnds[0];
751            restack_serial = XNextRequest(g_display);
752            XReconfigureWMWindow(g_display, wnds[1], DefaultScreen(g_display), CWStackMode | CWSibling,
753                                 &values);
754            sw_wait_configurenotify(wnds[1], restack_serial);
755    
756            /* Now verify that middle is behind top but not behind
757               bottom */
758            if (!sw_window_is_behind(wnds[1], wnds[0]))
759            {
760                    warning("Broken Window Manager: doesn't handle restack (restack request was ignored)\n");
761                    g_seamless_broken_restack = True;
762            }
763            else if (sw_window_is_behind(wnds[1], wnds[2]))
764            {
765                    warning("Broken Window Manager: doesn't handle restack (window was moved to bottom)\n");
766                    g_seamless_broken_restack = True;
767            }
768    
769            /* Destroy windows */
770            for (i = 0; i < 3; i++)
771                    XDestroyWindow(g_display, wnds[i]);
772    }
773    
774  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
775  { \  { \
776          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
# Line 579  translate_colour(uint32 colour) Line 825  translate_colour(uint32 colour)
825                          SPLITCOLOUR16(colour, pc);                          SPLITCOLOUR16(colour, pc);
826                          break;                          break;
827                  case 24:                  case 24:
828                    case 32:
829                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
830                          break;                          break;
831                  default:                  default:
# Line 1187  translate_image(int width, int height, u Line 1434  translate_image(int width, int height, u
1434             is only set for compatible depths, but the RDP depth might've             is only set for compatible depths, but the RDP depth might've
1435             changed during connection negotiations.             changed during connection negotiations.
1436           */           */
1437    
1438            /* todo */
1439            if (g_server_depth == 32 && g_depth == 24)
1440            {
1441                    return data;
1442            }
1443    
1444          if (g_no_translate_image)          if (g_no_translate_image)
1445          {          {
1446                  if ((g_depth == 15 && g_server_depth == 15) ||                  if ((g_depth == 15 && g_server_depth == 15) ||
# Line 1264  translate_image(int width, int height, u Line 1518  translate_image(int width, int height, u
1518          return out;          return out;
1519  }  }
1520    
1521  BOOL  static void
1522    xwin_refresh_pointer_map(void)
1523    {
1524            unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)];
1525            int i, pointer_buttons;
1526    
1527            pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map));
1528            if (pointer_buttons > sizeof(phys_to_log_map))
1529                    pointer_buttons = sizeof(phys_to_log_map);
1530    
1531            /* if multiple physical buttons map to the same logical button, then
1532             * use the lower numbered physical one */
1533            for (i = pointer_buttons - 1; i >= 0; i--)
1534            {
1535                    /* a user could specify arbitrary values for the logical button
1536                     * number, ignore any that are abnormally large */
1537                    if (phys_to_log_map[i] > sizeof(g_pointer_log_to_phys_map))
1538                            continue;
1539                    g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
1540            }
1541    }
1542    
1543    RD_BOOL
1544  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1545  {  {
1546          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
# Line 1312  calculate_mask_weight(uint32 mask) Line 1588  calculate_mask_weight(uint32 mask)
1588          return weight;          return weight;
1589  }  }
1590    
1591  static BOOL  static RD_BOOL
1592  select_visual(int screen_num)  select_visual(int screen_num)
1593  {  {
1594          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
# Line 1351  select_visual(int screen_num) Line 1627  select_visual(int screen_num)
1627                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
1628                  {                  {
1629                          XVisualInfo *visual_info = &vmatches[i];                          XVisualInfo *visual_info = &vmatches[i];
1630                          BOOL can_translate_to_bpp = False;                          RD_BOOL can_translate_to_bpp = False;
1631                          int j;                          int j;
1632    
1633                          /* Try to find a no-translation visual that'll                          /* Try to find a no-translation visual that'll
# Line 1508  select_visual(int screen_num) Line 1784  select_visual(int screen_num)
1784  }  }
1785    
1786  static XErrorHandler g_old_error_handler;  static XErrorHandler g_old_error_handler;
1787    static RD_BOOL g_error_expected = False;
1788    
1789    /* Check if the X11 window corresponding to a seamless window with
1790       specified id exists. */
1791    RD_BOOL
1792    sw_window_exists(unsigned long id)
1793    {
1794            seamless_window *sw;
1795            char *name;
1796            Status sts = 0;
1797    
1798            sw = sw_get_window_by_id(id);
1799            if (!sw)
1800                    return False;
1801    
1802            g_error_expected = True;
1803            sts = XFetchName(g_display, sw->wnd, &name);
1804            g_error_expected = False;
1805            if (sts)
1806            {
1807                    XFree(name);
1808            }
1809    
1810            return sts;
1811    }
1812    
1813  static int  static int
1814  error_handler(Display * dpy, XErrorEvent * eev)  error_handler(Display * dpy, XErrorEvent * eev)
1815  {  {
1816          if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))          if (g_error_expected)
         {  
                 fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");  
                 fprintf(stderr,  
                         "This is most likely caused by a broken window manager (commonly KWin).\n");  
1817                  return 0;                  return 0;
         }  
1818    
1819          return g_old_error_handler(dpy, eev);          return g_old_error_handler(dpy, eev);
1820  }  }
1821    
1822  BOOL  RD_BOOL
1823  ui_init(void)  ui_init(void)
1824  {  {
1825          int screen_num;          int screen_num;
# Line 1537  ui_init(void) Line 1833  ui_init(void)
1833    
1834          {          {
1835                  uint16 endianess_test = 1;                  uint16 endianess_test = 1;
1836                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test));
1837          }          }
1838    
1839          g_old_error_handler = XSetErrorHandler(error_handler);          g_old_error_handler = XSetErrorHandler(error_handler);
# Line 1618  ui_init(void) Line 1914  ui_init(void)
1914          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1915    
1916          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1917            xwin_refresh_pointer_map();
1918    
1919          xkeymap_init();          xkeymap_init();
1920    
# Line 1627  ui_init(void) Line 1924  ui_init(void)
1924          xclip_init();          xclip_init();
1925          ewmh_init();          ewmh_init();
1926          if (g_seamless_rdp)          if (g_seamless_rdp)
1927            {
1928                  seamless_init();                  seamless_init();
1929            }
1930    
1931          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1932    
# Line 1689  get_input_mask(long *input_mask) Line 1988  get_input_mask(long *input_mask)
1988                  *input_mask |= LeaveWindowMask;                  *input_mask |= LeaveWindowMask;
1989  }  }
1990    
1991  BOOL  RD_BOOL
1992  ui_create_window(void)  ui_create_window(void)
1993  {  {
1994          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
# Line 1737  ui_create_window(void) Line 2036  ui_create_window(void)
2036          }          }
2037    
2038          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
2039            ewmh_set_wm_name(g_wnd, g_title);
2040    
2041          if (g_hide_decorations)          if (g_hide_decorations)
2042                  mwm_hide_decorations(g_wnd);                  mwm_hide_decorations(g_wnd);
# Line 1801  ui_create_window(void) Line 2101  ui_create_window(void)
2101          if (g_null_cursor == NULL)          if (g_null_cursor == NULL)
2102                  g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);                  g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
2103    
2104            if (g_seamless_rdp)
2105            {
2106                    seamless_restack_test();
2107            }
2108    
2109          return True;          return True;
2110  }  }
2111    
# Line 1876  xwin_toggle_fullscreen(void) Line 2181  xwin_toggle_fullscreen(void)
2181  }  }
2182    
2183  static void  static void
2184  handle_button_event(XEvent xevent, BOOL down)  handle_button_event(XEvent xevent, RD_BOOL down)
2185  {  {
2186          uint16 button, flags = 0;          uint16 button, flags = 0;
2187          g_last_gesturetime = xevent.xbutton.time;          g_last_gesturetime = xevent.xbutton.time;
2188            /* Reverse the pointer button mapping, e.g. in the case of
2189               "left-handed mouse mode"; the RDP session expects to
2190               receive physical buttons (true in mstsc as well) and
2191               logical button behavior depends on the remote desktop's own
2192               mouse settings */
2193            xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
2194          button = xkeymap_translate_button(xevent.xbutton.button);          button = xkeymap_translate_button(xevent.xbutton.button);
2195          if (button == 0)          if (button == 0)
2196                  return;                  return;
# Line 1992  xwin_process_events(void) Line 2303  xwin_process_events(void)
2303                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
2304                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
2305                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
2306                                          /* Quit */                                  {
2307                                          return 0;                                          /* When killing a seamless window, close the window on the
2308                                               serverside instead of terminating rdesktop */
2309                                            sw = sw_get_window_by_wnd(xevent.xclient.window);
2310                                            if (!sw)
2311                                                    /* Otherwise, quit */
2312                                                    return 0;
2313                                            /* send seamless destroy process message */
2314                                            seamless_send_destroy(sw->id);
2315                                    }
2316                                  break;                                  break;
2317    
2318                          case KeyPress:                          case KeyPress:
# Line 2094  xwin_process_events(void) Line 2413  xwin_process_events(void)
2413                                  if (!sw)                                  if (!sw)
2414                                          break;                                          break;
2415    
2416                                    /* Menu windows are real X11 windows,
2417                                       with focus. When such a window is
2418                                       destroyed, focus is reverted to the
2419                                       main application window, which
2420                                       would cause us to send FOCUS. This
2421                                       breaks window switching in, say,
2422                                       Seamonkey. We shouldn't need to
2423                                       send FOCUS: Windows should also
2424                                       revert focus to some other window
2425                                       when the menu window is
2426                                       destroyed. So, we only send FOCUS
2427                                       if the previous focus window still
2428                                       exists. */
2429                                  if (sw->id != g_seamless_focused)                                  if (sw->id != g_seamless_focused)
2430                                  {                                  {
2431                                          seamless_send_focus(sw->id, 0);  
2432                                            if (sw_window_exists(g_seamless_focused))
2433                                                    seamless_send_focus(sw->id, 0);
2434                                          g_seamless_focused = sw->id;                                          g_seamless_focused = sw->id;
2435                                  }                                  }
2436                                  break;                                  break;
# Line 2167  xwin_process_events(void) Line 2501  xwin_process_events(void)
2501                                          XFreeModifiermap(g_mod_map);                                          XFreeModifiermap(g_mod_map);
2502                                          g_mod_map = XGetModifierMapping(g_display);                                          g_mod_map = XGetModifierMapping(g_display);
2503                                  }                                  }
2504    
2505                                    if (xevent.xmapping.request == MappingPointer)
2506                                    {
2507                                            xwin_refresh_pointer_map();
2508                                    }
2509    
2510                                  break;                                  break;
2511    
2512                                  /* clipboard stuff */                                  /* clipboard stuff */
# Line 2250  ui_select(int rdp_socket) Line 2590  ui_select(int rdp_socket)
2590          int n;          int n;
2591          fd_set rfds, wfds;          fd_set rfds, wfds;
2592          struct timeval tv;          struct timeval tv;
2593          BOOL s_timeout = False;          RD_BOOL s_timeout = False;
2594    
2595          while (True)          while (True)
2596          {          {
# Line 2294  ui_select(int rdp_socket) Line 2634  ui_select(int rdp_socket)
2634    
2635                                  /* Abort serial read calls */                                  /* Abort serial read calls */
2636                                  if (s_timeout)                                  if (s_timeout)
2637                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);                                          rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True);
2638                                  continue;                                  continue;
2639                  }                  }
2640    
# Line 2302  ui_select(int rdp_socket) Line 2642  ui_select(int rdp_socket)
2642                  rdpsnd_check_fds(&rfds, &wfds);                  rdpsnd_check_fds(&rfds, &wfds);
2643  #endif  #endif
2644    
2645                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);                  rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False);
2646    
2647                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2648                          return 1;                          return 1;
# Line 2316  ui_move_pointer(int x, int y) Line 2656  ui_move_pointer(int x, int y)
2656          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
2657  }  }
2658    
2659  HBITMAP  RD_HBITMAP
2660  ui_create_bitmap(int width, int height, uint8 * data)  ui_create_bitmap(int width, int height, uint8 * data)
2661  {  {
2662          XImage *image;          XImage *image;
# Line 2346  ui_create_bitmap(int width, int height, Line 2686  ui_create_bitmap(int width, int height,
2686          XFree(image);          XFree(image);
2687          if (tdata != data)          if (tdata != data)
2688                  xfree(tdata);                  xfree(tdata);
2689          return (HBITMAP) bitmap;          return (RD_HBITMAP) bitmap;
2690  }  }
2691    
2692  void  void
# Line 2394  ui_paint_bitmap(int x, int y, int cx, in Line 2734  ui_paint_bitmap(int x, int y, int cx, in
2734  }  }
2735    
2736  void  void
2737  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(RD_HBITMAP bmp)
2738  {  {
2739          XFreePixmap(g_display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2740  }  }
2741    
2742  HGLYPH  RD_HGLYPH
2743  ui_create_glyph(int width, int height, uint8 * data)  ui_create_glyph(int width, int height, uint8 * data)
2744  {  {
2745          XImage *image;          XImage *image;
# Line 2421  ui_create_glyph(int width, int height, u Line 2761  ui_create_glyph(int width, int height, u
2761          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
2762    
2763          XFree(image);          XFree(image);
2764          return (HGLYPH) bitmap;          return (RD_HGLYPH) bitmap;
2765  }  }
2766    
2767  void  void
2768  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(RD_HGLYPH glyph)
2769  {  {
2770          XFreePixmap(g_display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2771  }  }
2772    
2773  HCURSOR  RD_HCURSOR
2774  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
2775                   uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
2776  {  {
2777          HGLYPH maskglyph, cursorglyph;          RD_HGLYPH maskglyph, cursorglyph;
2778          XColor bg, fg;          XColor bg, fg;
2779          Cursor xcursor;          Cursor xcursor;
2780          uint8 *cursor, *pcursor;          uint8 *cursor, *pcursor;
# Line 2498  ui_create_cursor(unsigned int x, unsigne Line 2838  ui_create_cursor(unsigned int x, unsigne
2838          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2839          xfree(mask);          xfree(mask);
2840          xfree(cursor);          xfree(cursor);
2841          return (HCURSOR) xcursor;          return (RD_HCURSOR) xcursor;
2842  }  }
2843    
2844  void  void
2845  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(RD_HCURSOR cursor)
2846  {  {
2847          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2848          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
# Line 2510  ui_set_cursor(HCURSOR cursor) Line 2850  ui_set_cursor(HCURSOR cursor)
2850  }  }
2851    
2852  void  void
2853  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(RD_HCURSOR cursor)
2854  {  {
2855          XFreeCursor(g_display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2856  }  }
# Line 2528  ui_set_null_cursor(void) Line 2868  ui_set_null_cursor(void)
2868                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2869    
2870    
2871  HCOLOURMAP  RD_HCOLOURMAP
2872  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
2873  {  {
2874          COLOURENTRY *entry;          COLOURENTRY *entry;
# Line 2624  ui_create_colourmap(COLOURMAP * colours) Line 2964  ui_create_colourmap(COLOURMAP * colours)
2964                  XStoreColors(g_display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2965    
2966                  xfree(xcolours);                  xfree(xcolours);
2967                  return (HCOLOURMAP) map;                  return (RD_HCOLOURMAP) map;
2968          }          }
2969  }  }
2970    
2971  void  void
2972  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(RD_HCOLOURMAP map)
2973  {  {
2974          if (!g_owncolmap)          if (!g_owncolmap)
2975                  xfree(map);                  xfree(map);
# Line 2638  ui_destroy_colourmap(HCOLOURMAP map) Line 2978  ui_destroy_colourmap(HCOLOURMAP map)
2978  }  }
2979    
2980  void  void
2981  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(RD_HCOLOURMAP map)
2982  {  {
2983          if (!g_owncolmap)          if (!g_owncolmap)
2984          {          {
# Line 2726  ui_patblt(uint8 opcode, Line 3066  ui_patblt(uint8 opcode,
3066                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3067                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3068                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3069                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3070                          break;                          break;
3071    
3072                  case 3: /* Pattern */                  case 3: /* Pattern */
3073                          for (i = 0; i != 8; i++)                          if (brush->bd == 0)     /* rdp4 brush */
3074                                  ipattern[7 - i] = brush->pattern[i];                          {
3075                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                                  for (i = 0; i != 8; i++)
3076                          SET_FOREGROUND(bgcolour);                                          ipattern[7 - i] = brush->pattern[i];
3077                          SET_BACKGROUND(fgcolour);                                  fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
3078                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                                  SET_FOREGROUND(bgcolour);
3079                          XSetStipple(g_display, g_gc, fill);                                  SET_BACKGROUND(fgcolour);
3080                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                                  XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3081                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                                  XSetStipple(g_display, g_gc, fill);
3082                          XSetFillStyle(g_display, g_gc, FillSolid);                                  XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3083                          XSetTSOrigin(g_display, g_gc, 0, 0);                                  FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3084                          ui_destroy_glyph((HGLYPH) fill);                                  XSetFillStyle(g_display, g_gc, FillSolid);
3085                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3086                                    ui_destroy_glyph((RD_HGLYPH) fill);
3087                            }
3088                            else if (brush->bd->colour_code > 1)    /* > 1 bpp */
3089                            {
3090                                    fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
3091                                    XSetFillStyle(g_display, g_gc, FillTiled);
3092                                    XSetTile(g_display, g_gc, fill);
3093                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3094                                    FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3095                                    XSetFillStyle(g_display, g_gc, FillSolid);
3096                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3097                                    ui_destroy_bitmap((RD_HBITMAP) fill);
3098                            }
3099                            else
3100                            {
3101                                    fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
3102                                    SET_FOREGROUND(bgcolour);
3103                                    SET_BACKGROUND(fgcolour);
3104                                    XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3105                                    XSetStipple(g_display, g_gc, fill);
3106                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3107                                    FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3108                                    XSetFillStyle(g_display, g_gc, FillSolid);
3109                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3110                                    ui_destroy_glyph((RD_HGLYPH) fill);
3111                            }
3112                          break;                          break;
3113    
3114                  default:                  default:
# Line 2784  ui_screenblt(uint8 opcode, Line 3151  ui_screenblt(uint8 opcode,
3151  void  void
3152  ui_memblt(uint8 opcode,  ui_memblt(uint8 opcode,
3153            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
3154            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ RD_HBITMAP src, int srcx, int srcy)
3155  {  {
3156          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
3157          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
# Line 2799  ui_memblt(uint8 opcode, Line 3166  ui_memblt(uint8 opcode,
3166  void  void
3167  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
3168            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
3169            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ RD_HBITMAP src, int srcx, int srcy,
3170            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
3171  {  {
3172          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
# Line 2857  ui_rect( Line 3224  ui_rect(
3224  void  void
3225  ui_polygon(uint8 opcode,  ui_polygon(uint8 opcode,
3226             /* mode */ uint8 fillmode,             /* mode */ uint8 fillmode,
3227             /* dest */ POINT * point, int npoints,             /* dest */ RD_POINT * point, int npoints,
3228             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
3229  {  {
3230          uint8 style, i, ipattern[8];          uint8 style, i, ipattern[8];
# Line 2900  ui_polygon(uint8 opcode, Line 3267  ui_polygon(uint8 opcode,
3267                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
3268                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3269                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3270                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3271                          break;                          break;
3272    
3273                  case 3: /* Pattern */                  case 3: /* Pattern */
3274                          for (i = 0; i != 8; i++)                          if (brush->bd == 0)     /* rdp4 brush */
3275                                  ipattern[7 - i] = brush->pattern[i];                          {
3276                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                                  for (i = 0; i != 8; i++)
3277                          SET_FOREGROUND(bgcolour);                                          ipattern[7 - i] = brush->pattern[i];
3278                          SET_BACKGROUND(fgcolour);                                  fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
3279                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                                  SET_FOREGROUND(bgcolour);
3280                          XSetStipple(g_display, g_gc, fill);                                  SET_BACKGROUND(fgcolour);
3281                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                                  XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3282                          FILL_POLYGON((XPoint *) point, npoints);                                  XSetStipple(g_display, g_gc, fill);
3283                          XSetFillStyle(g_display, g_gc, FillSolid);                                  XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3284                          XSetTSOrigin(g_display, g_gc, 0, 0);                                  FILL_POLYGON((XPoint *) point, npoints);
3285                          ui_destroy_glyph((HGLYPH) fill);                                  XSetFillStyle(g_display, g_gc, FillSolid);
3286                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3287                                    ui_destroy_glyph((RD_HGLYPH) fill);
3288                            }
3289                            else if (brush->bd->colour_code > 1)    /* > 1 bpp */
3290                            {
3291                                    fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
3292                                    XSetFillStyle(g_display, g_gc, FillTiled);
3293                                    XSetTile(g_display, g_gc, fill);
3294                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3295                                    FILL_POLYGON((XPoint *) point, npoints);
3296                                    XSetFillStyle(g_display, g_gc, FillSolid);
3297                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3298                                    ui_destroy_bitmap((RD_HBITMAP) fill);
3299                            }
3300                            else
3301                            {
3302                                    fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
3303                                    SET_FOREGROUND(bgcolour);
3304                                    SET_BACKGROUND(fgcolour);
3305                                    XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3306                                    XSetStipple(g_display, g_gc, fill);
3307                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3308                                    FILL_POLYGON((XPoint *) point, npoints);
3309                                    XSetFillStyle(g_display, g_gc, FillSolid);
3310                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3311                                    ui_destroy_glyph((RD_HGLYPH) fill);
3312                            }
3313                          break;                          break;
3314    
3315                  default:                  default:
# Line 2927  ui_polygon(uint8 opcode, Line 3321  ui_polygon(uint8 opcode,
3321    
3322  void  void
3323  ui_polyline(uint8 opcode,  ui_polyline(uint8 opcode,
3324              /* dest */ POINT * points, int npoints,              /* dest */ RD_POINT * points, int npoints,
3325              /* pen */ PEN * pen)              /* pen */ PEN * pen)
3326  {  {
3327          /* TODO: set join style */          /* TODO: set join style */
# Line 2978  ui_ellipse(uint8 opcode, Line 3372  ui_ellipse(uint8 opcode,
3372                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3373                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3374                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3375                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3376                          break;                          break;
3377    
3378                  case 3: /* Pattern */                  case 3: /* Pattern */
3379                          for (i = 0; i != 8; i++)                          if (brush->bd == 0)     /* rdp4 brush */
3380                                  ipattern[7 - i] = brush->pattern[i];                          {
3381                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                                  for (i = 0; i != 8; i++)
3382                          SET_FOREGROUND(bgcolour);                                          ipattern[7 - i] = brush->pattern[i];
3383                          SET_BACKGROUND(fgcolour);                                  fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
3384                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                                  SET_FOREGROUND(bgcolour);
3385                          XSetStipple(g_display, g_gc, fill);                                  SET_BACKGROUND(fgcolour);
3386                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                                  XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3387                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                                  XSetStipple(g_display, g_gc, fill);
3388                          XSetFillStyle(g_display, g_gc, FillSolid);                                  XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3389                          XSetTSOrigin(g_display, g_gc, 0, 0);                                  DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3390                          ui_destroy_glyph((HGLYPH) fill);                                  XSetFillStyle(g_display, g_gc, FillSolid);
3391                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3392                                    ui_destroy_glyph((RD_HGLYPH) fill);
3393                            }
3394                            else if (brush->bd->colour_code > 1)    /* > 1 bpp */
3395                            {
3396                                    fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
3397                                    XSetFillStyle(g_display, g_gc, FillTiled);
3398                                    XSetTile(g_display, g_gc, fill);
3399                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3400                                    DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3401                                    XSetFillStyle(g_display, g_gc, FillSolid);
3402                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3403                                    ui_destroy_bitmap((RD_HBITMAP) fill);
3404                            }
3405                            else
3406                            {
3407                                    fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
3408                                    SET_FOREGROUND(bgcolour);
3409                                    SET_BACKGROUND(fgcolour);
3410                                    XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3411                                    XSetStipple(g_display, g_gc, fill);
3412                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3413                                    DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3414                                    XSetFillStyle(g_display, g_gc, FillSolid);
3415                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3416                                    ui_destroy_glyph((RD_HGLYPH) fill);
3417                            }
3418                          break;                          break;
3419    
3420                  default:                  default:
# Line 3007  ui_ellipse(uint8 opcode, Line 3428  ui_ellipse(uint8 opcode,
3428  void  void
3429  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
3430                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
3431                /* src */ HGLYPH glyph, int srcx, int srcy,                /* src */ RD_HGLYPH glyph, int srcx, int srcy,
3432                int bgcolour, int fgcolour)                int bgcolour, int fgcolour)
3433  {  {
3434          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
# Line 3192  ui_desktop_save(uint32 offset, int x, in Line 3613  ui_desktop_save(uint32 offset, int x, in
3613          if (g_ownbackstore)          if (g_ownbackstore)
3614          {          {
3615                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3616                    exit_if_null(image);
3617          }          }
3618          else          else
3619          {          {
3620                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3621                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
3622                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3623                    exit_if_null(image);
3624                  XFreePixmap(g_display, pix);                  XFreePixmap(g_display, pix);
3625          }          }
3626    
# Line 3219  ui_desktop_restore(uint32 offset, int x, Line 3642  ui_desktop_restore(uint32 offset, int x,
3642                  return;                  return;
3643    
3644          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3645                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3646    
3647          if (g_ownbackstore)          if (g_ownbackstore)
3648          {          {
# Line 3253  ui_end_update(void) Line 3676  ui_end_update(void)
3676    
3677    
3678  void  void
3679  ui_seamless_begin(BOOL hidden)  ui_seamless_begin(RD_BOOL hidden)
3680  {  {
3681          if (!g_seamless_rdp)          if (!g_seamless_rdp)
3682                  return;                  return;
# Line 3408  ui_seamless_create_window(unsigned long Line 3831  ui_seamless_create_window(unsigned long
3831                  ewmh_set_window_modal(wnd);                  ewmh_set_window_modal(wnd);
3832          }          }
3833    
3834            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
3835            {
3836                    /* Make window always-on-top */
3837                    ewmh_set_window_above(wnd);
3838            }
3839    
3840          /* FIXME: Support for Input Context:s */          /* FIXME: Support for Input Context:s */
3841    
3842          get_input_mask(&input_mask);          get_input_mask(&input_mask);
# Line 3415  ui_seamless_create_window(unsigned long Line 3844  ui_seamless_create_window(unsigned long
3844    
3845          XSelectInput(g_display, wnd, input_mask);          XSelectInput(g_display, wnd, input_mask);
3846    
3847          /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a          /* handle the WM_DELETE_WINDOW protocol. */
            seamless window, we could try to close the window on the  
            serverside, instead of terminating rdesktop */  
3848          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3849    
3850          sw = xmalloc(sizeof(seamless_window));          sw = xmalloc(sizeof(seamless_window));
3851    
3852            memset(sw, 0, sizeof(seamless_window));
3853    
3854          sw->wnd = wnd;          sw->wnd = wnd;
3855          sw->id = id;          sw->id = id;
         sw->behind = 0;  
3856          sw->group = sw_find_group(group, False);          sw->group = sw_find_group(group, False);
3857          sw->group->refcnt++;          sw->group->refcnt++;
         sw->xoffset = 0;  
         sw->yoffset = 0;  
         sw->width = 0;  
         sw->height = 0;  
3858          sw->state = SEAMLESSRDP_NOTYETMAPPED;          sw->state = SEAMLESSRDP_NOTYETMAPPED;
3859          sw->desktop = 0;          sw->desktop = 0;
3860          sw->position_timer = xmalloc(sizeof(struct timeval));          sw->position_timer = xmalloc(sizeof(struct timeval));
# Line 3497  ui_seamless_destroy_group(unsigned long Line 3922  ui_seamless_destroy_group(unsigned long
3922    
3923    
3924  void  void
3925    ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
3926                        const char *data, int chunk_len)
3927    {
3928            seamless_window *sw;
3929    
3930            if (!g_seamless_active)
3931                    return;
3932    
3933            sw = sw_get_window_by_id(id);
3934            if (!sw)
3935            {
3936                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3937                    return;
3938            }
3939    
3940            if (chunk == 0)
3941            {
3942                    if (sw->icon_size)
3943                            warning("ui_seamless_seticon: New icon started before previous completed\n");
3944    
3945                    if (strcmp(format, "RGBA") != 0)
3946                    {
3947                            warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3948                            return;
3949                    }
3950    
3951                    sw->icon_size = width * height * 4;
3952                    if (sw->icon_size > 32 * 32 * 4)
3953                    {
3954                            warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
3955                            sw->icon_size = 0;
3956                            return;
3957                    }
3958    
3959                    sw->icon_offset = 0;
3960            }
3961            else
3962            {
3963                    if (!sw->icon_size)
3964                            return;
3965            }
3966    
3967            if (chunk_len > (sw->icon_size - sw->icon_offset))
3968            {
3969                    warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
3970                            chunk_len, sw->icon_size - sw->icon_offset);
3971                    sw->icon_size = 0;
3972                    return;
3973            }
3974    
3975            memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
3976            sw->icon_offset += chunk_len;
3977    
3978            if (sw->icon_offset == sw->icon_size)
3979            {
3980                    ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
3981                    sw->icon_size = 0;
3982            }
3983    }
3984    
3985    
3986    void
3987    ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
3988    {
3989            seamless_window *sw;
3990    
3991            if (!g_seamless_active)
3992                    return;
3993    
3994            sw = sw_get_window_by_id(id);
3995            if (!sw)
3996            {
3997                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3998                    return;
3999            }
4000    
4001            if (strcmp(format, "RGBA") != 0)
4002            {
4003                    warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
4004                    return;
4005            }
4006    
4007            ewmh_del_icon(sw->wnd, width, height);
4008    }
4009    
4010    
4011    void
4012  ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)  ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
4013  {  {
4014          seamless_window *sw;          seamless_window *sw;
# Line 3542  void Line 4054  void
4054  ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)  ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
4055  {  {
4056          seamless_window *sw;          seamless_window *sw;
4057            XWindowChanges values;
4058            unsigned long restack_serial;
4059    
4060          if (!g_seamless_active)          if (!g_seamless_active)
4061                  return;                  return;
# Line 3556  ui_seamless_restack_window(unsigned long Line 4070  ui_seamless_restack_window(unsigned long
4070          if (behind)          if (behind)
4071          {          {
4072                  seamless_window *sw_behind;                  seamless_window *sw_behind;
                 Window wnds[2];  
4073    
4074                  sw_behind = sw_get_window_by_id(behind);                  sw_behind = sw_get_window_by_id(behind);
4075                  if (!sw_behind)                  if (!sw_behind)
4076                  {                  {
4077                          warning("ui_seamless_restack_window: No information for window 0x%lx\n",                          warning("ui_seamless_restack_window: No information for behind window 0x%lx\n", behind);
                                 behind);  
4078                          return;                          return;
4079                  }                  }
4080    
4081                  wnds[1] = sw_behind->wnd;                  if (!g_seamless_broken_restack)
4082                  wnds[0] = sw->wnd;                  {
4083                            values.stack_mode = Below;
4084                  XRestackWindows(g_display, wnds, 2);                          values.sibling = sw_behind->wnd;
4085                            restack_serial = XNextRequest(g_display);
4086                            XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display),
4087                                                 CWStackMode | CWSibling, &values);
4088                            sw_wait_configurenotify(sw->wnd, restack_serial);
4089                    }
4090          }          }
4091          else          else
4092          {          {
4093                  XRaiseWindow(g_display, sw->wnd);                  values.stack_mode = Above;
4094                    restack_serial = XNextRequest(g_display);
4095                    XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display), CWStackMode,
4096                                         &values);
4097                    sw_wait_configurenotify(sw->wnd, restack_serial);
4098          }          }
4099    
4100          sw_restack_window(sw, behind);          sw_restack_window(sw, behind);
4101    
4102            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
4103            {
4104                    /* Make window always-on-top */
4105                    ewmh_set_window_above(sw->wnd);
4106            }
4107  }  }
4108    
4109    

Legend:
Removed from v.1302  
changed lines
  Added in v.1488

  ViewVC Help
Powered by ViewVC 1.1.26