/[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 jpeg/rdesktop/trunk/xwin.c revision 1508 by dpavlin, Mon Jul 20 16:47:49 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    
33  /* We can't include Xproto.h because of conflicting defines for BOOL */  /* DJ globals begin */
34  #define X_ConfigureWindow              12  extern uint8 * g_bitmap_data;
35    extern uint8 * g_bitmap_data_last_write;
36    extern uint32 g_pixels_changed;
37    extern unsigned long long g_time_last_change;
38    /* DJ globals end */
39    
40  extern int g_width;  extern int g_width;
41  extern int g_height;  extern int g_height;
42  extern int g_xpos;  extern int g_xpos;
43  extern int g_ypos;  extern int g_ypos;
44  extern int g_pos;  extern int g_pos;
45  extern BOOL g_sendmotion;  extern RD_BOOL g_sendmotion;
46  extern BOOL g_fullscreen;  extern RD_BOOL g_fullscreen;
47  extern BOOL g_grab_keyboard;  extern RD_BOOL g_grab_keyboard;
48  extern BOOL g_hide_decorations;  extern RD_BOOL g_hide_decorations;
49  extern char g_title[];  extern char g_title[];
50  /* Color depth of the RDP session.  /* Color depth of the RDP session.
51     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 77  typedef struct _seamless_window
77          unsigned int desktop;          unsigned int desktop;
78          struct timeval *position_timer;          struct timeval *position_timer;
79    
80          BOOL outstanding_position;          RD_BOOL outstanding_position;
81          unsigned int outpos_serial;          unsigned int outpos_serial;
82          int outpos_xoffset, outpos_yoffset;          int outpos_xoffset, outpos_yoffset;
83          int outpos_width, outpos_height;          int outpos_width, outpos_height;
84    
85            unsigned int icon_size;
86            unsigned int icon_offset;
87            char icon_buffer[32 * 32 * 4];
88    
89          struct _seamless_window *next;          struct _seamless_window *next;
90  } seamless_window;  } seamless_window;
91  static seamless_window *g_seamless_windows = NULL;  static seamless_window *g_seamless_windows = NULL;
92  static unsigned long g_seamless_focused = 0;  static unsigned long g_seamless_focused = 0;
93  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 */
94  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 */
95  static BOOL g_seamless_hidden = False;  /* Desktop is hidden on server */  static RD_BOOL g_seamless_hidden = False;       /* Desktop is hidden on server */
96  extern BOOL g_seamless_rdp;  static RD_BOOL g_seamless_broken_restack = False;       /* WM does not properly restack */
97    extern RD_BOOL g_seamless_rdp;
98    
99  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
100  BOOL g_enable_compose = False;  RD_BOOL g_enable_compose = False;
101  BOOL g_Unobscured;              /* used for screenblt */  RD_BOOL g_Unobscured;           /* used for screenblt */
102  static GC g_gc = NULL;  static GC g_gc = NULL;
103  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
104  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
# Line 104  static int g_bpp; Line 115  static int g_bpp;
115  static XIM g_IM;  static XIM g_IM;
116  static XIC g_IC;  static XIC g_IC;
117  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
118    /* Maps logical (xmodmap -pp) pointing device buttons (0-based) back
119       to physical (1-based) indices. */
120    static unsigned char g_pointer_log_to_phys_map[32];
121  static Cursor g_current_cursor;  static Cursor g_current_cursor;
122  static HCURSOR g_null_cursor = NULL;  static RD_HCURSOR g_null_cursor = NULL;
123  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
124  extern Atom g_net_wm_state_atom;  extern Atom g_net_wm_state_atom;
125  extern Atom g_net_wm_desktop_atom;  extern Atom g_net_wm_desktop_atom;
126  static BOOL g_focused;  static RD_BOOL g_focused;
127  static BOOL g_mouse_in_wnd;  static RD_BOOL g_mouse_in_wnd;
128  /* Indicates that:  /* Indicates that:
129     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
130        as its RDP equivalent (implies X server is LE),        as its RDP equivalent (implies X server is LE),
131     2) host is LE     2) host is LE
132     This will trigger an optimization whose real value is questionable.     This will trigger an optimization whose real value is questionable.
133  */  */
134  static BOOL g_compatible_arch;  static RD_BOOL g_compatible_arch;
135  /* Indicates whether RDP's bitmaps and our XImages have the same  /* Indicates whether RDP's bitmaps and our XImages have the same
136     binary format. If so, we can avoid an expensive translation.     binary format. If so, we can avoid an expensive translation.
137     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 142  static BOOL g_compatible_arch;
142     ('host' is the machine running rdesktop; the host simply memcpy's     ('host' is the machine running rdesktop; the host simply memcpy's
143      so its endianess doesn't matter)      so its endianess doesn't matter)
144   */   */
145  static BOOL g_no_translate_image = False;  static RD_BOOL g_no_translate_image = False;
146    
147  /* endianness */  /* endianness */
148  static BOOL g_host_be;  static RD_BOOL g_host_be;
149  static BOOL g_xserver_be;  static RD_BOOL g_xserver_be;
150  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;
151  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;
152    
153  /* software backing store */  /* software backing store */
154  extern BOOL g_ownbackstore;  extern RD_BOOL g_ownbackstore;
155  static Pixmap g_backstore = 0;  static Pixmap g_backstore = 0;
156    
157  /* Moving in single app mode */  /* Moving in single app mode */
158  static BOOL g_moving_wnd;  static RD_BOOL g_moving_wnd;
159  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
160  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
161  static BOOL g_using_full_workarea = False;  static RD_BOOL g_using_full_workarea = False;
162    
163  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
164  extern int g_dsp_fd;  extern RD_BOOL g_rdpsnd;
 extern BOOL g_dsp_busy;  
 extern BOOL g_rdpsnd;  
165  #endif  #endif
166    
167  /* MWM decorations */  /* MWM decorations */
# Line 250  seamless_XDrawLines(Drawable d, XPoint * Line 262  seamless_XDrawLines(Drawable d, XPoint *
262  }  }
263    
264  /* colour maps */  /* colour maps */
265  extern BOOL g_owncolmap;  extern RD_BOOL g_owncolmap;
266  static Colormap g_xcolmap;  static Colormap g_xcolmap;
267  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
268    
# Line 474  sw_handle_restack(seamless_window * sw) Line 486  sw_handle_restack(seamless_window * sw)
486    
487    
488  static seamless_group *  static seamless_group *
489  sw_find_group(unsigned long id, BOOL dont_create)  sw_find_group(unsigned long id, RD_BOOL dont_create)
490  {  {
491          seamless_window *sw;          seamless_window *sw;
492          seamless_group *sg;          seamless_group *sg;
# Line 525  mwm_hide_decorations(Window wnd) Line 537  mwm_hide_decorations(Window wnd)
537    
538  }  }
539    
540    typedef struct _sw_configurenotify_context
541    {
542            Window window;
543            unsigned long serial;
544    } sw_configurenotify_context;
545    
546    /* Predicate procedure for sw_wait_configurenotify */
547    static Bool
548    sw_configurenotify_p(Display * display, XEvent * xevent, XPointer arg)
549    {
550            sw_configurenotify_context *context = (sw_configurenotify_context *) arg;
551            if (xevent->xany.type == ConfigureNotify
552                && xevent->xconfigure.window == context->window
553                && xevent->xany.serial >= context->serial)
554                    return True;
555    
556            return False;
557    }
558    
559    /* Wait for a ConfigureNotify, with a equal or larger serial, on the
560       specified window. The event will be removed from the queue. We
561       could use XMaskEvent(StructureNotifyMask), but we would then risk
562       throwing away crucial events like DestroyNotify.
563    
564       After a ConfigureWindow, according to ICCCM section 4.1.5, we
565       should recieve a ConfigureNotify, either a real or synthetic
566       one. This indicates that the configure has been "completed".
567       However, some WMs such as several versions of Metacity fails to
568       send synthetic events. See bug
569       http://bugzilla.gnome.org/show_bug.cgi?id=322840. We need to use a
570       timeout to avoid a hang. Tk uses the same approach. */
571    static void
572    sw_wait_configurenotify(Window wnd, unsigned long serial)
573    {
574            XEvent xevent;
575            sw_configurenotify_context context;
576            struct timeval now;
577            struct timeval nextsecond;
578            RD_BOOL got = False;
579    
580            context.window = wnd;
581            context.serial = serial;
582    
583            gettimeofday(&nextsecond, NULL);
584            nextsecond.tv_sec += 1;
585    
586            do
587            {
588                    if (XCheckIfEvent(g_display, &xevent, sw_configurenotify_p, (XPointer) & context))
589                    {
590                            got = True;
591                            break;
592                    }
593                    usleep(100000);
594                    gettimeofday(&now, NULL);
595            }
596            while (timercmp(&now, &nextsecond, <));
597    
598            if (!got)
599            {
600                    warning("Broken Window Manager: Timeout while waiting for ConfigureNotify\n");
601            }
602    }
603    
604    /* Get the toplevel window, in case of reparenting */
605    static Window
606    sw_get_toplevel(Window wnd)
607    {
608            Window root, parent;
609            Window *child_list;
610            unsigned int num_children;
611    
612            while (1)
613            {
614                    XQueryTree(g_display, wnd, &root, &parent, &child_list, &num_children);
615                    if (root == parent)
616                    {
617                            break;
618                    }
619                    else if (!parent)
620                    {
621                            warning("Internal error: sw_get_toplevel called with root window\n");
622                    }
623    
624                    wnd = parent;
625            }
626    
627            return wnd;
628    }
629    
630    
631    /* Check if wnd is already behind a window wrt stacking order */
632    static RD_BOOL
633    sw_window_is_behind(Window wnd, Window behind)
634    {
635            Window dummy1, dummy2;
636            Window *child_list;
637            unsigned int num_children;
638            unsigned int i;
639            RD_BOOL found_behind = False;
640            RD_BOOL found_wnd = False;
641    
642            wnd = sw_get_toplevel(wnd);
643            behind = sw_get_toplevel(behind);
644    
645            XQueryTree(g_display, RootWindowOfScreen(g_screen), &dummy1, &dummy2, &child_list,
646                       &num_children);
647    
648            for (i = num_children - 1; i >= 0; i--)
649            {
650                    if (child_list[i] == behind)
651                    {
652                            found_behind = True;
653                    }
654                    else if (child_list[i] == wnd)
655                    {
656                            found_wnd = True;
657                            break;
658                    }
659            }
660    
661            if (child_list)
662                    XFree(child_list);
663    
664            if (!found_wnd)
665            {
666                    warning("sw_window_is_behind: Unable to find window 0x%lx\n", wnd);
667    
668                    if (!found_behind)
669                    {
670                            warning("sw_window_is_behind: Unable to find behind window 0x%lx\n",
671                                    behind);
672                    }
673            }
674    
675            return found_behind;
676    }
677    
678    
679    /* Test if the window manager correctly handles window restacking. In
680       particular, we are testing if it's possible to place a window
681       between two other windows. Many WMs such as Metacity can only stack
682       windows on the top or bottom. The window creation should mostly
683       match ui_seamless_create_window. */
684    static void
685    seamless_restack_test()
686    {
687            /* The goal is to have the middle window between top and
688               bottom.  The middle window is initially at the top,
689               though. */
690            Window wnds[3];         /* top, middle and bottom */
691            int i;
692            XEvent xevent;
693            XWindowChanges values;
694            unsigned long restack_serial;
695    
696            for (i = 0; i < 3; i++)
697            {
698                    char name[64];
699                    wnds[i] =
700                            XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, 20, 20,
701                                                0, 0, 0);
702                    snprintf(name, sizeof(name), "SeamlessRDP restack test - window %d", i);
703                    XStoreName(g_display, wnds[i], name);
704                    ewmh_set_wm_name(wnds[i], name);
705    
706                    /* Hide decorations. Often this means that no
707                       reparenting will be done, which makes the restack
708                       easier. Besides, we want to mimic our other
709                       seamless windows as much as possible. We must still
710                       handle the case with reparenting, though. */
711                    mwm_hide_decorations(wnds[i]);
712    
713                    /* Prevent windows from appearing in task bar */
714                    XSetTransientForHint(g_display, wnds[i], RootWindowOfScreen(g_screen));
715                    ewmh_set_window_popup(wnds[i]);
716    
717                    /* We need to catch MapNotify/ConfigureNotify */
718                    XSelectInput(g_display, wnds[i], StructureNotifyMask);
719            }
720    
721            /* Map Windows. Currently, we assume that XMapRaised places
722               the window on the top of the stack. Should be fairly safe;
723               the window is configured before it's mapped. */
724            XMapRaised(g_display, wnds[2]); /* bottom */
725            do
726            {
727                    XWindowEvent(g_display, wnds[2], StructureNotifyMask, &xevent);
728            }
729            while (xevent.type != MapNotify);
730            XMapRaised(g_display, wnds[0]); /* top */
731            do
732            {
733                    XWindowEvent(g_display, wnds[0], StructureNotifyMask, &xevent);
734            }
735            while (xevent.type != MapNotify);
736            XMapRaised(g_display, wnds[1]); /* middle */
737            do
738            {
739                    XWindowEvent(g_display, wnds[1], StructureNotifyMask, &xevent);
740            }
741            while (xevent.type != MapNotify);
742    
743            /* The stacking order should now be 1 - 0 - 2 */
744            if (!sw_window_is_behind(wnds[0], wnds[1]) || !sw_window_is_behind(wnds[2], wnds[1]))
745            {
746                    /* Ok, technically a WM is allowed to stack windows arbitrarily, but... */
747                    warning("Broken Window Manager: Unable to test window restacking\n");
748                    g_seamless_broken_restack = True;
749                    for (i = 0; i < 3; i++)
750                            XDestroyWindow(g_display, wnds[i]);
751                    return;
752            }
753    
754            /* Restack, using XReconfigureWMWindow, which should correctly
755               handle reparented windows as well as nonreparenting WMs. */
756            values.stack_mode = Below;
757            values.sibling = wnds[0];
758            restack_serial = XNextRequest(g_display);
759            XReconfigureWMWindow(g_display, wnds[1], DefaultScreen(g_display), CWStackMode | CWSibling,
760                                 &values);
761            sw_wait_configurenotify(wnds[1], restack_serial);
762    
763            /* Now verify that middle is behind top but not behind
764               bottom */
765            if (!sw_window_is_behind(wnds[1], wnds[0]))
766            {
767                    warning("Broken Window Manager: doesn't handle restack (restack request was ignored)\n");
768                    g_seamless_broken_restack = True;
769            }
770            else if (sw_window_is_behind(wnds[1], wnds[2]))
771            {
772                    warning("Broken Window Manager: doesn't handle restack (window was moved to bottom)\n");
773                    g_seamless_broken_restack = True;
774            }
775    
776            /* Destroy windows */
777            for (i = 0; i < 3; i++)
778                    XDestroyWindow(g_display, wnds[i]);
779    }
780    
781  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
782  { \  { \
783          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
# Line 579  translate_colour(uint32 colour) Line 832  translate_colour(uint32 colour)
832                          SPLITCOLOUR16(colour, pc);                          SPLITCOLOUR16(colour, pc);
833                          break;                          break;
834                  case 24:                  case 24:
835                    case 32:
836                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
837                          break;                          break;
838                  default:                  default:
# Line 1187  translate_image(int width, int height, u Line 1441  translate_image(int width, int height, u
1441             is only set for compatible depths, but the RDP depth might've             is only set for compatible depths, but the RDP depth might've
1442             changed during connection negotiations.             changed during connection negotiations.
1443           */           */
1444    
1445            /* todo */
1446            if (g_server_depth == 32 && g_depth == 24)
1447            {
1448                    return data;
1449            }
1450    
1451          if (g_no_translate_image)          if (g_no_translate_image)
1452          {          {
1453                  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 1525  translate_image(int width, int height, u
1525          return out;          return out;
1526  }  }
1527    
1528  BOOL  static void
1529    xwin_refresh_pointer_map(void)
1530    {
1531            unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)];
1532            int i, pointer_buttons;
1533    
1534            pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map));
1535            if (pointer_buttons > sizeof(phys_to_log_map))
1536                    pointer_buttons = sizeof(phys_to_log_map);
1537    
1538            /* if multiple physical buttons map to the same logical button, then
1539             * use the lower numbered physical one */
1540            for (i = pointer_buttons - 1; i >= 0; i--)
1541            {
1542                    /* a user could specify arbitrary values for the logical button
1543                     * number, ignore any that are abnormally large */
1544                    if (phys_to_log_map[i] > sizeof(g_pointer_log_to_phys_map))
1545                            continue;
1546                    g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
1547            }
1548    }
1549    
1550    RD_BOOL
1551  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1552  {  {
1553          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
# Line 1312  calculate_mask_weight(uint32 mask) Line 1595  calculate_mask_weight(uint32 mask)
1595          return weight;          return weight;
1596  }  }
1597    
1598  static BOOL  static RD_BOOL
1599  select_visual(int screen_num)  select_visual(int screen_num)
1600  {  {
1601          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
# Line 1351  select_visual(int screen_num) Line 1634  select_visual(int screen_num)
1634                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
1635                  {                  {
1636                          XVisualInfo *visual_info = &vmatches[i];                          XVisualInfo *visual_info = &vmatches[i];
1637                          BOOL can_translate_to_bpp = False;                          RD_BOOL can_translate_to_bpp = False;
1638                          int j;                          int j;
1639    
1640                          /* 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 1791  select_visual(int screen_num)
1791  }  }
1792    
1793  static XErrorHandler g_old_error_handler;  static XErrorHandler g_old_error_handler;
1794    static RD_BOOL g_error_expected = False;
1795    
1796    /* Check if the X11 window corresponding to a seamless window with
1797       specified id exists. */
1798    RD_BOOL
1799    sw_window_exists(unsigned long id)
1800    {
1801            seamless_window *sw;
1802            char *name;
1803            Status sts = 0;
1804    
1805            sw = sw_get_window_by_id(id);
1806            if (!sw)
1807                    return False;
1808    
1809            g_error_expected = True;
1810            sts = XFetchName(g_display, sw->wnd, &name);
1811            g_error_expected = False;
1812            if (sts)
1813            {
1814                    XFree(name);
1815            }
1816    
1817            return sts;
1818    }
1819    
1820  static int  static int
1821  error_handler(Display * dpy, XErrorEvent * eev)  error_handler(Display * dpy, XErrorEvent * eev)
1822  {  {
1823          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");  
1824                  return 0;                  return 0;
         }  
1825    
1826          return g_old_error_handler(dpy, eev);          return g_old_error_handler(dpy, eev);
1827  }  }
1828    
1829  BOOL  RD_BOOL
1830  ui_init(void)  ui_init(void)
1831  {  {
1832          int screen_num;          int screen_num;
# Line 1537  ui_init(void) Line 1840  ui_init(void)
1840    
1841          {          {
1842                  uint16 endianess_test = 1;                  uint16 endianess_test = 1;
1843                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test));
1844          }          }
1845    
1846          g_old_error_handler = XSetErrorHandler(error_handler);          g_old_error_handler = XSetErrorHandler(error_handler);
# Line 1618  ui_init(void) Line 1921  ui_init(void)
1921          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1922    
1923          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1924            xwin_refresh_pointer_map();
1925    
1926          xkeymap_init();          xkeymap_init();
1927    
# Line 1627  ui_init(void) Line 1931  ui_init(void)
1931          xclip_init();          xclip_init();
1932          ewmh_init();          ewmh_init();
1933          if (g_seamless_rdp)          if (g_seamless_rdp)
1934            {
1935                  seamless_init();                  seamless_init();
1936            }
1937    
1938          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));
1939    
# Line 1689  get_input_mask(long *input_mask) Line 1995  get_input_mask(long *input_mask)
1995                  *input_mask |= LeaveWindowMask;                  *input_mask |= LeaveWindowMask;
1996  }  }
1997    
1998  BOOL  RD_BOOL
1999  ui_create_window(void)  ui_create_window(void)
2000  {  {
2001          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
# Line 1737  ui_create_window(void) Line 2043  ui_create_window(void)
2043          }          }
2044    
2045          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
2046            ewmh_set_wm_name(g_wnd, g_title);
2047    
2048          if (g_hide_decorations)          if (g_hide_decorations)
2049                  mwm_hide_decorations(g_wnd);                  mwm_hide_decorations(g_wnd);
# Line 1801  ui_create_window(void) Line 2108  ui_create_window(void)
2108          if (g_null_cursor == NULL)          if (g_null_cursor == NULL)
2109                  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);
2110    
2111            if (g_seamless_rdp)
2112            {
2113                    seamless_restack_test();
2114            }
2115    
2116          return True;          return True;
2117  }  }
2118    
# Line 1876  xwin_toggle_fullscreen(void) Line 2188  xwin_toggle_fullscreen(void)
2188  }  }
2189    
2190  static void  static void
2191  handle_button_event(XEvent xevent, BOOL down)  handle_button_event(XEvent xevent, RD_BOOL down)
2192  {  {
2193          uint16 button, flags = 0;          uint16 button, flags = 0;
2194          g_last_gesturetime = xevent.xbutton.time;          g_last_gesturetime = xevent.xbutton.time;
2195            /* Reverse the pointer button mapping, e.g. in the case of
2196               "left-handed mouse mode"; the RDP session expects to
2197               receive physical buttons (true in mstsc as well) and
2198               logical button behavior depends on the remote desktop's own
2199               mouse settings */
2200            xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
2201          button = xkeymap_translate_button(xevent.xbutton.button);          button = xkeymap_translate_button(xevent.xbutton.button);
2202          if (button == 0)          if (button == 0)
2203                  return;                  return;
# Line 1992  xwin_process_events(void) Line 2310  xwin_process_events(void)
2310                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
2311                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
2312                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
2313                                          /* Quit */                                  {
2314                                          return 0;                                          /* When killing a seamless window, close the window on the
2315                                               serverside instead of terminating rdesktop */
2316                                            sw = sw_get_window_by_wnd(xevent.xclient.window);
2317                                            if (!sw)
2318                                                    /* Otherwise, quit */
2319                                                    return 0;
2320                                            /* send seamless destroy process message */
2321                                            seamless_send_destroy(sw->id);
2322                                    }
2323                                  break;                                  break;
2324    
2325                          case KeyPress:                          case KeyPress:
# Line 2094  xwin_process_events(void) Line 2420  xwin_process_events(void)
2420                                  if (!sw)                                  if (!sw)
2421                                          break;                                          break;
2422    
2423                                    /* Menu windows are real X11 windows,
2424                                       with focus. When such a window is
2425                                       destroyed, focus is reverted to the
2426                                       main application window, which
2427                                       would cause us to send FOCUS. This
2428                                       breaks window switching in, say,
2429                                       Seamonkey. We shouldn't need to
2430                                       send FOCUS: Windows should also
2431                                       revert focus to some other window
2432                                       when the menu window is
2433                                       destroyed. So, we only send FOCUS
2434                                       if the previous focus window still
2435                                       exists. */
2436                                  if (sw->id != g_seamless_focused)                                  if (sw->id != g_seamless_focused)
2437                                  {                                  {
2438                                          seamless_send_focus(sw->id, 0);  
2439                                            if (sw_window_exists(g_seamless_focused))
2440                                                    seamless_send_focus(sw->id, 0);
2441                                          g_seamless_focused = sw->id;                                          g_seamless_focused = sw->id;
2442                                  }                                  }
2443                                  break;                                  break;
# Line 2167  xwin_process_events(void) Line 2508  xwin_process_events(void)
2508                                          XFreeModifiermap(g_mod_map);                                          XFreeModifiermap(g_mod_map);
2509                                          g_mod_map = XGetModifierMapping(g_display);                                          g_mod_map = XGetModifierMapping(g_display);
2510                                  }                                  }
2511    
2512                                    if (xevent.xmapping.request == MappingPointer)
2513                                    {
2514                                            xwin_refresh_pointer_map();
2515                                    }
2516    
2517                                  break;                                  break;
2518    
2519                                  /* clipboard stuff */                                  /* clipboard stuff */
# Line 2250  ui_select(int rdp_socket) Line 2597  ui_select(int rdp_socket)
2597          int n;          int n;
2598          fd_set rfds, wfds;          fd_set rfds, wfds;
2599          struct timeval tv;          struct timeval tv;
2600          BOOL s_timeout = False;          RD_BOOL s_timeout = False;
2601    
2602          while (True)          while (True)
2603          {          {
# Line 2294  ui_select(int rdp_socket) Line 2641  ui_select(int rdp_socket)
2641    
2642                                  /* Abort serial read calls */                                  /* Abort serial read calls */
2643                                  if (s_timeout)                                  if (s_timeout)
2644                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);                                          rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True);
2645                                  continue;                                  continue;
2646                  }                  }
2647    
# Line 2302  ui_select(int rdp_socket) Line 2649  ui_select(int rdp_socket)
2649                  rdpsnd_check_fds(&rfds, &wfds);                  rdpsnd_check_fds(&rfds, &wfds);
2650  #endif  #endif
2651    
2652                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);                  rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False);
2653    
2654                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2655                          return 1;                          return 1;
# Line 2316  ui_move_pointer(int x, int y) Line 2663  ui_move_pointer(int x, int y)
2663          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);
2664  }  }
2665    
2666  HBITMAP  RD_HBITMAP
2667  ui_create_bitmap(int width, int height, uint8 * data)  ui_create_bitmap(int width, int height, uint8 * data)
2668  {  {
2669          XImage *image;          XImage *image;
# Line 2346  ui_create_bitmap(int width, int height, Line 2693  ui_create_bitmap(int width, int height,
2693          XFree(image);          XFree(image);
2694          if (tdata != data)          if (tdata != data)
2695                  xfree(tdata);                  xfree(tdata);
2696          return (HBITMAP) bitmap;          return (RD_HBITMAP) bitmap;
2697    }
2698    
2699    void
2700    update_bitmap(int x, int y, int width, int height, uint8 * data)
2701    {
2702            int size;
2703            uint8 *out;
2704            uint8 *end;
2705            uint8 *c_current;
2706            uint8 *c_update;
2707            uint8 *c_written;
2708            int col;
2709            int row;
2710            BOOL matches_written;
2711            BOOL matches_current;
2712    
2713            size = width * height * 3;   /* force 24-bit color for libjpeg: R G B */
2714            out = (uint8 *) xmalloc(size);
2715            end = out + size;
2716    
2717            switch (g_server_depth)
2718            {
2719                    case 24:
2720                            translate24to24(data, out, end);
2721                            break;
2722                    case 16:
2723                            translate16to24((uint16 *) data, out, end);
2724                            break;
2725                    case 15:
2726                            translate15to24((uint16 *) data, out, end);
2727                            break;
2728                    case 8:
2729                            translate8to24(data, out, end);
2730                            break;
2731            }
2732    
2733            for (row=0; row<height; row++)
2734            {
2735                    /* truncate if out of bounds */
2736                    if (g_height <= (y + row))
2737                            break;
2738    
2739                    c_update = out + row * width * 3;
2740                    c_current = g_bitmap_data + (row + y) * g_width * 3 + x * 3;
2741                    c_written = g_bitmap_data_last_write + (row + y) * g_width * 3 + x * 3;
2742    
2743                    for (col = 0; col < width; col++)
2744                    {
2745                            /* truncate if out of bounds */
2746                            if (g_width <= (x + col))
2747                                    break;
2748    
2749                            matches_written = True;
2750                            matches_current = True;
2751    
2752                            /* updates come in as BGR order... force RGB */
2753                            if (*c_current != *(c_update+2))
2754                            {
2755                                    if (*(c_update+2) != *c_written)
2756                                            matches_written = False;
2757                                    matches_current = False;
2758                                    *c_current = *(c_update+2);
2759                            }
2760    
2761                            c_written++;
2762    
2763                            if (*(++c_current) != *(++c_update))
2764                            {
2765                                    if (*c_update != *c_written)
2766                                            matches_written = False;
2767                                    matches_current = False;
2768                                    *c_current = *c_update;
2769                            }
2770    
2771                            c_written++;
2772    
2773                            if (*(++c_current) != *(++c_update-2))
2774                            {
2775                                    if (*(c_update-2) != *c_written)
2776                                            matches_written = False;
2777                                    matches_current = False;
2778                                    *c_current = *(c_update-2);
2779                            }
2780    
2781                            c_written++;
2782                            c_current++;
2783                            c_update++;
2784    
2785                            if (!matches_current)
2786                            {
2787                                    if (matches_written)
2788                                            g_pixels_changed--;
2789                                    else
2790                                            g_pixels_changed++;
2791                            }
2792                    }
2793            }
2794    
2795            //printf("g_pixels_changed=%d\n", g_pixels_changed);
2796    
2797            xfree(out);
2798            g_time_last_change = tod();
2799  }  }
2800    
2801  void  void
# Line 2356  ui_paint_bitmap(int x, int y, int cx, in Line 2805  ui_paint_bitmap(int x, int y, int cx, in
2805          uint8 *tdata;          uint8 *tdata;
2806          int bitmap_pad;          int bitmap_pad;
2807    
2808            update_bitmap(x, y, width, height, data);
2809    
2810          if (g_server_depth == 8)          if (g_server_depth == 8)
2811          {          {
2812                  bitmap_pad = 8;                  bitmap_pad = 8;
# Line 2394  ui_paint_bitmap(int x, int y, int cx, in Line 2845  ui_paint_bitmap(int x, int y, int cx, in
2845  }  }
2846    
2847  void  void
2848  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(RD_HBITMAP bmp)
2849  {  {
2850          XFreePixmap(g_display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2851  }  }
2852    
2853  HGLYPH  RD_HGLYPH
2854  ui_create_glyph(int width, int height, uint8 * data)  ui_create_glyph(int width, int height, uint8 * data)
2855  {  {
2856          XImage *image;          XImage *image;
# Line 2421  ui_create_glyph(int width, int height, u Line 2872  ui_create_glyph(int width, int height, u
2872          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);
2873    
2874          XFree(image);          XFree(image);
2875          return (HGLYPH) bitmap;          return (RD_HGLYPH) bitmap;
2876  }  }
2877    
2878  void  void
2879  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(RD_HGLYPH glyph)
2880  {  {
2881          XFreePixmap(g_display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2882  }  }
2883    
2884  HCURSOR  RD_HCURSOR
2885  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,
2886                   uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
2887  {  {
2888          HGLYPH maskglyph, cursorglyph;          RD_HGLYPH maskglyph, cursorglyph;
2889          XColor bg, fg;          XColor bg, fg;
2890          Cursor xcursor;          Cursor xcursor;
2891          uint8 *cursor, *pcursor;          uint8 *cursor, *pcursor;
# Line 2498  ui_create_cursor(unsigned int x, unsigne Line 2949  ui_create_cursor(unsigned int x, unsigne
2949          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2950          xfree(mask);          xfree(mask);
2951          xfree(cursor);          xfree(cursor);
2952          return (HCURSOR) xcursor;          return (RD_HCURSOR) xcursor;
2953  }  }
2954    
2955  void  void
2956  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(RD_HCURSOR cursor)
2957  {  {
2958          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2959          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
# Line 2510  ui_set_cursor(HCURSOR cursor) Line 2961  ui_set_cursor(HCURSOR cursor)
2961  }  }
2962    
2963  void  void
2964  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(RD_HCURSOR cursor)
2965  {  {
2966          XFreeCursor(g_display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2967  }  }
# Line 2528  ui_set_null_cursor(void) Line 2979  ui_set_null_cursor(void)
2979                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2980    
2981    
2982  HCOLOURMAP  RD_HCOLOURMAP
2983  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
2984  {  {
2985          COLOURENTRY *entry;          COLOURENTRY *entry;
# Line 2624  ui_create_colourmap(COLOURMAP * colours) Line 3075  ui_create_colourmap(COLOURMAP * colours)
3075                  XStoreColors(g_display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
3076    
3077                  xfree(xcolours);                  xfree(xcolours);
3078                  return (HCOLOURMAP) map;                  return (RD_HCOLOURMAP) map;
3079          }          }
3080  }  }
3081    
3082  void  void
3083  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(RD_HCOLOURMAP map)
3084  {  {
3085          if (!g_owncolmap)          if (!g_owncolmap)
3086                  xfree(map);                  xfree(map);
# Line 2638  ui_destroy_colourmap(HCOLOURMAP map) Line 3089  ui_destroy_colourmap(HCOLOURMAP map)
3089  }  }
3090    
3091  void  void
3092  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(RD_HCOLOURMAP map)
3093  {  {
3094          if (!g_owncolmap)          if (!g_owncolmap)
3095          {          {
# Line 2726  ui_patblt(uint8 opcode, Line 3177  ui_patblt(uint8 opcode,
3177                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3178                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3179                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3180                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3181                          break;                          break;
3182    
3183                  case 3: /* Pattern */                  case 3: /* Pattern */
3184                          for (i = 0; i != 8; i++)                          if (brush->bd == 0)     /* rdp4 brush */
3185                                  ipattern[7 - i] = brush->pattern[i];                          {
3186                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                                  for (i = 0; i != 8; i++)
3187                          SET_FOREGROUND(bgcolour);                                          ipattern[7 - i] = brush->pattern[i];
3188                          SET_BACKGROUND(fgcolour);                                  fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
3189                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                                  SET_FOREGROUND(bgcolour);
3190                          XSetStipple(g_display, g_gc, fill);                                  SET_BACKGROUND(fgcolour);
3191                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                                  XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3192                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                                  XSetStipple(g_display, g_gc, fill);
3193                          XSetFillStyle(g_display, g_gc, FillSolid);                                  XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3194                          XSetTSOrigin(g_display, g_gc, 0, 0);                                  FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3195                          ui_destroy_glyph((HGLYPH) fill);                                  XSetFillStyle(g_display, g_gc, FillSolid);
3196                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3197                                    ui_destroy_glyph((RD_HGLYPH) fill);
3198                            }
3199                            else if (brush->bd->colour_code > 1)    /* > 1 bpp */
3200                            {
3201                                    fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
3202                                    XSetFillStyle(g_display, g_gc, FillTiled);
3203                                    XSetTile(g_display, g_gc, fill);
3204                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3205                                    FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3206                                    XSetFillStyle(g_display, g_gc, FillSolid);
3207                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3208                                    ui_destroy_bitmap((RD_HBITMAP) fill);
3209                            }
3210                            else
3211                            {
3212                                    fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
3213                                    SET_FOREGROUND(bgcolour);
3214                                    SET_BACKGROUND(fgcolour);
3215                                    XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3216                                    XSetStipple(g_display, g_gc, fill);
3217                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3218                                    FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3219                                    XSetFillStyle(g_display, g_gc, FillSolid);
3220                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3221                                    ui_destroy_glyph((RD_HGLYPH) fill);
3222                            }
3223                          break;                          break;
3224    
3225                  default:                  default:
# Line 2784  ui_screenblt(uint8 opcode, Line 3262  ui_screenblt(uint8 opcode,
3262  void  void
3263  ui_memblt(uint8 opcode,  ui_memblt(uint8 opcode,
3264            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
3265            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ RD_HBITMAP src, int srcx, int srcy)
3266  {  {
3267          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
3268          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 3277  ui_memblt(uint8 opcode,
3277  void  void
3278  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
3279            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
3280            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ RD_HBITMAP src, int srcx, int srcy,
3281            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
3282  {  {
3283          /* 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 3335  ui_rect(
3335  void  void
3336  ui_polygon(uint8 opcode,  ui_polygon(uint8 opcode,
3337             /* mode */ uint8 fillmode,             /* mode */ uint8 fillmode,
3338             /* dest */ POINT * point, int npoints,             /* dest */ RD_POINT * point, int npoints,
3339             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
3340  {  {
3341          uint8 style, i, ipattern[8];          uint8 style, i, ipattern[8];
# Line 2900  ui_polygon(uint8 opcode, Line 3378  ui_polygon(uint8 opcode,
3378                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
3379                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3380                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3381                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3382                          break;                          break;
3383    
3384                  case 3: /* Pattern */                  case 3: /* Pattern */
3385                          for (i = 0; i != 8; i++)                          if (brush->bd == 0)     /* rdp4 brush */
3386                                  ipattern[7 - i] = brush->pattern[i];                          {
3387                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                                  for (i = 0; i != 8; i++)
3388                          SET_FOREGROUND(bgcolour);                                          ipattern[7 - i] = brush->pattern[i];
3389                          SET_BACKGROUND(fgcolour);                                  fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
3390                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                                  SET_FOREGROUND(bgcolour);
3391                          XSetStipple(g_display, g_gc, fill);                                  SET_BACKGROUND(fgcolour);
3392                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                                  XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3393                          FILL_POLYGON((XPoint *) point, npoints);                                  XSetStipple(g_display, g_gc, fill);
3394                          XSetFillStyle(g_display, g_gc, FillSolid);                                  XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3395                          XSetTSOrigin(g_display, g_gc, 0, 0);                                  FILL_POLYGON((XPoint *) point, npoints);
3396                          ui_destroy_glyph((HGLYPH) fill);                                  XSetFillStyle(g_display, g_gc, FillSolid);
3397                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3398                                    ui_destroy_glyph((RD_HGLYPH) fill);
3399                            }
3400                            else if (brush->bd->colour_code > 1)    /* > 1 bpp */
3401                            {
3402                                    fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
3403                                    XSetFillStyle(g_display, g_gc, FillTiled);
3404                                    XSetTile(g_display, g_gc, fill);
3405                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3406                                    FILL_POLYGON((XPoint *) point, npoints);
3407                                    XSetFillStyle(g_display, g_gc, FillSolid);
3408                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3409                                    ui_destroy_bitmap((RD_HBITMAP) fill);
3410                            }
3411                            else
3412                            {
3413                                    fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
3414                                    SET_FOREGROUND(bgcolour);
3415                                    SET_BACKGROUND(fgcolour);
3416                                    XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3417                                    XSetStipple(g_display, g_gc, fill);
3418                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3419                                    FILL_POLYGON((XPoint *) point, npoints);
3420                                    XSetFillStyle(g_display, g_gc, FillSolid);
3421                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3422                                    ui_destroy_glyph((RD_HGLYPH) fill);
3423                            }
3424                          break;                          break;
3425    
3426                  default:                  default:
# Line 2927  ui_polygon(uint8 opcode, Line 3432  ui_polygon(uint8 opcode,
3432    
3433  void  void
3434  ui_polyline(uint8 opcode,  ui_polyline(uint8 opcode,
3435              /* dest */ POINT * points, int npoints,              /* dest */ RD_POINT * points, int npoints,
3436              /* pen */ PEN * pen)              /* pen */ PEN * pen)
3437  {  {
3438          /* TODO: set join style */          /* TODO: set join style */
# Line 2978  ui_ellipse(uint8 opcode, Line 3483  ui_ellipse(uint8 opcode,
3483                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3484                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3485                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3486                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3487                          break;                          break;
3488    
3489                  case 3: /* Pattern */                  case 3: /* Pattern */
3490                          for (i = 0; i != 8; i++)                          if (brush->bd == 0)     /* rdp4 brush */
3491                                  ipattern[7 - i] = brush->pattern[i];                          {
3492                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                                  for (i = 0; i != 8; i++)
3493                          SET_FOREGROUND(bgcolour);                                          ipattern[7 - i] = brush->pattern[i];
3494                          SET_BACKGROUND(fgcolour);                                  fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
3495                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                                  SET_FOREGROUND(bgcolour);
3496                          XSetStipple(g_display, g_gc, fill);                                  SET_BACKGROUND(fgcolour);
3497                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                                  XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3498                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                                  XSetStipple(g_display, g_gc, fill);
3499                          XSetFillStyle(g_display, g_gc, FillSolid);                                  XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3500                          XSetTSOrigin(g_display, g_gc, 0, 0);                                  DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3501                          ui_destroy_glyph((HGLYPH) fill);                                  XSetFillStyle(g_display, g_gc, FillSolid);
3502                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3503                                    ui_destroy_glyph((RD_HGLYPH) fill);
3504                            }
3505                            else if (brush->bd->colour_code > 1)    /* > 1 bpp */
3506                            {
3507                                    fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
3508                                    XSetFillStyle(g_display, g_gc, FillTiled);
3509                                    XSetTile(g_display, g_gc, fill);
3510                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3511                                    DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3512                                    XSetFillStyle(g_display, g_gc, FillSolid);
3513                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3514                                    ui_destroy_bitmap((RD_HBITMAP) fill);
3515                            }
3516                            else
3517                            {
3518                                    fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
3519                                    SET_FOREGROUND(bgcolour);
3520                                    SET_BACKGROUND(fgcolour);
3521                                    XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
3522                                    XSetStipple(g_display, g_gc, fill);
3523                                    XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
3524                                    DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3525                                    XSetFillStyle(g_display, g_gc, FillSolid);
3526                                    XSetTSOrigin(g_display, g_gc, 0, 0);
3527                                    ui_destroy_glyph((RD_HGLYPH) fill);
3528                            }
3529                          break;                          break;
3530    
3531                  default:                  default:
# Line 3007  ui_ellipse(uint8 opcode, Line 3539  ui_ellipse(uint8 opcode,
3539  void  void
3540  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
3541                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
3542                /* src */ HGLYPH glyph, int srcx, int srcy,                /* src */ RD_HGLYPH glyph, int srcx, int srcy,
3543                int bgcolour, int fgcolour)                int bgcolour, int fgcolour)
3544  {  {
3545          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
# Line 3192  ui_desktop_save(uint32 offset, int x, in Line 3724  ui_desktop_save(uint32 offset, int x, in
3724          if (g_ownbackstore)          if (g_ownbackstore)
3725          {          {
3726                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3727                    exit_if_null(image);
3728          }          }
3729          else          else
3730          {          {
3731                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3732                  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);
3733                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3734                    exit_if_null(image);
3735                  XFreePixmap(g_display, pix);                  XFreePixmap(g_display, pix);
3736          }          }
3737    
# Line 3219  ui_desktop_restore(uint32 offset, int x, Line 3753  ui_desktop_restore(uint32 offset, int x,
3753                  return;                  return;
3754    
3755          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3756                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3757    
3758          if (g_ownbackstore)          if (g_ownbackstore)
3759          {          {
# Line 3253  ui_end_update(void) Line 3787  ui_end_update(void)
3787    
3788    
3789  void  void
3790  ui_seamless_begin(BOOL hidden)  ui_seamless_begin(RD_BOOL hidden)
3791  {  {
3792          if (!g_seamless_rdp)          if (!g_seamless_rdp)
3793                  return;                  return;
# Line 3408  ui_seamless_create_window(unsigned long Line 3942  ui_seamless_create_window(unsigned long
3942                  ewmh_set_window_modal(wnd);                  ewmh_set_window_modal(wnd);
3943          }          }
3944    
3945            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
3946            {
3947                    /* Make window always-on-top */
3948                    ewmh_set_window_above(wnd);
3949            }
3950    
3951          /* FIXME: Support for Input Context:s */          /* FIXME: Support for Input Context:s */
3952    
3953          get_input_mask(&input_mask);          get_input_mask(&input_mask);
# Line 3415  ui_seamless_create_window(unsigned long Line 3955  ui_seamless_create_window(unsigned long
3955    
3956          XSelectInput(g_display, wnd, input_mask);          XSelectInput(g_display, wnd, input_mask);
3957    
3958          /* 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 */  
3959          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3960    
3961          sw = xmalloc(sizeof(seamless_window));          sw = xmalloc(sizeof(seamless_window));
3962    
3963            memset(sw, 0, sizeof(seamless_window));
3964    
3965          sw->wnd = wnd;          sw->wnd = wnd;
3966          sw->id = id;          sw->id = id;
         sw->behind = 0;  
3967          sw->group = sw_find_group(group, False);          sw->group = sw_find_group(group, False);
3968          sw->group->refcnt++;          sw->group->refcnt++;
         sw->xoffset = 0;  
         sw->yoffset = 0;  
         sw->width = 0;  
         sw->height = 0;  
3969          sw->state = SEAMLESSRDP_NOTYETMAPPED;          sw->state = SEAMLESSRDP_NOTYETMAPPED;
3970          sw->desktop = 0;          sw->desktop = 0;
3971          sw->position_timer = xmalloc(sizeof(struct timeval));          sw->position_timer = xmalloc(sizeof(struct timeval));
# Line 3497  ui_seamless_destroy_group(unsigned long Line 4033  ui_seamless_destroy_group(unsigned long
4033    
4034    
4035  void  void
4036    ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
4037                        const char *data, int chunk_len)
4038    {
4039            seamless_window *sw;
4040    
4041            if (!g_seamless_active)
4042                    return;
4043    
4044            sw = sw_get_window_by_id(id);
4045            if (!sw)
4046            {
4047                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
4048                    return;
4049            }
4050    
4051            if (chunk == 0)
4052            {
4053                    if (sw->icon_size)
4054                            warning("ui_seamless_seticon: New icon started before previous completed\n");
4055    
4056                    if (strcmp(format, "RGBA") != 0)
4057                    {
4058                            warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
4059                            return;
4060                    }
4061    
4062                    sw->icon_size = width * height * 4;
4063                    if (sw->icon_size > 32 * 32 * 4)
4064                    {
4065                            warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
4066                            sw->icon_size = 0;
4067                            return;
4068                    }
4069    
4070                    sw->icon_offset = 0;
4071            }
4072            else
4073            {
4074                    if (!sw->icon_size)
4075                            return;
4076            }
4077    
4078            if (chunk_len > (sw->icon_size - sw->icon_offset))
4079            {
4080                    warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
4081                            chunk_len, sw->icon_size - sw->icon_offset);
4082                    sw->icon_size = 0;
4083                    return;
4084            }
4085    
4086            memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
4087            sw->icon_offset += chunk_len;
4088    
4089            if (sw->icon_offset == sw->icon_size)
4090            {
4091                    ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
4092                    sw->icon_size = 0;
4093            }
4094    }
4095    
4096    
4097    void
4098    ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
4099    {
4100            seamless_window *sw;
4101    
4102            if (!g_seamless_active)
4103                    return;
4104    
4105            sw = sw_get_window_by_id(id);
4106            if (!sw)
4107            {
4108                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
4109                    return;
4110            }
4111    
4112            if (strcmp(format, "RGBA") != 0)
4113            {
4114                    warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
4115                    return;
4116            }
4117    
4118            ewmh_del_icon(sw->wnd, width, height);
4119    }
4120    
4121    
4122    void
4123  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)
4124  {  {
4125          seamless_window *sw;          seamless_window *sw;
# Line 3542  void Line 4165  void
4165  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)
4166  {  {
4167          seamless_window *sw;          seamless_window *sw;
4168            XWindowChanges values;
4169            unsigned long restack_serial;
4170    
4171          if (!g_seamless_active)          if (!g_seamless_active)
4172                  return;                  return;
# Line 3556  ui_seamless_restack_window(unsigned long Line 4181  ui_seamless_restack_window(unsigned long
4181          if (behind)          if (behind)
4182          {          {
4183                  seamless_window *sw_behind;                  seamless_window *sw_behind;
                 Window wnds[2];  
4184    
4185                  sw_behind = sw_get_window_by_id(behind);                  sw_behind = sw_get_window_by_id(behind);
4186                  if (!sw_behind)                  if (!sw_behind)
4187                  {                  {
4188                          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);  
4189                          return;                          return;
4190                  }                  }
4191    
4192                  wnds[1] = sw_behind->wnd;                  if (!g_seamless_broken_restack)
4193                  wnds[0] = sw->wnd;                  {
4194                            values.stack_mode = Below;
4195                  XRestackWindows(g_display, wnds, 2);                          values.sibling = sw_behind->wnd;
4196                            restack_serial = XNextRequest(g_display);
4197                            XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display),
4198                                                 CWStackMode | CWSibling, &values);
4199                            sw_wait_configurenotify(sw->wnd, restack_serial);
4200                    }
4201          }          }
4202          else          else
4203          {          {
4204                  XRaiseWindow(g_display, sw->wnd);                  values.stack_mode = Above;
4205                    restack_serial = XNextRequest(g_display);
4206                    XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display), CWStackMode,
4207                                         &values);
4208                    sw_wait_configurenotify(sw->wnd, restack_serial);
4209          }          }
4210    
4211          sw_restack_window(sw, behind);          sw_restack_window(sw, behind);
4212    
4213            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
4214            {
4215                    /* Make window always-on-top */
4216                    ewmh_set_window_above(sw->wnd);
4217            }
4218  }  }
4219    
4220    

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

  ViewVC Help
Powered by ViewVC 1.1.26