/[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 1119 by astrand, Wed Mar 15 06:42:57 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            unsigned int desktop;
61            struct _seamless_window *next;
62    } seamless_window;
63    static seamless_window *g_seamless_windows = NULL;
64    extern BOOL g_seamless_rdp;
65    
66  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
67  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
68  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
69  static GC g_gc = NULL;  static GC g_gc = NULL;
70  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
71  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
72    static XRectangle g_clip_rectangle;
73  static Visual *g_visual;  static Visual *g_visual;
74  /* 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).
75     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 85  static XModifierKeymap *g_mod_map;
85  static Cursor g_current_cursor;  static Cursor g_current_cursor;
86  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
87  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
88    extern Atom g_net_wm_state_atom;
89    extern Atom g_net_wm_desktop_atom;
90  static BOOL g_focused;  static BOOL g_focused;
91  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
92  /* Indicates that:  /* Indicates that:
# Line 133  typedef struct Line 151  typedef struct
151  }  }
152  PixelColour;  PixelColour;
153    
154    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
155            do { \
156                    seamless_window *sw; \
157                    XRectangle rect; \
158                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
159                        rect.x = g_clip_rectangle.x - sw->xoffset; \
160                        rect.y = g_clip_rectangle.y - sw->yoffset; \
161                        rect.width = g_clip_rectangle.width; \
162                        rect.height = g_clip_rectangle.height; \
163                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
164                        func args; \
165                    } \
166                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
167            } while (0)
168    
169    static void
170    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
171    {
172            points[0].x -= xoffset;
173            points[0].y -= yoffset;
174            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
175            points[0].x += xoffset;
176            points[0].y += yoffset;
177    }
178    
179    static void
180    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
181    {
182            points[0].x -= xoffset;
183            points[0].y -= yoffset;
184            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
185            points[0].x += xoffset;
186            points[0].y += yoffset;
187    }
188    
189  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
190  { \  { \
191          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
192            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
193          if (g_ownbackstore) \          if (g_ownbackstore) \
194                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
195  }  }
# Line 151  PixelColour; Line 204  PixelColour;
204          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
205          if (g_ownbackstore) \          if (g_ownbackstore) \
206                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
207            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
208  }  }
209    
210  #define DRAW_ELLIPSE(x,y,cx,cy,m)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 159  PixelColour; Line 213  PixelColour;
213          { \          { \
214                  case 0: /* Outline */ \                  case 0: /* Outline */ \
215                          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); \
216                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
217                          if (g_ownbackstore) \                          if (g_ownbackstore) \
218                                  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); \
219                          break; \                          break; \
220                  case 1: /* Filled */ \                  case 1: /* Filled */ \
221                          XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          XFillArc(g_display, g_wnd, g_gc, x, y, \
222                                     cx, cy, 0, 360*64); \
223                            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)); \
224                          if (g_ownbackstore) \                          if (g_ownbackstore) \
225                                  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); \
226                          break; \                          break; \
# Line 201  static int rop2_map[] = { Line 258  static int rop2_map[] = {
258  #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]); }
259  #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); }
260    
261    static seamless_window *
262    seamless_get_window_by_id(unsigned long id)
263    {
264            seamless_window *sw;
265            for (sw = g_seamless_windows; sw; sw = sw->next)
266            {
267                    if (sw->id == id)
268                            return sw;
269            }
270            return NULL;
271    }
272    
273    
274    static seamless_window *
275    seamless_get_window_by_wnd(Window wnd)
276    {
277            seamless_window *sw;
278            for (sw = g_seamless_windows; sw; sw = sw->next)
279            {
280                    if (sw->wnd == wnd)
281                            return sw;
282            }
283            return NULL;
284    }
285    
286    
287    static void
288    seamless_remove_window(seamless_window * win)
289    {
290            seamless_window *sw, **prevnext = &g_seamless_windows;
291            for (sw = g_seamless_windows; sw; sw = sw->next)
292            {
293                    if (sw == win)
294                    {
295                            *prevnext = sw->next;
296                            xfree(sw);
297                            return;
298                    }
299                    prevnext = &sw->next;
300            }
301            return;
302    }
303    
304    
305    /* Move all windows except wnd to new desktop */
306  static void  static void
307  mwm_hide_decorations(void)  seamless_all_to_desktop(Window wnd, unsigned int desktop)
308    {
309            seamless_window *sw;
310            for (sw = g_seamless_windows; sw; sw = sw->next)
311            {
312                    if (sw->wnd == wnd)
313                            continue;
314                    if (sw->desktop != desktop)
315                    {
316                            ewmh_move_to_desktop(sw->wnd, desktop);
317                            sw->desktop = desktop;
318                    }
319            }
320    }
321    
322    
323    static void
324    mwm_hide_decorations(Window wnd)
325  {  {
326          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
327          Atom hintsatom;          Atom hintsatom;
# Line 219  mwm_hide_decorations(void) Line 338  mwm_hide_decorations(void)
338                  return;                  return;
339          }          }
340    
341          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
342                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
343    
344  }  }
345    
346  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 1298  ui_init(void) Line 1418  ui_init(void)
1418                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1419    
1420          xclip_init();          xclip_init();
1421            ewmh_init();
1422            if (g_seamless_rdp)
1423                    seamless_init();
1424    
1425          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));
1426    
# Line 1323  ui_deinit(void) Line 1446  ui_deinit(void)
1446          g_display = NULL;          g_display = NULL;
1447  }  }
1448    
1449    
1450    static void
1451    get_window_attribs(XSetWindowAttributes * attribs)
1452    {
1453            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1454            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1455            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1456            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1457            attribs->override_redirect = g_fullscreen;
1458            attribs->colormap = g_xcolmap;
1459    }
1460    
1461    static void
1462    get_input_mask(long *input_mask)
1463    {
1464            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1465                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1466    
1467            if (g_sendmotion)
1468                    *input_mask |= PointerMotionMask;
1469            if (g_ownbackstore)
1470                    *input_mask |= ExposureMask;
1471            if (g_fullscreen || g_grab_keyboard)
1472                    *input_mask |= EnterWindowMask;
1473            if (g_grab_keyboard)
1474                    *input_mask |= LeaveWindowMask;
1475    }
1476    
1477  BOOL  BOOL
1478  ui_create_window(void)  ui_create_window(void)
1479  {  {
# Line 1345  ui_create_window(void) Line 1496  ui_create_window(void)
1496          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1497                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1498    
1499          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;  
1500    
1501          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,
1502                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1357  ui_create_window(void) Line 1504  ui_create_window(void)
1504                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1505    
1506          if (g_gc == NULL)          if (g_gc == NULL)
1507            {
1508                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1509                    ui_reset_clip();
1510            }
1511    
1512          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1513                  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 1524  ui_create_window(void)
1524          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1525    
1526          if (g_hide_decorations)          if (g_hide_decorations)
1527                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1528    
1529          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1530          if (classhints != NULL)          if (classhints != NULL)
# Line 1401  ui_create_window(void) Line 1551  ui_create_window(void)
1551                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1552          }          }
1553    
1554          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;  
1555    
1556          if (g_IM != NULL)          if (g_IM != NULL)
1557          {          {
# Line 1424  ui_create_window(void) Line 1564  ui_create_window(void)
1564          }          }
1565    
1566          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1567          XMapWindow(g_display, g_wnd);          if (!g_seamless_rdp)
   
         /* wait for VisibilityNotify */  
         do  
