/[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

revision 1246 by stargo, Tue Jul 11 17:22:24 2006 UTC revision 1463 by astrand, Fri Mar 28 11:36:15 2008 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-2007
5       Copyright 2007 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[16];
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 242  seamless_XDrawLines(Drawable d, XPoint * Line 247  seamless_XDrawLines(Drawable d, XPoint *
247                          break; \                          break; \
248                  case 1: /* Filled */ \                  case 1: /* Filled */ \
249                          XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
250                          ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc, \                          ON_ALL_SEAMLESS_WINDOWS(XFillArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
                                                             x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \  
251                          if (g_ownbackstore) \                          if (g_ownbackstore) \
252                                  XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \                                  XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
253                          break; \                          break; \
# Line 251  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 475  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 526  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 580  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 1188  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 1265  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            for (i = 0; i < pointer_buttons; ++i)
1529            {
1530                    /* This might produce multiple logical buttons mapping
1531                       to a single physical one, but hey, that's
1532                       life... */
1533                    g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
1534            }
1535    }
1536    
1537    RD_BOOL
1538  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1539  {  {
1540          int modifierpos, key, keysymMask = 0;          int modifierpos, key, keysymMask = 0;
# Line 1313  calculate_mask_weight(uint32 mask) Line 1582  calculate_mask_weight(uint32 mask)
1582          return weight;          return weight;
1583  }  }
1584    
1585  static BOOL  static RD_BOOL
1586  select_visual(int screen_num)  select_visual(int screen_num)
1587  {  {
1588          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
# Line 1341  select_visual(int screen_num) Line 1610  select_visual(int screen_num)
1610          /* Search for best TrueColor visual */          /* Search for best TrueColor visual */
1611          template.class = TrueColor;          template.class = TrueColor;
1612          template.screen = screen_num;          template.screen = screen_num;
1613          vmatches = XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template, &visuals_count);          vmatches =
1614                    XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template,
1615                                   &visuals_count);
1616          g_visual = NULL;          g_visual = NULL;
1617          g_no_translate_image = False;          g_no_translate_image = False;
1618          g_compatible_arch = False;          g_compatible_arch = False;
# Line 1350  select_visual(int screen_num) Line 1621  select_visual(int screen_num)
1621                  for (i = 0; i < visuals_count; ++i)                  for (i = 0; i < visuals_count; ++i)
1622                  {                  {
1623                          XVisualInfo *visual_info = &vmatches[i];                          XVisualInfo *visual_info = &vmatches[i];
1624                          BOOL can_translate_to_bpp = False;                          RD_BOOL can_translate_to_bpp = False;
1625                          int j;                          int j;
1626    
1627                          /* Try to find a no-translation visual that'll                          /* Try to find a no-translation visual that'll
# Line 1507  select_visual(int screen_num) Line 1778  select_visual(int screen_num)
1778  }  }
1779    
1780  static XErrorHandler g_old_error_handler;  static XErrorHandler g_old_error_handler;
1781    static RD_BOOL g_error_expected = False;
1782    
1783    /* Check if the X11 window corresponding to a seamless window with
1784       specified id exists. */
1785    RD_BOOL
1786    sw_window_exists(unsigned long id)
1787    {
1788            seamless_window *sw;
1789            char *name;
1790            Status sts = 0;
1791    
1792            sw = sw_get_window_by_id(id);
1793            if (!sw)
1794                    return False;
1795    
1796            g_error_expected = True;
1797            sts = XFetchName(g_display, sw->wnd, &name);
1798            g_error_expected = False;
1799            if (sts)
1800            {
1801                    XFree(name);
1802            }
1803    
1804            return sts;
1805    }
1806    
1807  static int  static int
1808  error_handler(Display * dpy, XErrorEvent * eev)  error_handler(Display * dpy, XErrorEvent * eev)
1809  {  {
1810          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");  
1811                  return 0;                  return 0;
         }  
1812    
1813          return g_old_error_handler(dpy, eev);          return g_old_error_handler(dpy, eev);
1814  }  }
1815    
1816  BOOL  RD_BOOL
1817  ui_init(void)  ui_init(void)
1818  {  {
1819          int screen_num;          int screen_num;
# Line 1536  ui_init(void) Line 1827  ui_init(void)
1827    
1828          {          {
1829                  uint16 endianess_test = 1;                  uint16 endianess_test = 1;
1830                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test));
1831          }          }
1832    
1833          g_old_error_handler = XSetErrorHandler(error_handler);          g_old_error_handler = XSetErrorHandler(error_handler);
# Line 1617  ui_init(void) Line 1908  ui_init(void)
1908          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1909    
1910          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1911            xwin_refresh_pointer_map();
1912    
1913          xkeymap_init();          xkeymap_init();
1914    
# Line 1626  ui_init(void) Line 1918  ui_init(void)
1918          xclip_init();          xclip_init();
1919          ewmh_init();          ewmh_init();
1920          if (g_seamless_rdp)          if (g_seamless_rdp)
1921            {
1922                  seamless_init();                  seamless_init();
1923            }
1924    
1925          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));
1926    
# Line 1688  get_input_mask(long *input_mask) Line 1982  get_input_mask(long *input_mask)
1982                  *input_mask |= LeaveWindowMask;                  *input_mask |= LeaveWindowMask;
1983  }  }
1984    
1985  BOOL  RD_BOOL
1986  ui_create_window(void)  ui_create_window(void)
1987  {  {
1988          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
# Line 1736  ui_create_window(void) Line 2030  ui_create_window(void)
2030          }          }
2031    
2032          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
2033            ewmh_set_wm_name(g_wnd, g_title);
2034    
2035          if (g_hide_decorations)          if (g_hide_decorations)
2036                  mwm_hide_decorations(g_wnd);                  mwm_hide_decorations(g_wnd);
# Line 1800  ui_create_window(void) Line 2095  ui_create_window(void)
2095          if (g_null_cursor == NULL)          if (g_null_cursor == NULL)
2096                  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);
2097    
2098            if (g_seamless_rdp)
2099            {
2100                    seamless_restack_test();
2101            }
2102    
2103          return True;          return True;
2104  }  }
2105    
# Line 1875  xwin_toggle_fullscreen(void) Line 2175  xwin_toggle_fullscreen(void)
2175  }  }
2176    
2177  static void  static void
2178  handle_button_event(XEvent xevent, BOOL down)  handle_button_event(XEvent xevent, RD_BOOL down)
2179  {  {
2180          uint16 button, flags = 0;          uint16 button, flags = 0;
2181          g_last_gesturetime = xevent.xbutton.time;          g_last_gesturetime = xevent.xbutton.time;
2182            /* Reverse the pointer button mapping, e.g. in the case of
2183               "left-handed mouse mode"; the RDP session expects to
2184               receive physical buttons (true in mstsc as well) and
2185               logical button behavior depends on the remote desktop's own
2186               mouse settings */
2187            xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
2188          button = xkeymap_translate_button(xevent.xbutton.button);          button = xkeymap_translate_button(xevent.xbutton.button);
2189          if (button == 0)          if (button == 0)
2190                  return;                  return;
# Line 1991  xwin_process_events(void) Line 2297  xwin_process_events(void)
2297                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
2298                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
2299                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
2300                                          /* Quit */                                  {
2301                                          return 0;                                          /* When killing a seamless window, close the window on the
2302                                               serverside instead of terminating rdesktop */
2303                                            sw = sw_get_window_by_wnd(xevent.xclient.window);
2304                                            if (!sw)
2305                                                    /* Otherwise, quit */
2306                                                    return 0;
2307                                            /* send seamless destroy process message */
2308                                            seamless_send_destroy(sw->id);
2309                                    }
2310                                  break;                                  break;
2311    
2312                          case KeyPress:                          case KeyPress:
# Line 2093  xwin_process_events(void) Line 2407  xwin_process_events(void)
2407                                  if (!sw)                                  if (!sw)
2408                                          break;                                          break;
2409    
2410                                    /* Menu windows are real X11 windows,
2411                                       with focus. When such a window is
2412                                       destroyed, focus is reverted to the
2413                                       main application window, which
2414                                       would cause us to send FOCUS. This
2415                                       breaks window switching in, say,
2416                                       Seamonkey. We shouldn't need to
2417                                       send FOCUS: Windows should also
2418                                       revert focus to some other window
2419                                       when the menu window is
2420                                       destroyed. So, we only send FOCUS
2421                                       if the previous focus window still
2422                                       exists. */
2423                                  if (sw->id != g_seamless_focused)                                  if (sw->id != g_seamless_focused)
2424                                  {                                  {
2425                                          seamless_send_focus(sw->id, 0);  
2426                                            if (sw_window_exists(g_seamless_focused))
2427                                                    seamless_send_focus(sw->id, 0);
2428                                          g_seamless_focused = sw->id;                                          g_seamless_focused = sw->id;
2429                                  }                                  }
2430                                  break;                                  break;
# Line 2166  xwin_process_events(void) Line 2495  xwin_process_events(void)
2495                                          XFreeModifiermap(g_mod_map);                                          XFreeModifiermap(g_mod_map);
2496                                          g_mod_map = XGetModifierMapping(g_display);                                          g_mod_map = XGetModifierMapping(g_display);
2497                                  }                                  }
2498    
2499                                    if (xevent.xmapping.request == MappingPointer)
2500                                    {
2501                                            xwin_refresh_pointer_map();
2502                                    }
2503    
2504                                  break;                                  break;
2505    
2506                                  /* clipboard stuff */                                  /* clipboard stuff */
# Line 2249  ui_select(int rdp_socket) Line 2584  ui_select(int rdp_socket)
2584          int n;          int n;
2585          fd_set rfds, wfds;          fd_set rfds, wfds;
2586          struct timeval tv;          struct timeval tv;
2587          BOOL s_timeout = False;          RD_BOOL s_timeout = False;
2588    
2589          while (True)          while (True)
2590          {          {
# Line 2267  ui_select(int rdp_socket) Line 2602  ui_select(int rdp_socket)
2602                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
2603                  FD_SET(g_x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
2604    
 #ifdef WITH_RDPSND  
                 /* FIXME: there should be an API for registering fds */  
                 if (g_dsp_busy)  
                 {  
                         FD_SET(g_dsp_fd, &wfds);  
                         n = (g_dsp_fd > n) ? g_dsp_fd : n;  
                 }  
 #endif  
2605                  /* default timeout */                  /* default timeout */
2606                  tv.tv_sec = 60;                  tv.tv_sec = 60;
2607                  tv.tv_usec = 0;                  tv.tv_usec = 0;
2608    
2609    #ifdef WITH_RDPSND
2610                    rdpsnd_add_fds(&n, &rfds, &wfds, &tv);
2611    #endif
2612    
2613                  /* add redirection handles */                  /* add redirection handles */
2614                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2615                  seamless_select_timeout(&tv);                  seamless_select_timeout(&tv);
# Line 2291  ui_select(int rdp_socket) Line 2622  ui_select(int rdp_socket)
2622                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
2623    
2624                          case 0:                          case 0:
2625    #ifdef WITH_RDPSND
2626                                    rdpsnd_check_fds(&rfds, &wfds);
2627    #endif
2628    
2629                                  /* Abort serial read calls */                                  /* Abort serial read calls */
2630                                  if (s_timeout)                                  if (s_timeout)
2631                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);                                          rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True);
2632                                  continue;                                  continue;
2633                  }                  }
2634    
2635                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);  #ifdef WITH_RDPSND
2636                    rdpsnd_check_fds(&rfds, &wfds);
2637    #endif
2638    
2639                    rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False);
2640    
2641                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
2642                          return 1;                          return 1;
2643    
 #ifdef WITH_RDPSND  
                 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))  
                         wave_out_play();  
 #endif  
