/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

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

sourceforge.net/trunk/rdesktop/xwin.c revision 1057 by astrand, Tue Mar 7 08:17:40 2006 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1118 by astrand, Tue Mar 14 13:56:50 2006 UTC
# Line 48  Time g_last_gesturetime; Line 48  Time g_last_gesturetime;
48  static int g_x_socket;  static int g_x_socket;
49  static Screen *g_screen;  static Screen *g_screen;
50  Window g_wnd;  Window g_wnd;
51    
52    /* SeamlessRDP support */
53    typedef struct _seamless_window
54    {
55            Window wnd;
56            unsigned long id;
57            int xoffset, yoffset;
58            int width, height;
59            unsigned int state;     /* normal/minimized/maximized */
60            struct _seamless_window *next;
61    } seamless_window;
62    static seamless_window *g_seamless_windows = NULL;
63    extern BOOL g_seamless_rdp;
64    
65  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
66  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
67  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
68  static GC g_gc = NULL;  static GC g_gc = NULL;
69  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
70  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
71    static XRectangle g_clip_rectangle;
72  static Visual *g_visual;  static Visual *g_visual;
73  /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).  /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
74     This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined     This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
# Line 69  static XModifierKeymap *g_mod_map; Line 84  static XModifierKeymap *g_mod_map;
84  static Cursor g_current_cursor;  static Cursor g_current_cursor;
85  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
86  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
87    extern Atom g_net_wm_state_atom;
88  static BOOL g_focused;  static BOOL g_focused;
89  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
90  /* Indicates that:  /* Indicates that:
# Line 133  typedef struct Line 149  typedef struct
149  }  }
150  PixelColour;  PixelColour;
151    
152    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
153            do { \
154                    seamless_window *sw; \
155                    XRectangle rect; \
156                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
157                        rect.x = g_clip_rectangle.x - sw->xoffset; \
158                        rect.y = g_clip_rectangle.y - sw->yoffset; \
159                        rect.width = g_clip_rectangle.width; \
160                        rect.height = g_clip_rectangle.height; \
161                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
162                        func args; \
163                    } \
164                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
165            } while (0)
166    
167    static void
168    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
169    {
170            points[0].x -= xoffset;
171            points[0].y -= yoffset;
172            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
173            points[0].x += xoffset;
174            points[0].y += yoffset;
175    }
176    
177    static void
178    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
179    {
180            points[0].x -= xoffset;
181            points[0].y -= yoffset;
182            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
183            points[0].x += xoffset;
184            points[0].y += yoffset;
185    }
186    
187  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
188  { \  { \
189          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
190            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
191          if (g_ownbackstore) \          if (g_ownbackstore) \
192                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
193  }  }
# Line 151  PixelColour; Line 202  PixelColour;
202          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
203          if (g_ownbackstore) \          if (g_ownbackstore) \
204                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
205            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
206  }  }
207    
208  #define DRAW_ELLIPSE(x,y,cx,cy,m)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 159  PixelColour; Line 211  PixelColour;
211          { \          { \
212                  case 0: /* Outline */ \                  case 0: /* Outline */ \
213                          XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
214                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
215                          if (g_ownbackstore) \                          if (g_ownbackstore) \
216                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \                                  XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
217                          break; \                          break; \
218                  case 1: /* Filled */ \                  case 1: /* Filled */ \
219                          XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          XFillArc(g_display, g_wnd, g_gc, x, y, \
220                                     cx, cy, 0, 360*64); \
221                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc, x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \
222                          if (g_ownbackstore) \                          if (g_ownbackstore) \
223                                  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); \
224                          break; \                          break; \
# Line 201  static int rop2_map[] = { Line 256  static int rop2_map[] = {
256  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
257  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
258    
259    static seamless_window *
260    seamless_get_window_by_id(unsigned long id)
261    {
262            seamless_window *sw;
263            for (sw = g_seamless_windows; sw; sw = sw->next)
264            {
265                    if (sw->id == id)
266                            return sw;
267            }
268            return NULL;
269    }
270    
271    
272    static seamless_window *
273    seamless_get_window_by_wnd(Window wnd)
274    {
275            seamless_window *sw;
276            for (sw = g_seamless_windows; sw; sw = sw->next)
277            {
278                    if (sw->wnd == wnd)
279                            return sw;
280            }
281            return NULL;
282    }
283    
284    
285    static void
286    seamless_remove_window(seamless_window * win)
287    {
288            seamless_window *sw, **prevnext = &g_seamless_windows;
289            for (sw = g_seamless_windows; sw; sw = sw->next)
290            {
291                    if (sw == win)
292                    {
293                            *prevnext = sw->next;
294                            xfree(sw);
295                            return;
296                    }
297                    prevnext = &sw->next;
298            }
299            return;
300    }
301    
302    
303  static void  static void
304  mwm_hide_decorations(void)  mwm_hide_decorations(Window wnd)
305  {  {
306          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
307          Atom hintsatom;          Atom hintsatom;
# Line 219  mwm_hide_decorations(void) Line 318  mwm_hide_decorations(void)
318                  return;                  return;
319          }          }
320    
321          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
322                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
323    
324  }  }
325    
326  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 1298  ui_init(void) Line 1398  ui_init(void)
1398                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1399    
1400          xclip_init();          xclip_init();
1401            ewmh_init();
1402            if (g_seamless_rdp)
1403                    seamless_init();
1404    
1405          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));
1406    
# Line 1323  ui_deinit(void) Line 1426  ui_deinit(void)
1426          g_display = NULL;          g_display = NULL;
1427  }  }
1428    
1429    
1430    static void
1431    get_window_attribs(XSetWindowAttributes * attribs)
1432    {
1433            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1434            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1435            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1436            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1437            attribs->override_redirect = g_fullscreen;
1438            attribs->colormap = g_xcolmap;
1439    }
1440    
1441    static void
1442    get_input_mask(long *input_mask)
1443    {
1444            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1445                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1446    
1447            if (g_sendmotion)
1448                    *input_mask |= PointerMotionMask;
1449            if (g_ownbackstore)
1450                    *input_mask |= ExposureMask;
1451            if (g_fullscreen || g_grab_keyboard)
1452                    *input_mask |= EnterWindowMask;
1453            if (g_grab_keyboard)
1454                    *input_mask |= LeaveWindowMask;
1455    }
1456    
1457  BOOL  BOOL
1458  ui_create_window(void)  ui_create_window(void)
1459  {  {
# Line 1345  ui_create_window(void) Line 1476  ui_create_window(void)
1476          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1477                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1478    
1479          attribs.background_pixel = BlackPixelOfScreen(g_screen);          get_window_attribs(&attribs);
         attribs.border_pixel = WhitePixelOfScreen(g_screen);  
         attribs.backing_store = g_ownbackstore ? NotUseful : Always;  
         attribs.override_redirect = g_fullscreen;  
         attribs.colormap = g_xcolmap;  
1480    
1481          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1482                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1357  ui_create_window(void) Line 1484  ui_create_window(void)
1484                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1485    
1486          if (g_gc == NULL)          if (g_gc == NULL)
1487            {
1488                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1489                    ui_reset_clip();
1490            }
1491    
1492          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1493                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
# Line 1374  ui_create_window(void) Line 1504  ui_create_window(void)
1504          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1505    
1506          if (g_hide_decorations)          if (g_hide_decorations)
1507                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1508    
1509          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1510          if (classhints != NULL)          if (classhints != NULL)
# Line 1401  ui_create_window(void) Line 1531  ui_create_window(void)
1531                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1532          }          }
1533    
1534          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          get_input_mask(&input_mask);
                 VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;  
   
         if (g_sendmotion)  
                 input_mask |= PointerMotionMask;  
         if (g_ownbackstore)  
                 input_mask |= ExposureMask;  
         if (g_fullscreen || g_grab_keyboard)  
                 input_mask |= EnterWindowMask;  
         if (g_grab_keyboard)  
                 input_mask |= LeaveWindowMask;  