1568          {          {
1569                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMapWindow(g_display, g_wnd);
1570                    /* wait for VisibilityNotify */
1571                    do
1572                    {
1573                            XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1574                    }
1575                    while (xevent.type != VisibilityNotify);
1576                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1577          }          }
         while (xevent.type != VisibilityNotify);  
         g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;  
1578    
1579          g_focused = False;          g_focused = False;
1580          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1496  xwin_toggle_fullscreen(void) Line 1638  xwin_toggle_fullscreen(void)
1638  {  {
1639          Pixmap contents = 0;          Pixmap contents = 0;
1640    
1641            if (g_seamless_rdp)
1642                    /* Turn off SeamlessRDP mode */
1643                    ui_seamless_toggle();
1644    
1645          if (!g_ownbackstore)          if (!g_ownbackstore)
1646          {          {
1647                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1584  handle_button_event(XEvent xevent, BOOL Line 1730  handle_button_event(XEvent xevent, BOOL
1730                  }                  }
1731          }          }
1732    
1733          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1734                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1735                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1736                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1737            }
1738            else
1739            {
1740                    /* SeamlessRDP */
1741                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1742                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1743            }
1744  }  }
1745    
1746  /* Process events in Xlib queue  /* Process events in Xlib queue
# Line 1599  xwin_process_events(void) Line 1754  xwin_process_events(void)
1754          char str[256];          char str[256];
1755          Status status;          Status status;
1756          int events = 0;          int events = 0;
1757            seamless_window *sw;
1758    
1759          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1760          {          {
# Line 1613  xwin_process_events(void) Line 1769  xwin_process_events(void)
1769                  switch (xevent.type)                  switch (xevent.type)
1770                  {                  {
1771                          case VisibilityNotify:                          case VisibilityNotify:
1772                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1773                                            g_Unobscured =
1774                                                    xevent.xvisibility.state == VisibilityUnobscured;
1775    
1776                                  break;                                  break;
1777                          case ClientMessage:                          case ClientMessage:
1778                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1693  xwin_process_events(void) Line 1852  xwin_process_events(void)
1852                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1853                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1854                                                         CurrentTime);                                                         CurrentTime);
1855                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1856                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1857                                    {
1858                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1859                                                           xevent.xmotion.x, xevent.xmotion.y);
1860                                    }
1861                                    else
1862                                    {
1863                                            /* SeamlessRDP */
1864                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1865                                                           xevent.xmotion.x_root,
1866                                                           xevent.xmotion.y_root);
1867                                    }
1868                                  break;                                  break;
1869    
1870                          case FocusIn:                          case FocusIn:
# Line 1737  xwin_process_events(void) Line 1907  xwin_process_events(void)
1907                                  break;                                  break;
1908    
1909                          case Expose:                          case Expose:
1910                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
1911                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
1912                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
1913                                            xevent.xexpose.height,                                                    g_gc,
1914                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
1915                                                      xevent.xexpose.width, xevent.xexpose.height,
1916                                                      xevent.xexpose.x, xevent.xexpose.y);
1917                                    }
1918                                    else
1919                                    {
1920                                            sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1921                                            if (sw)
1922                                                    XCopyArea(g_display, g_backstore,
1923                                                              xevent.xexpose.window, g_gc,
1924                                                              xevent.xexpose.x + sw->xoffset,
1925                                                              xevent.xexpose.y + sw->yoffset,
1926                                                              xevent.xexpose.width,
1927                                                              xevent.xexpose.height, xevent.xexpose.x,
1928                                                              xevent.xexpose.y);
1929                                            else
1930                                            {
1931                                                    error("Expose for unknown window 0x%lx\n",
1932                                                          xevent.xexpose.window);
1933                                            }
1934                                    }
1935    
1936                                  break;                                  break;
1937    
1938                          case MappingNotify:                          case MappingNotify:
# Line 1770  xwin_process_events(void) Line 1961  xwin_process_events(void)
1961                                  break;                                  break;
1962                          case PropertyNotify:                          case PropertyNotify:
1963                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1964                                    if (xevent.xproperty.window == g_wnd)
1965                                            break;
1966                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
1967                                            break;
1968    
1969                                    /* seamless */
1970                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
1971                                    if (!sw)
1972                                            break;
1973    
1974                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
1975                                        && (xevent.xproperty.state == PropertyNewValue))
1976                                    {
1977                                            sw->state = ewmh_get_window_state(sw->wnd);
1978                                            seamless_send_state(sw->id, sw->state, 0);
1979                                    }
1980    
1981                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
1982                                        && (xevent.xproperty.state == PropertyNewValue))
1983                                    {
1984                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
1985                                            seamless_all_to_desktop(sw->wnd, sw->desktop);
1986                                    }
1987    
1988                                  break;                                  break;
1989                          case MapNotify:                          case MapNotify:
1990                                  rdp_send_client_window_status(1);                                  if (!g_seamless_rdp)
1991                                            rdp_send_client_window_status(1);
1992                                  break;                                  break;
1993                          case UnmapNotify:                          case UnmapNotify:
1994                                  rdp_send_client_window_status(0);                                  if (!g_seamless_rdp)
1995                                            rdp_send_client_window_status(0);
1996                                  break;                                  break;
1997                  }                  }
1998          }          }
# Line 1912  ui_paint_bitmap(int x, int y, int cx, in Line 2129  ui_paint_bitmap(int x, int y, int cx, in
2129          {          {
2130                  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);
2131                  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);
2132                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2133                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2134                                             x - sw->xoffset, y - sw->yoffset));
2135          }          }
2136          else          else
2137          {          {
2138                  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);
2139                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2140                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2141                                             x - sw->xoffset, y - sw->yoffset));
2142          }          }
2143    
2144          XFree(image);          XFree(image);
# Line 2036  ui_set_cursor(HCURSOR cursor) Line 2259  ui_set_cursor(HCURSOR cursor)
2259  {  {
2260          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2261          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2262            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2263  }  }
2264    
2265  void  void
# Line 2177  ui_set_colourmap(HCOLOURMAP map) Line 2401  ui_set_colourmap(HCOLOURMAP map)
2401                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2402          }          }
2403          else          else
2404            {
2405                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2406                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2407            }
2408  }  }
2409    
2410  void  void
2411  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2412  {  {
2413          XRectangle rect;          g_clip_rectangle.x = x;
2414            g_clip_rectangle.y = y;
2415          rect.x = x;          g_clip_rectangle.width = cx;
2416          rect.y = y;          g_clip_rectangle.height = cy;
2417          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);  
2418  }  }
2419    
2420  void  void
2421  ui_reset_clip(void)  ui_reset_clip(void)
2422  {  {
2423          XRectangle rect;          g_clip_rectangle.x = 0;
2424            g_clip_rectangle.y = 0;
2425          rect.x = 0;          g_clip_rectangle.width = g_width;
2426          rect.y = 0;          g_clip_rectangle.height = g_height;
2427          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);  
2428  }  }
2429    
2430  void  void
# Line 2282  ui_patblt(uint8 opcode, Line 2505  ui_patblt(uint8 opcode,
2505    
2506          if (g_ownbackstore)          if (g_ownbackstore)
2507                  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);
2508            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2509                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2510                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2511  }  }
2512    
2513  void  void
# Line 2292  ui_screenblt(uint8 opcode, Line 2518  ui_screenblt(uint8 opcode,
2518          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2519          if (g_ownbackstore)          if (g_ownbackstore)
2520          {          {
2521                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2522                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2523                          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);  
                 }  