2644          }          }
2645  }  }
2646    
# Line 2315  ui_move_pointer(int x, int y) Line 2650  ui_move_pointer(int x, int y)
2650          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);
2651  }  }
2652    
2653  HBITMAP  RD_HBITMAP
2654  ui_create_bitmap(int width, int height, uint8 * data)  ui_create_bitmap(int width, int height, uint8 * data)
2655  {  {
2656          XImage *image;          XImage *image;
# Line 2345  ui_create_bitmap(int width, int height, Line 2680  ui_create_bitmap(int width, int height,
2680          XFree(image);          XFree(image);
2681          if (tdata != data)          if (tdata != data)
2682                  xfree(tdata);                  xfree(tdata);
2683          return (HBITMAP) bitmap;          return (RD_HBITMAP) bitmap;
2684  }  }
2685    
2686  void  void
# Line 2393  ui_paint_bitmap(int x, int y, int cx, in Line 2728  ui_paint_bitmap(int x, int y, int cx, in
2728  }  }
2729    
2730  void  void
2731  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(RD_HBITMAP bmp)
2732  {  {
2733          XFreePixmap(g_display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
2734  }  }
2735    
2736  HGLYPH  RD_HGLYPH
2737  ui_create_glyph(int width, int height, uint8 * data)  ui_create_glyph(int width, int height, uint8 * data)
2738  {  {
2739          XImage *image;          XImage *image;
# Line 2420  ui_create_glyph(int width, int height, u Line 2755  ui_create_glyph(int width, int height, u
2755          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);
2756    
2757          XFree(image);          XFree(image);
2758          return (HGLYPH) bitmap;          return (RD_HGLYPH) bitmap;
2759  }  }
2760    
2761  void  void
2762  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(RD_HGLYPH glyph)
2763  {  {
2764          XFreePixmap(g_display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
2765  }  }
2766    
2767  HCURSOR  RD_HCURSOR
2768  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,
2769                   uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
2770  {  {
2771          HGLYPH maskglyph, cursorglyph;          RD_HGLYPH maskglyph, cursorglyph;
2772          XColor bg, fg;          XColor bg, fg;
2773          Cursor xcursor;          Cursor xcursor;
2774          uint8 *cursor, *pcursor;          uint8 *cursor, *pcursor;
# Line 2497  ui_create_cursor(unsigned int x, unsigne Line 2832  ui_create_cursor(unsigned int x, unsigne
2832          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2833          xfree(mask);          xfree(mask);
2834          xfree(cursor);          xfree(cursor);
2835          return (HCURSOR) xcursor;          return (RD_HCURSOR) xcursor;
2836  }  }
2837    
2838  void  void
2839  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(RD_HCURSOR cursor)
2840  {  {
2841          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2842          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
# Line 2509  ui_set_cursor(HCURSOR cursor) Line 2844  ui_set_cursor(HCURSOR cursor)
2844  }  }
2845    
2846  void  void
2847  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(RD_HCURSOR cursor)
2848  {  {
2849          XFreeCursor(g_display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
2850  }  }
# Line 2527  ui_set_null_cursor(void) Line 2862  ui_set_null_cursor(void)
2862                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2863    
2864    
2865  HCOLOURMAP  RD_HCOLOURMAP
2866  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
2867  {  {
2868          COLOURENTRY *entry;          COLOURENTRY *entry;
# Line 2623  ui_create_colourmap(COLOURMAP * colours) Line 2958  ui_create_colourmap(COLOURMAP * colours)
2958                  XStoreColors(g_display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
2959    
2960                  xfree(xcolours);                  xfree(xcolours);
2961                  return (HCOLOURMAP) map;                  return (RD_HCOLOURMAP) map;
2962          }          }
2963  }  }
2964    
2965  void  void
2966  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(RD_HCOLOURMAP map)
2967  {  {
2968          if (!g_owncolmap)          if (!g_owncolmap)
2969                  xfree(map);                  xfree(map);
# Line 2637  ui_destroy_colourmap(HCOLOURMAP map) Line 2972  ui_destroy_colourmap(HCOLOURMAP map)
2972  }  }
2973    
2974  void  void
2975  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(RD_HCOLOURMAP map)
2976  {  {
2977          if (!g_owncolmap)          if (!g_owncolmap)
2978          {          {
# Line 2725  ui_patblt(uint8 opcode, Line 3060  ui_patblt(uint8 opcode,
3060                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3061                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3062                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3063                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3064                          break;                          break;
3065    
3066                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2740  ui_patblt(uint8 opcode, Line 3075  ui_patblt(uint8 opcode,
3075                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
3076                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3077                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3078                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3079                          break;                          break;
3080    
3081                  default:                  default:
# Line 2783  ui_screenblt(uint8 opcode, Line 3118  ui_screenblt(uint8 opcode,
3118  void  void
3119  ui_memblt(uint8 opcode,  ui_memblt(uint8 opcode,
3120            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
3121            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ RD_HBITMAP src, int srcx, int srcy)
3122  {  {
3123          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
3124          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 2798  ui_memblt(uint8 opcode, Line 3133  ui_memblt(uint8 opcode,
3133  void  void
3134  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
3135            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
3136            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ RD_HBITMAP src, int srcx, int srcy,
3137            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
3138  {  {
3139          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
# Line 2856  ui_rect( Line 3191  ui_rect(
3191  void  void
3192  ui_polygon(uint8 opcode,  ui_polygon(uint8 opcode,
3193             /* mode */ uint8 fillmode,             /* mode */ uint8 fillmode,
3194             /* dest */ POINT * point, int npoints,             /* dest */ RD_POINT * point, int npoints,
3195             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)             /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
3196  {  {
3197          uint8 style, i, ipattern[8];          uint8 style, i, ipattern[8];
# Line 2899  ui_polygon(uint8 opcode, Line 3234  ui_polygon(uint8 opcode,
3234                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
3235                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3236                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3237                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3238                          break;                          break;
3239    
3240                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2914  ui_polygon(uint8 opcode, Line 3249  ui_polygon(uint8 opcode,
3249                          FILL_POLYGON((XPoint *) point, npoints);                          FILL_POLYGON((XPoint *) point, npoints);
3250                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3251                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3252                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3253                          break;                          break;
3254    
3255                  default:                  default:
# Line 2926  ui_polygon(uint8 opcode, Line 3261  ui_polygon(uint8 opcode,
3261    
3262  void  void
3263  ui_polyline(uint8 opcode,  ui_polyline(uint8 opcode,
3264              /* dest */ POINT * points, int npoints,              /* dest */ RD_POINT * points, int npoints,
3265              /* pen */ PEN * pen)              /* pen */ PEN * pen)
3266  {  {
3267          /* TODO: set join style */          /* TODO: set join style */
# Line 2977  ui_ellipse(uint8 opcode, Line 3312  ui_ellipse(uint8 opcode,
3312                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3313                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3314                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3315                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3316                          break;                          break;
3317    
3318                  case 3: /* Pattern */                  case 3: /* Pattern */
# Line 2992  ui_ellipse(uint8 opcode, Line 3327  ui_ellipse(uint8 opcode,
3327                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);                          DRAW_ELLIPSE(x, y, cx, cy, fillmode);
3328                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
3329                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
3330                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((RD_HGLYPH) fill);
3331                          break;                          break;
3332    
3333                  default:                  default:
# Line 3006  ui_ellipse(uint8 opcode, Line 3341  ui_ellipse(uint8 opcode,
3341  void  void
3342  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
3343                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
3344                /* src */ HGLYPH glyph, int srcx, int srcy,                /* src */ RD_HGLYPH glyph, int srcx, int srcy,
3345                int bgcolour, int fgcolour)                int bgcolour, int fgcolour)
3346  {  {
3347          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
# Line 3191  ui_desktop_save(uint32 offset, int x, in Line 3526  ui_desktop_save(uint32 offset, int x, in
3526          if (g_ownbackstore)          if (g_ownbackstore)
3527          {          {
3528                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3529                    exit_if_null(image);
3530          }          }
3531          else          else
3532          {          {
3533                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
3534                  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);
3535                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3536                    exit_if_null(image);
3537                  XFreePixmap(g_display, pix);                  XFreePixmap(g_display, pix);
3538          }          }
3539    
# Line 3218  ui_desktop_restore(uint32 offset, int x, Line 3555  ui_desktop_restore(uint32 offset, int x,
3555                  return;                  return;
3556    
3557          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3558                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3559    
3560          if (g_ownbackstore)          if (g_ownbackstore)
3561          {          {
# Line 3252  ui_end_update(void) Line 3589  ui_end_update(void)
3589    
3590    
3591  void  void
3592  ui_seamless_begin(BOOL hidden)  ui_seamless_begin(RD_BOOL hidden)
3593  {  {
3594          if (!g_seamless_rdp)          if (!g_seamless_rdp)
3595                  return;                  return;
# Line 3407  ui_seamless_create_window(unsigned long Line 3744  ui_seamless_create_window(unsigned long
3744                  ewmh_set_window_modal(wnd);                  ewmh_set_window_modal(wnd);
3745          }          }
3746    
3747            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
3748            {
3749                    /* Make window always-on-top */
3750                    ewmh_set_window_above(wnd);
3751            }
3752    
3753          /* FIXME: Support for Input Context:s */          /* FIXME: Support for Input Context:s */
3754    
3755          get_input_mask(&input_mask);          get_input_mask(&input_mask);
# Line 3414  ui_seamless_create_window(unsigned long Line 3757  ui_seamless_create_window(unsigned long
3757    
3758          XSelectInput(g_display, wnd, input_mask);          XSelectInput(g_display, wnd, input_mask);
3759    
3760          /* 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 */  
3761          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3762    
3763          sw = xmalloc(sizeof(seamless_window));          sw = xmalloc(sizeof(seamless_window));
3764    
3765            memset(sw, 0, sizeof(seamless_window));
3766    
3767          sw->wnd = wnd;          sw->wnd = wnd;
3768          sw->id = id;          sw->id = id;
         sw->behind = 0;  
3769          sw->group = sw_find_group(group, False);          sw->group = sw_find_group(group, False);
3770          sw->group->refcnt++;          sw->group->refcnt++;
         sw->xoffset = 0;  
         sw->yoffset = 0;  
         sw->width = 0;  
         sw->height = 0;  
3771          sw->state = SEAMLESSRDP_NOTYETMAPPED;          sw->state = SEAMLESSRDP_NOTYETMAPPED;
3772          sw->desktop = 0;          sw->desktop = 0;
3773          sw->position_timer = xmalloc(sizeof(struct timeval));          sw->position_timer = xmalloc(sizeof(struct timeval));
# Line 3496  ui_seamless_destroy_group(unsigned long Line 3835  ui_seamless_destroy_group(unsigned long
3835    
3836    
3837  void  void
3838    ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
3839                        const char *data, int chunk_len)
3840    {
3841            seamless_window *sw;
3842    
3843            if (!g_seamless_active)
3844                    return;
3845    
3846            sw = sw_get_window_by_id(id);
3847            if (!sw)
3848            {
3849                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3850                    return;
3851            }
3852    
3853            if (chunk == 0)
3854            {
3855                    if (sw->icon_size)
3856                            warning("ui_seamless_seticon: New icon started before previous completed\n");
3857    
3858                    if (strcmp(format, "RGBA") != 0)
3859                    {
3860                            warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3861                            return;
3862                    }
3863    
3864                    sw->icon_size = width * height * 4;
3865                    if (sw->icon_size > 32 * 32 * 4)
3866                    {
3867                            warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
3868                            sw->icon_size = 0;
3869                            return;
3870                    }
3871    
3872                    sw->icon_offset = 0;
3873            }
3874            else
3875            {
3876                    if (!sw->icon_size)
3877                            return;
3878            }
3879    
3880            if (chunk_len > (sw->icon_size - sw->icon_offset))
3881            {
3882                    warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
3883                            chunk_len, sw->icon_size - sw->icon_offset);
3884                    sw->icon_size = 0;
3885                    return;
3886            }
3887    
3888            memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
3889            sw->icon_offset += chunk_len;
3890    
3891            if (sw->icon_offset == sw->icon_size)
3892            {
3893                    ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
3894                    sw->icon_size = 0;
3895            }
3896    }
3897    
3898    
3899    void
3900    ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
3901    {
3902            seamless_window *sw;
3903    
3904            if (!g_seamless_active)
3905                    return;
3906    
3907            sw = sw_get_window_by_id(id);
3908            if (!sw)
3909            {
3910                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3911                    return;
3912            }
3913    
3914            if (strcmp(format, "RGBA") != 0)
3915            {
3916                    warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3917                    return;
3918            }
3919    
3920            ewmh_del_icon(sw->wnd, width, height);
3921    }
3922    
3923    
3924    void
3925  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)
3926  {  {
3927          seamless_window *sw;          seamless_window *sw;
# Line 3541  void Line 3967  void
3967  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)
3968  {  {
3969          seamless_window *sw;          seamless_window *sw;
3970            XWindowChanges values;
3971            unsigned long restack_serial;
3972    
3973          if (!g_seamless_active)          if (!g_seamless_active)
3974                  return;                  return;
# Line 3555  ui_seamless_restack_window(unsigned long Line 3983  ui_seamless_restack_window(unsigned long
3983          if (behind)          if (behind)
3984          {          {
3985                  seamless_window *sw_behind;                  seamless_window *sw_behind;
                 Window wnds[2];  
3986    
3987                  sw_behind = sw_get_window_by_id(behind);                  sw_behind = sw_get_window_by_id(behind);
3988                  if (!sw_behind)                  if (!sw_behind)
3989                  {                  {
3990                          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);  
3991                          return;                          return;
3992                  }                  }
3993    
3994                  wnds[1] = sw_behind->wnd;                  if (!g_seamless_broken_restack)
3995                  wnds[0] = sw->wnd;                  {
3996                            values.stack_mode = Below;
3997                  XRestackWindows(g_display, wnds, 2);                          values.sibling = sw_behind->wnd;
3998                            restack_serial = XNextRequest(g_display);
3999                            XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display),
4000                                                 CWStackMode | CWSibling, &values);
4001                            sw_wait_configurenotify(sw->wnd, restack_serial);
4002                    }
4003          }          }
4004          else          else
4005          {          {
4006                  XRaiseWindow(g_display, sw->wnd);                  values.stack_mode = Above;
4007                    restack_serial = XNextRequest(g_display);
4008                    XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display), CWStackMode,
4009                                         &values);
4010                    sw_wait_configurenotify(sw->wnd, restack_serial);
4011          }          }
4012    
4013          sw_restack_window(sw, behind);          sw_restack_window(sw, behind);
4014    
4015            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
4016            {
4017                    /* Make window always-on-top */
4018                    ewmh_set_window_above(sw->wnd);
4019            }
4020  }  }
4021    
4022    

Legend:
Removed from v.1246  
changed lines
  Added in v.1463

  ViewVC Help
Powered by ViewVC 1.1.26