1535    
1536          if (g_IM != NULL)          if (g_IM != NULL)
1537          {          {
# Line 1424  ui_create_window(void) Line 1544  ui_create_window(void)
1544          }          }
1545    
1546          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1547          XMapWindow(g_display, g_wnd);          if (!g_seamless_rdp)
   
         /* wait for VisibilityNotify */  
         do  
1548          {          {
1549                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMapWindow(g_display, g_wnd);
1550                    /* wait for VisibilityNotify */
1551                    do
1552                    {
1553                            XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1554                    }
1555                    while (xevent.type != VisibilityNotify);
1556                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1557          }          }
         while (xevent.type != VisibilityNotify);  
         g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;  
1558    
1559          g_focused = False;          g_focused = False;
1560          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1496  xwin_toggle_fullscreen(void) Line 1618  xwin_toggle_fullscreen(void)
1618  {  {
1619          Pixmap contents = 0;          Pixmap contents = 0;
1620    
1621            if (g_seamless_rdp)
1622                    /* Turn off SeamlessRDP mode */
1623                    ui_seamless_toggle();
1624    
1625          if (!g_ownbackstore)          if (!g_ownbackstore)
1626          {          {
1627                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1584  handle_button_event(XEvent xevent, BOOL Line 1710  handle_button_event(XEvent xevent, BOOL
1710                  }                  }
1711          }          }
1712    
1713          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1714                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1715                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1716                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1717            }
1718            else
1719            {
1720                    /* SeamlessRDP */
1721                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1722                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1723            }
1724  }  }
1725    
1726  /* Process events in Xlib queue  /* Process events in Xlib queue
# Line 1599  xwin_process_events(void) Line 1734  xwin_process_events(void)
1734          char str[256];          char str[256];
1735          Status status;          Status status;
1736          int events = 0;          int events = 0;
1737            seamless_window *sw;
1738    
1739          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1740          {          {
# Line 1613  xwin_process_events(void) Line 1749  xwin_process_events(void)
1749                  switch (xevent.type)                  switch (xevent.type)
1750                  {                  {
1751                          case VisibilityNotify:                          case VisibilityNotify:
1752                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1753                                            g_Unobscured =
1754                                                    xevent.xvisibility.state == VisibilityUnobscured;
1755    
1756                                  break;                                  break;
1757                          case ClientMessage:                          case ClientMessage:
1758                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1693  xwin_process_events(void) Line 1832  xwin_process_events(void)
1832                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1833                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1834                                                         CurrentTime);                                                         CurrentTime);
1835                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1836                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1837                                    {
1838                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1839                                                           xevent.xmotion.x, xevent.xmotion.y);
1840                                    }
1841                                    else
1842                                    {
1843                                            /* SeamlessRDP */
1844                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1845                                                           xevent.xmotion.x_root,
1846                                                           xevent.xmotion.y_root);
1847                                    }
1848                                  break;                                  break;
1849    
1850                          case FocusIn:                          case FocusIn:
# Line 1737  xwin_process_events(void) Line 1887  xwin_process_events(void)
1887                                  break;                                  break;
1888    
1889                          case Expose:                          case Expose:
1890                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
1891                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1892                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1893                                            xevent.xexpose.height,                                                    g_gc,
1894                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1895                                                      xevent.xexpose.width, xevent.xexpose.height,
1896                                                      xevent.xexpose.x, xevent.xexpose.y);
1897                                    }
1898                                    else
1899                                    {
1900                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1901                                            if (sw)
1902                                                    XCopyArea(g_display, g_backstore,
1903                                                              xevent.xexpose.window, g_gc,
1904                                                              xevent.xexpose.x + sw->xoffset,
1905                                                              xevent.xexpose.y + sw->yoffset,
1906                                                              xevent.xexpose.width,
1907                                                              xevent.xexpose.height, xevent.xexpose.x,
1908                                                              xevent.xexpose.y);
1909                                            else
1910                                            {
1911                                                    error("Expose for unknown window 0x%lx\n",
1912                                                          xevent.xexpose.window);
1913                                            }
1914                                    }
1915    
1916                                  break;                                  break;
1917    
1918                          case MappingNotify:                          case MappingNotify:
# Line 1770  xwin_process_events(void) Line 1941  xwin_process_events(void)
1941                                  break;                                  break;
1942                          case PropertyNotify:                          case PropertyNotify:
1943                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1944                                    if (xevent.xproperty.window == g_wnd)
1945                                            break;
1946                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
1947                                            break;
1948    
1949                                    /* seamless */
1950                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
1951                                    if (!sw)
1952                                            break;
1953    
1954                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
1955                                        && (xevent.xproperty.state == PropertyNewValue))
1956                                    {
1957                                            sw->state = ewmh_get_window_state(sw->wnd);
1958                                            seamless_send_state(sw->id, sw->state, 0);
1959                                    }
1960                                  break;                                  break;
1961                          case MapNotify:                          case MapNotify:
1962                                  rdp_send_client_window_status(1);                                  if (!g_seamless_rdp)
1963                                            rdp_send_client_window_status(1);
1964                                  break;                                  break;
1965                          case UnmapNotify:                          case UnmapNotify:
1966                                  rdp_send_client_window_status(0);                                  if (!g_seamless_rdp)
1967                                            rdp_send_client_window_status(0);
1968                                  break;                                  break;
1969                  }                  }
1970          }          }
# Line 1912  ui_paint_bitmap(int x, int y, int cx, in Line 2101  ui_paint_bitmap(int x, int y, int cx, in
2101          {          {
2102                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2103                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2104                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2105                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2106                                             x - sw->xoffset, y - sw->yoffset));
2107          }          }
2108          else          else
2109          {          {
2110                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2111                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2112                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2113                                             x - sw->xoffset, y - sw->yoffset));
2114          }          }
2115    
2116          XFree(image);          XFree(image);
# Line 2036  ui_set_cursor(HCURSOR cursor) Line 2231  ui_set_cursor(HCURSOR cursor)
2231  {  {
2232          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2233          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2234            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2235  }  }
2236    
2237  void  void
# Line 2177  ui_set_colourmap(HCOLOURMAP map) Line 2373  ui_set_colourmap(HCOLOURMAP map)
2373                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2374          }          }
2375          else          else
2376            {
2377                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2378                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2379            }
2380  }  }
2381    
2382  void  void
2383  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2384  {  {
2385          XRectangle rect;          g_clip_rectangle.x = x;
2386            g_clip_rectangle.y = y;
2387          rect.x = x;          g_clip_rectangle.width = cx;
2388          rect.y = y;          g_clip_rectangle.height = cy;
2389          rect.width = cx;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = cy;  
         XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);  
2390  }  }
2391    
2392  void  void
2393  ui_reset_clip(void)  ui_reset_clip(void)
2394  {  {
2395          XRectangle rect;          g_clip_rectangle.x = 0;
2396            g_clip_rectangle.y = 0;
2397          rect.x = 0;          g_clip_rectangle.width = g_width;
2398          rect.y = 0;          g_clip_rectangle.height = g_height;
2399          rect.width = g_width;          XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
         rect.height = g_height;  
         XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);  
2400  }  }
2401    
2402  void  void
# Line 2282  ui_patblt(uint8 opcode, Line 2477  ui_patblt(uint8 opcode,
2477    
2478          if (g_ownbackstore)          if (g_ownbackstore)
2479                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2480            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2481                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2482                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2483  }  }
2484    
2485  void  void
# Line 2292  ui_screenblt(uint8 opcode, Line 2490  ui_screenblt(uint8 opcode,
2490          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2491          if (g_ownbackstore)          if (g_ownbackstore)
2492          {          {
2493                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2494                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2495                          XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                         XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,  
                                   y);  
                 }  
                 else  
                 {  
                         XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
                         XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,  
                                   y);  
                 }  