2524          }          }
2525          else          else
2526          {          {
2527                  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);
2528          }          }
2529    
2530            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2531                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2532                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2533    
2534          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2535  }  }
2536    
# Line 2319  ui_memblt(uint8 opcode, Line 2541  ui_memblt(uint8 opcode,
2541  {  {
2542          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2543          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);
2544            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2545                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2546                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2547          if (g_ownbackstore)          if (g_ownbackstore)
2548                  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);
2549          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2365  ui_line(uint8 opcode, Line 2590  ui_line(uint8 opcode,
2590          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2591          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2592          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2593            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2594                                                startx - sw->xoffset, starty - sw->yoffset,
2595                                                endx - sw->xoffset, endy - sw->yoffset));
2596          if (g_ownbackstore)          if (g_ownbackstore)
2597                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2598          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2462  ui_polyline(uint8 opcode, Line 2690  ui_polyline(uint8 opcode,
2690          if (g_ownbackstore)          if (g_ownbackstore)
2691                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2692                             CoordModePrevious);                             CoordModePrevious);
2693    
2694            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2695                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2696    
2697          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2698  }  }
2699    
# Line 2682  ui_draw_text(uint8 font, uint8 flags, ui Line 2914  ui_draw_text(uint8 font, uint8 flags, ui
2914          if (g_ownbackstore)          if (g_ownbackstore)
2915          {          {
2916                  if (boxcx > 1)                  if (boxcx > 1)
2917                    {
2918                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2919                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
2920                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2921                                                    (g_display, g_backstore, sw->wnd, g_gc,
2922                                                     boxx, boxy,
2923                                                     boxcx, boxcy,
2924                                                     boxx - sw->xoffset, boxy - sw->yoffset));
2925                    }
2926                  else                  else
2927                    {
2928                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2929                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
2930                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2931                                                    (g_display, g_backstore, sw->wnd, g_gc,
2932                                                     clipx, clipy,
2933                                                     clipcx, clipcy, clipx - sw->xoffset,
2934                                                     clipy - sw->yoffset));
2935                    }
2936          }          }
2937  }  }
2938    
# Line 2732  ui_desktop_restore(uint32 offset, int x, Line 2978  ui_desktop_restore(uint32 offset, int x,
2978          {          {
2979                  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);
2980                  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);
2981                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2982                                            (g_display, g_backstore, sw->wnd, g_gc,
2983                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2984          }          }
2985          else          else
2986          {          {
2987                  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);
2988                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2989                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2990                                             x - sw->xoffset, y - sw->yoffset));
2991          }          }
2992    
2993          XFree(image);          XFree(image);
# Line 2751  void Line 3003  void
3003  ui_end_update(void)  ui_end_update(void)
3004  {  {
3005  }  }
3006    
3007    void
3008    ui_seamless_toggle()
3009    {
3010            if (g_seamless_rdp)
3011            {
3012                    /* Deactivate */
3013                    while (g_seamless_windows)
3014                    {
3015                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3016                            seamless_remove_window(g_seamless_windows);
3017                    }
3018                    XMapWindow(g_display, g_wnd);
3019            }
3020            else
3021            {
3022                    /* Activate */
3023                    if (g_win_button_size)
3024                    {
3025                            error("SeamlessRDP mode cannot be activated when using single application mode\n");
3026                            return;
3027                    }
3028                    if (!g_using_full_workarea)
3029                    {
3030                            error("SeamlessRDP mode requires a session that covers the whole screen");
3031                            return;
3032                    }
3033    
3034                    XUnmapWindow(g_display, g_wnd);
3035                    seamless_send_sync();
3036            }
3037    
3038            g_seamless_rdp = !g_seamless_rdp;
3039    }
3040    
3041    void
3042    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3043    {
3044            Window wnd;
3045            XSetWindowAttributes attribs;
3046            XClassHint *classhints;
3047            long input_mask;
3048            seamless_window *sw, *sw_parent;
3049    
3050            get_window_attribs(&attribs);
3051    
3052            attribs.override_redirect = False;
3053    
3054            /* FIXME: Do not assume that -1, -1 is outside screen Consider
3055               wait with showing the window until STATE and others have
3056               been recieved. */
3057            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, 0,
3058                                InputOutput, g_visual,
3059                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3060                                CWBorderPixel, &attribs);
3061    
3062            XStoreName(g_display, wnd, "rdesktop-seamless");
3063    
3064            mwm_hide_decorations(wnd);
3065    
3066            classhints = XAllocClassHint();
3067            if (classhints != NULL)
3068            {
3069                    classhints->res_name = classhints->res_class = "rdesktop";
3070                    XSetClassHint(g_display, wnd, classhints);
3071                    XFree(classhints);
3072            }
3073    
3074            /* Set WM_TRANSIENT_FOR, if necessary */
3075            if (parent)
3076            {
3077                    sw_parent = seamless_get_window_by_id(parent);
3078                    if (sw_parent)
3079                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3080                    else
3081                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3082            }
3083    
3084            /* FIXME: Support for Input Context:s */
3085    
3086            get_input_mask(&input_mask);
3087            input_mask |= PropertyChangeMask;
3088    
3089            XSelectInput(g_display, wnd, input_mask);
3090    
3091            XMapWindow(g_display, wnd);
3092    
3093            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3094               seamless window, we could try to close the window on the
3095               serverside, instead of terminating rdesktop */
3096            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3097    
3098            sw = malloc(sizeof(seamless_window));
3099            sw->wnd = wnd;
3100            sw->id = id;
3101            sw->xoffset = 0;
3102            sw->yoffset = 0;
3103            sw->width = 0;
3104            sw->height = 0;
3105            sw->next = g_seamless_windows;
3106            g_seamless_windows = sw;
3107    }
3108    
3109    
3110    void
3111    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3112    {
3113            seamless_window *sw;
3114    
3115            sw = seamless_get_window_by_id(id);
3116            if (!sw)
3117            {
3118                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3119                    return;
3120            }
3121    
3122            XDestroyWindow(g_display, sw->wnd);
3123            seamless_remove_window(sw);
3124    }
3125    
3126    
3127    void
3128    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3129    {
3130            seamless_window *sw;
3131    
3132            sw = seamless_get_window_by_id(id);
3133            if (!sw)
3134            {
3135                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3136                    return;
3137            }
3138    
3139            if (!width || !height)
3140                    /* X11 windows must be at least 1x1 */
3141                    return;
3142    
3143            /* About MAX and MIN: Windows allows moving a window outside
3144               the desktop. This happens, for example, when maximizing an
3145               application. In this case, the position is set to something
3146               like -4,-4,1288,1032. Many WMs does not allow windows
3147               outside the desktop, however. Therefore, clip the window
3148               ourselves. */
3149            sw->xoffset = MAX(0, x);
3150            sw->yoffset = MAX(0, y);
3151            sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3152            sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3153    
3154            /* If we move the window in a maximized state, then KDE won't
3155               accept restoration */
3156            if (sw->state != SEAMLESSRDP_NORMAL)
3157                    return;
3158    
3159            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3160            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3161    }
3162    
3163    
3164    void
3165    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3166    {
3167            seamless_window *sw;
3168    
3169            sw = seamless_get_window_by_id(id);
3170            if (!sw)
3171            {
3172                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3173                    return;
3174            }
3175    
3176            XStoreName(g_display, sw->wnd, title);
3177    }
3178    
3179    
3180    void
3181    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3182    {
3183            seamless_window *sw;
3184    
3185            sw = seamless_get_window_by_id(id);
3186            if (!sw)
3187            {
3188                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3189                    return;
3190            }
3191    
3192            sw->state = state;
3193    
3194            switch (state)
3195            {
3196                    case SEAMLESSRDP_NORMAL:
3197                    case SEAMLESSRDP_MAXIMIZED:
3198                            ewmh_change_state(sw->wnd, state);
3199                            break;
3200                    case SEAMLESSRDP_MINIMIZED:
3201                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3202                               the Window Manager should probably just ignore the request, since
3203                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3204                               such as minimization, rather than an independent state." Besides,
3205                               XIconifyWindow is easier. */
3206                            XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3207                            break;
3208                    default:
3209                            warning("SeamlessRDP: Invalid state %d\n", state);
3210                            break;
3211            }
3212    }

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

  ViewVC Help
Powered by ViewVC 1.1.26