2496          }          }
2497          else          else
2498          {          {
2499                  XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2500          }          }
2501    
2502            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2503                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2504                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2505    
2506          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2507  }  }
2508    
# Line 2319  ui_memblt(uint8 opcode, Line 2513  ui_memblt(uint8 opcode,
2513  {  {
2514          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2515          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);
2516            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2517                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2518                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2519          if (g_ownbackstore)          if (g_ownbackstore)
2520                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2521          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2365  ui_line(uint8 opcode, Line 2562  ui_line(uint8 opcode,
2562          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2563          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2564          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2565            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2566                                                startx - sw->xoffset, starty - sw->yoffset,
2567                                                endx - sw->xoffset, endy - sw->yoffset));
2568          if (g_ownbackstore)          if (g_ownbackstore)
2569                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2570          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2462  ui_polyline(uint8 opcode, Line 2662  ui_polyline(uint8 opcode,
2662          if (g_ownbackstore)          if (g_ownbackstore)
2663                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2664                             CoordModePrevious);                             CoordModePrevious);
2665    
2666            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2667                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2668    
2669          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2670  }  }
2671    
# Line 2682  ui_draw_text(uint8 font, uint8 flags, ui Line 2886  ui_draw_text(uint8 font, uint8 flags, ui
2886          if (g_ownbackstore)          if (g_ownbackstore)
2887          {          {
2888                  if (boxcx > 1)                  if (boxcx > 1)
2889                    {
2890                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2891                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2892                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2893                                                    (g_display, g_backstore, sw->wnd, g_gc,
2894                                                     boxx, boxy,
2895                                                     boxcx, boxcy,
2896                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2897                    }
2898                  else                  else
2899                    {
2900                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2901                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2902                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2903                                                    (g_display, g_backstore, sw->wnd, g_gc,
2904                                                     clipx, clipy,
2905                                                     clipcx, clipcy, clipx - sw->xoffset,
2906                                                     clipy - sw->yoffset));
2907                    }
2908          }          }
2909  }  }
2910    
# Line 2732  ui_desktop_restore(uint32 offset, int x, Line 2950  ui_desktop_restore(uint32 offset, int x,
2950          {          {
2951                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2952                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2953                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2954                                            (g_display, g_backstore, sw->wnd, g_gc,
2955                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2956          }          }
2957          else          else
2958          {          {
2959                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2960                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2961                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2962                                             x - sw->xoffset, y - sw->yoffset));
2963          }          }
2964    
2965          XFree(image);          XFree(image);
# Line 2751  void Line 2975  void
2975  ui_end_update(void)  ui_end_update(void)
2976  {  {
2977  }  }
2978    
2979    void
2980    ui_seamless_toggle()
2981    {
2982            if (g_seamless_rdp)
2983            {
2984                    /* Deactivate */
2985                    while (g_seamless_windows)
2986                    {
2987                            XDestroyWindow(g_display, g_seamless_windows->wnd);
2988                            seamless_remove_window(g_seamless_windows);
2989                    }
2990                    XMapWindow(g_display, g_wnd);
2991            }
2992            else
2993            {
2994                    /* Activate */
2995                    if (g_win_button_size)
2996                    {
2997                            error("SeamlessRDP mode cannot be activated when using single application mode\n");
2998                            return;
2999                    }
3000                    if (!g_using_full_workarea)
3001                    {
3002                            error("SeamlessRDP mode requires a session that covers the whole screen");
3003                            return;
3004                    }
3005    
3006                    XUnmapWindow(g_display, g_wnd);
3007                    seamless_send_sync();
3008            }
3009    
3010            g_seamless_rdp = !g_seamless_rdp;
3011    }
3012    
3013    void
3014    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3015    {
3016            Window wnd;
3017            XSetWindowAttributes attribs;
3018            XClassHint *classhints;
3019            long input_mask;
3020            seamless_window *sw, *sw_parent;
3021    
3022            get_window_attribs(&attribs);
3023    
3024            attribs.override_redirect = False;
3025    
3026            /* FIXME: Do not assume that -1, -1 is outside screen Consider
3027               wait with showing the window until STATE and others have
3028               been recieved. */
3029            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, 0,
3030                                InputOutput, g_visual,
3031                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3032                                CWBorderPixel, &attribs);
3033    
3034            XStoreName(g_display, wnd, "rdesktop-seamless");
3035    
3036            mwm_hide_decorations(wnd);
3037    
3038            classhints = XAllocClassHint();
3039            if (classhints != NULL)
3040            {
3041                    classhints->res_name = classhints->res_class = "rdesktop";
3042                    XSetClassHint(g_display, wnd, classhints);
3043                    XFree(classhints);
3044            }
3045    
3046            /* Set WM_TRANSIENT_FOR, if necessary */
3047            if (parent)
3048            {
3049                    sw_parent = seamless_get_window_by_id(parent);
3050                    if (sw_parent)
3051                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3052                    else
3053                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3054            }
3055    
3056            /* FIXME: Support for Input Context:s */
3057    
3058            get_input_mask(&input_mask);
3059            input_mask |= PropertyChangeMask;
3060    
3061            XSelectInput(g_display, wnd, input_mask);
3062    
3063            XMapWindow(g_display, wnd);
3064    
3065            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3066               seamless window, we could try to close the window on the
3067               serverside, instead of terminating rdesktop */
3068            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3069    
3070            sw = malloc(sizeof(seamless_window));
3071            sw->wnd = wnd;
3072            sw->id = id;
3073            sw->xoffset = 0;
3074            sw->yoffset = 0;
3075            sw->width = 0;
3076            sw->height = 0;
3077            sw->next = g_seamless_windows;
3078            g_seamless_windows = sw;
3079    }
3080    
3081    
3082    void
3083    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3084    {
3085            seamless_window *sw;
3086    
3087            sw = seamless_get_window_by_id(id);
3088            if (!sw)
3089            {
3090                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3091                    return;
3092            }
3093    
3094            XDestroyWindow(g_display, sw->wnd);
3095            seamless_remove_window(sw);
3096    }
3097    
3098    
3099    void
3100    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3101    {
3102            seamless_window *sw;
3103    
3104            sw = seamless_get_window_by_id(id);
3105            if (!sw)
3106            {
3107                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3108                    return;
3109            }
3110    
3111            if (!width || !height)
3112                    /* X11 windows must be at least 1x1 */
3113                    return;
3114    
3115            /* About MAX and MIN: Windows allows moving a window outside
3116               the desktop. This happens, for example, when maximizing an
3117               application. In this case, the position is set to something
3118               like -4,-4,1288,1032. Many WMs does not allow windows
3119               outside the desktop, however. Therefore, clip the window
3120               ourselves. */
3121            sw->xoffset = MAX(0, x);
3122            sw->yoffset = MAX(0, y);
3123            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3124            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3125    
3126            /* If we move the window in a maximized state, then KDE won't
3127               accept restoration */
3128            if (sw->state != SEAMLESSRDP_NORMAL)
3129                    return;
3130    
3131            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3132            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3133    }
3134    
3135    
3136    void
3137    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3138    {
3139            seamless_window *sw;
3140    
3141            sw = seamless_get_window_by_id(id);
3142            if (!sw)
3143            {
3144                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3145                    return;
3146            }
3147    
3148            XStoreName(g_display, sw->wnd, title);
3149    }
3150    
3151    
3152    void
3153    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3154    {
3155            seamless_window *sw;
3156    
3157            sw = seamless_get_window_by_id(id);
3158            if (!sw)
3159            {
3160                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3161                    return;
3162            }
3163    
3164            sw->state = state;
3165    
3166            switch (state)
3167            {
3168                    case SEAMLESSRDP_NORMAL:
3169                    case SEAMLESSRDP_MAXIMIZED:
3170                            ewmh_change_state(sw->wnd, state);
3171                            break;
3172                    case SEAMLESSRDP_MINIMIZED:
3173                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3174                               the Window Manager should probably just ignore the request, since
3175                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3176                               such as minimization, rather than an independent state." Besides,
3177                               XIconifyWindow is easier. */
3178                            XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3179                            break;
3180                    default:
3181                            warning("SeamlessRDP: Invalid state %d\n", state);
3182                            break;
3183            }
3184    }

Legend:
Removed from v.1057  
changed lines
  Added in v.1118

  ViewVC Help
Powered by ViewVC 1.1.26