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

revision 1058, Tue Mar 7 08:17:41 2006 UTC revision 1170 by astrand, Mon Mar 20 15:43:15 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            unsigned long behind;
58            int xoffset, yoffset;
59            int width, height;
60            int state;              /* normal/minimized/maximized. */
61            unsigned int desktop;
62            struct timeval *position_timer;
63    
64            BOOL outstanding_position;
65            unsigned int outpos_serial;
66            int outpos_xoffset, outpos_yoffset;
67            int outpos_width, outpos_height;
68    
69            struct _seamless_window *next;
70    } seamless_window;
71    static seamless_window *g_seamless_windows = NULL;
72    static unsigned long g_seamless_focused = 0;
73    static BOOL g_seamless_started = False; /* Server end is up and running */
74    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
75    extern BOOL g_seamless_rdp;
76    
77  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
78  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
79  BOOL g_Unobscured;              /* used for screenblt */  BOOL g_Unobscured;              /* used for screenblt */
80  static GC g_gc = NULL;  static GC g_gc = NULL;
81  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
82  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
83    static XRectangle g_clip_rectangle;
84  static Visual *g_visual;  static Visual *g_visual;
85  /* 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).
86     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 96  static XModifierKeymap *g_mod_map;
96  static Cursor g_current_cursor;  static Cursor g_current_cursor;
97  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
98  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
99    extern Atom g_net_wm_state_atom;
100    extern Atom g_net_wm_desktop_atom;
101  static BOOL g_focused;  static BOOL g_focused;
102  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
103  /* Indicates that:  /* Indicates that:
# Line 133  typedef struct Line 162  typedef struct
162  }  }
163  PixelColour;  PixelColour;
164    
165    #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
166            do { \
167                    seamless_window *sw; \
168                    XRectangle rect; \
169                    for (sw = g_seamless_windows; sw; sw = sw->next) { \
170                        rect.x = g_clip_rectangle.x - sw->xoffset; \
171                        rect.y = g_clip_rectangle.y - sw->yoffset; \
172                        rect.width = g_clip_rectangle.width; \
173                        rect.height = g_clip_rectangle.height; \
174                        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
175                        func args; \
176                    } \
177                    XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
178            } while (0)
179    
180    static void
181    seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
182    {
183            points[0].x -= xoffset;
184            points[0].y -= yoffset;
185            XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
186            points[0].x += xoffset;
187            points[0].y += yoffset;
188    }
189    
190    static void
191    seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
192    {
193            points[0].x -= xoffset;
194            points[0].y -= yoffset;
195            XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
196            points[0].x += xoffset;
197            points[0].y += yoffset;
198    }
199    
200  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
201  { \  { \
202          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
203            ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
204          if (g_ownbackstore) \          if (g_ownbackstore) \
205                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
206  }  }
# Line 151  PixelColour; Line 215  PixelColour;
215          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \          XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
216          if (g_ownbackstore) \          if (g_ownbackstore) \
217                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \                  XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
218            ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
219  }  }
220    
221  #define DRAW_ELLIPSE(x,y,cx,cy,m)\  #define DRAW_ELLIPSE(x,y,cx,cy,m)\
# Line 159  PixelColour; Line 224  PixelColour;
224          { \          { \
225                  case 0: /* Outline */ \                  case 0: /* Outline */ \
226                          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); \
227                            ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
228                          if (g_ownbackstore) \                          if (g_ownbackstore) \
229                                  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); \
230                          break; \                          break; \
231                  case 1: /* Filled */ \                  case 1: /* Filled */ \
232                          XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \                          XFillArc(g_display, g_wnd, g_gc, x, y, \
233                                     cx, cy, 0, 360*64); \
234                            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)); \
235                          if (g_ownbackstore) \                          if (g_ownbackstore) \
236                                  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); \
237                          break; \                          break; \
# Line 201  static int rop2_map[] = { Line 269  static int rop2_map[] = {
269  #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]); }
270  #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); }
271    
272    static seamless_window *
273    sw_get_window_by_id(unsigned long id)
274    {
275            seamless_window *sw;
276            for (sw = g_seamless_windows; sw; sw = sw->next)
277            {
278                    if (sw->id == id)
279                            return sw;
280            }
281            return NULL;
282    }
283    
284    
285    static seamless_window *
286    sw_get_window_by_wnd(Window wnd)
287    {
288            seamless_window *sw;
289            for (sw = g_seamless_windows; sw; sw = sw->next)
290            {
291                    if (sw->wnd == wnd)
292                            return sw;
293            }
294            return NULL;
295    }
296    
297    
298    static void
299    sw_remove_window(seamless_window * win)
300    {
301            seamless_window *sw, **prevnext = &g_seamless_windows;
302            for (sw = g_seamless_windows; sw; sw = sw->next)
303            {
304                    if (sw == win)
305                    {
306                            *prevnext = sw->next;
307                            xfree(sw);
308                            return;
309                    }
310                    prevnext = &sw->next;
311            }
312            return;
313    }
314    
315    
316    /* Move all windows except wnd to new desktop */
317    static void
318    sw_all_to_desktop(Window wnd, unsigned int desktop)
319    {
320            seamless_window *sw;
321            for (sw = g_seamless_windows; sw; sw = sw->next)
322            {
323                    if (sw->wnd == wnd)
324                            continue;
325                    if (sw->desktop != desktop)
326                    {
327                            ewmh_move_to_desktop(sw->wnd, desktop);
328                            sw->desktop = desktop;
329                    }
330            }
331    }
332    
333    
334    /* Send our position */
335    static void
336    sw_update_position(seamless_window * sw)
337    {
338            XWindowAttributes wa;
339            int x, y;
340            Window child_return;
341            unsigned int serial;
342    
343            XGetWindowAttributes(g_display, sw->wnd, &wa);
344            XTranslateCoordinates(g_display, sw->wnd, wa.root,
345                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
346    
347            serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
348    
349            sw->outstanding_position = True;
350            sw->outpos_serial = serial;
351    
352            sw->outpos_xoffset = x;
353            sw->outpos_yoffset = y;
354            sw->outpos_width = wa.width;
355            sw->outpos_height = wa.height;
356    }
357    
358    
359    /* Check if it's time to send our position */
360    static void
361    sw_check_timers()
362    {
363            seamless_window *sw;
364            struct timeval now;
365    
366            gettimeofday(&now, NULL);
367            for (sw = g_seamless_windows; sw; sw = sw->next)
368            {
369                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
370                    {
371                            timerclear(sw->position_timer);
372                            sw_update_position(sw);
373                    }
374            }
375    }
376    
377    
378    static void
379    sw_restack_window(seamless_window * sw, unsigned long behind)
380    {
381            seamless_window *sw_above;
382    
383            /* Remove window from stack */
384            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
385            {
386                    if (sw_above->behind == sw->id)
387                            break;
388            }
389    
390            if (sw_above)
391                    sw_above->behind = sw->behind;
392    
393            /* And then add it at the new position */
394    
395            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
396            {
397                    if (sw_above->behind == behind)
398                            break;
399            }
400    
401            if (sw_above)
402                    sw_above->behind = sw->id;
403    
404            sw->behind = behind;
405    }
406    
407    
408  static void  static void
409  mwm_hide_decorations(void)  sw_handle_restack(seamless_window * sw)
410    {
411            Status status;
412            Window root, parent, *children;
413            unsigned int nchildren, i;
414            seamless_window *sw_below;
415    
416            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
417                                &root, &parent, &children, &nchildren);
418            if (!status || !nchildren)
419                    return;
420    
421            sw_below = NULL;
422    
423            i = 0;
424            while (children[i] != sw->wnd)
425            {
426                    i++;
427                    if (i >= nchildren)
428                            return;
429            }
430    
431            for (i++; i < nchildren; i++)
432            {
433                    sw_below = sw_get_window_by_wnd(children[i]);
434                    if (sw_below)
435                            break;
436            }
437    
438            if (!sw_below && !sw->behind)
439                    return;
440            if (sw_below && (sw_below->id == sw->behind))
441                    return;
442    
443            if (sw_below)
444            {
445                    seamless_send_zchange(sw->id, sw_below->id, 0);
446                    sw_restack_window(sw, sw_below->id);
447            }
448            else
449            {
450                    seamless_send_zchange(sw->id, 0, 0);
451                    sw_restack_window(sw, 0);
452            }
453    }
454    
455    
456    static void
457    mwm_hide_decorations(Window wnd)
458  {  {
459          PropMotifWmHints motif_hints;          PropMotifWmHints motif_hints;
460          Atom hintsatom;          Atom hintsatom;
# Line 219  mwm_hide_decorations(void) Line 471  mwm_hide_decorations(void)
471                  return;                  return;
472          }          }
473    
474          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,          XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
475                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
476    
477  }  }
478    
479  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
# Line 1298  ui_init(void) Line 1551  ui_init(void)
1551                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1552    
1553          xclip_init();          xclip_init();
1554            ewmh_init();
1555            if (g_seamless_rdp)
1556                    seamless_init();
1557    
1558          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));
1559    
# Line 1323  ui_deinit(void) Line 1579  ui_deinit(void)
1579          g_display = NULL;          g_display = NULL;
1580  }  }
1581    
1582    
1583    static void
1584    get_window_attribs(XSetWindowAttributes * attribs)
1585    {
1586            attribs->background_pixel = BlackPixelOfScreen(g_screen);
1587            attribs->background_pixel = WhitePixelOfScreen(g_screen);
1588            attribs->border_pixel = WhitePixelOfScreen(g_screen);
1589            attribs->backing_store = g_ownbackstore ? NotUseful : Always;
1590            attribs->override_redirect = g_fullscreen;
1591            attribs->colormap = g_xcolmap;
1592    }
1593    
1594    static void
1595    get_input_mask(long *input_mask)
1596    {
1597            *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1598                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1599    
1600            if (g_sendmotion)
1601                    *input_mask |= PointerMotionMask;
1602            if (g_ownbackstore)
1603                    *input_mask |= ExposureMask;
1604            if (g_fullscreen || g_grab_keyboard)
1605                    *input_mask |= EnterWindowMask;
1606            if (g_grab_keyboard)
1607                    *input_mask |= LeaveWindowMask;
1608    }
1609    
1610  BOOL  BOOL
1611  ui_create_window(void)  ui_create_window(void)
1612  {  {
# Line 1345  ui_create_window(void) Line 1629  ui_create_window(void)
1629          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1630                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1631    
1632          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;  
1633    
1634          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,
1635                                wndheight, 0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
# Line 1357  ui_create_window(void) Line 1637  ui_create_window(void)
1637                                CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1638    
1639          if (g_gc == NULL)          if (g_gc == NULL)
1640            {
1641                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1642                    ui_reset_clip();
1643            }
1644    
1645          if (g_create_bitmap_gc == NULL)          if (g_create_bitmap_gc == NULL)
1646                  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 1657  ui_create_window(void)
1657          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1658    
1659          if (g_hide_decorations)          if (g_hide_decorations)
1660                  mwm_hide_decorations();                  mwm_hide_decorations(g_wnd);
1661    
1662          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1663          if (classhints != NULL)          if (classhints != NULL)
# Line 1401  ui_create_window(void) Line 1684  ui_create_window(void)
1684                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1685          }          }
1686    
1687          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;  
1688    
1689          if (g_IM != NULL)          if (g_IM != NULL)
1690          {          {
# Line 1424  ui_create_window(void) Line 1697  ui_create_window(void)
1697          }          }
1698    
1699          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
         XMapWindow(g_display, g_wnd);  
1700    
1701            XMapWindow(g_display, g_wnd);
1702          /* wait for VisibilityNotify */          /* wait for VisibilityNotify */
1703          do          do
1704          {          {
# Line 1496  xwin_toggle_fullscreen(void) Line 1769  xwin_toggle_fullscreen(void)
1769  {  {
1770          Pixmap contents = 0;          Pixmap contents = 0;
1771    
1772            if (g_seamless_active)
1773                    /* Turn off SeamlessRDP mode */
1774                    ui_seamless_toggle();
1775    
1776          if (!g_ownbackstore)          if (!g_ownbackstore)
1777          {          {
1778                  /* need to save contents of window */                  /* need to save contents of window */
# Line 1584  handle_button_event(XEvent xevent, BOOL Line 1861  handle_button_event(XEvent xevent, BOOL
1861                  }                  }
1862          }          }
1863    
1864          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,          if (xevent.xmotion.window == g_wnd)
1865                         flags | button, xevent.xbutton.x, xevent.xbutton.y);          {
1866                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1867                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1868            }
1869            else
1870            {
1871                    /* SeamlessRDP */
1872                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1873                                   flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1874            }
1875  }  }
1876    
1877    
1878  /* Process events in Xlib queue  /* Process events in Xlib queue
1879     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1880  static int  static int
# Line 1599  xwin_process_events(void) Line 1886  xwin_process_events(void)
1886          char str[256];          char str[256];
1887          Status status;          Status status;
1888          int events = 0;          int events = 0;
1889            seamless_window *sw;
1890    
1891          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1892          {          {
# Line 1613  xwin_process_events(void) Line 1901  xwin_process_events(void)
1901                  switch (xevent.type)                  switch (xevent.type)
1902                  {                  {
1903                          case VisibilityNotify:                          case VisibilityNotify:
1904                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;                                  if (xevent.xvisibility.window == g_wnd)
1905                                            g_Unobscured =
1906                                                    xevent.xvisibility.state == VisibilityUnobscured;
1907    
1908                                  break;                                  break;
1909                          case ClientMessage:                          case ClientMessage:
1910                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
# Line 1693  xwin_process_events(void) Line 1984  xwin_process_events(void)
1984                                  if (g_fullscreen && !g_focused)                                  if (g_fullscreen && !g_focused)
1985                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1986                                                         CurrentTime);                                                         CurrentTime);
1987                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
1988                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);                                  if (xevent.xmotion.window == g_wnd)
1989                                    {
1990                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1991                                                           xevent.xmotion.x, xevent.xmotion.y);
1992                                    }
1993                                    else
1994                                    {
1995                                            /* SeamlessRDP */
1996                                            rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
1997                                                           xevent.xmotion.x_root,
1998                                                           xevent.xmotion.y_root);
1999                                    }
2000                                  break;                                  break;
2001    
2002                          case FocusIn:                          case FocusIn:
# Line 1705  xwin_process_events(void) Line 2007  xwin_process_events(void)
2007                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2008                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2009                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2010    
2011                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2012                                    if (!sw)
2013                                            break;
2014    
2015                                    if (sw->id != g_seamless_focused)
2016                                    {
2017                                            seamless_send_focus(sw->id, 0);
2018                                            g_seamless_focused = sw->id;
2019                                    }
2020                                  break;                                  break;
2021    
2022                          case FocusOut:                          case FocusOut:
# Line 1737  xwin_process_events(void) Line 2049  xwin_process_events(void)
2049                                  break;                                  break;
2050    
2051                          case Expose:                          case Expose:
2052                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,                                  if (xevent.xexpose.window == g_wnd)
2053                                            xevent.xexpose.x, xevent.xexpose.y,                                  {
2054                                            xevent.xexpose.width,                                          XCopyArea(g_display, g_backstore, xevent.xexpose.window,
2055                                            xevent.xexpose.height,                                                    g_gc,
2056                                            xevent.xexpose.x, xevent.xexpose.y);                                                    xevent.xexpose.x, xevent.xexpose.y,
2057                                                      xevent.xexpose.width, xevent.xexpose.height,
2058                                                      xevent.xexpose.x, xevent.xexpose.y);
2059                                    }
2060                                    else
2061                                    {
2062                                            sw = sw_get_window_by_wnd(xevent.xexpose.window);
2063                                            if (sw)
2064                                                    XCopyArea(g_display, g_backstore,
2065                                                              xevent.xexpose.window, g_gc,
2066                                                              xevent.xexpose.x + sw->xoffset,
2067                                                              xevent.xexpose.y + sw->yoffset,
2068                                                              xevent.xexpose.width,
2069                                                              xevent.xexpose.height, xevent.xexpose.x,
2070                                                              xevent.xexpose.y);
2071                                            else
2072                                            {
2073                                                    error("Expose for unknown window 0x%lx\n",
2074                                                          xevent.xexpose.window);
2075                                            }
2076                                    }
2077    
2078                                  break;                                  break;
2079    
2080                          case MappingNotify:                          case MappingNotify:
# Line 1770  xwin_process_events(void) Line 2103  xwin_process_events(void)
2103                                  break;                                  break;
2104                          case PropertyNotify:                          case PropertyNotify:
2105                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2106                                    if (xevent.xproperty.window == g_wnd)
2107                                            break;
2108                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2109                                            break;
2110    
2111                                    /* seamless */
2112                                    sw = sw_get_window_by_wnd(xevent.xproperty.window);
2113                                    if (!sw)
2114                                            break;
2115    
2116                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2117                                        && (xevent.xproperty.state == PropertyNewValue))
2118                                    {
2119                                            sw->state = ewmh_get_window_state(sw->wnd);
2120                                            seamless_send_state(sw->id, sw->state, 0);
2121                                    }
2122    
2123                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2124                                        && (xevent.xproperty.state == PropertyNewValue))
2125                                    {
2126                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2127                                            sw_all_to_desktop(sw->wnd, sw->desktop);
2128                                    }
2129    
2130                                  break;                                  break;
2131                          case MapNotify:                          case MapNotify:
2132                                  rdp_send_client_window_status(1);                                  if (!g_seamless_active)
2133                                            rdp_send_client_window_status(1);
2134                                  break;                                  break;
2135                          case UnmapNotify:                          case UnmapNotify:
2136                                  rdp_send_client_window_status(0);                                  if (!g_seamless_active)
2137                                            rdp_send_client_window_status(0);
2138                                    break;
2139                            case ConfigureNotify:
2140                                    if (!g_seamless_active)
2141                                            break;
2142    
2143                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2144                                    if (!sw)
2145                                    {
2146                                            error("ConfigureNotify for unknown window 0x%lx\n",
2147                                                  xevent.xconfigure.window);
2148                                    }
2149    
2150                                    gettimeofday(sw->position_timer, NULL);
2151                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2152                                        1000000)
2153                                    {
2154                                            sw->position_timer->tv_usec +=
2155                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2156                                            sw->position_timer->tv_sec += 1;
2157                                    }
2158                                    else
2159                                    {
2160                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2161                                    }
2162    
2163                                    sw_handle_restack(sw);
2164                                  break;                                  break;
2165                  }                  }
2166          }          }
# Line 1800  ui_select(int rdp_socket) Line 2185  ui_select(int rdp_socket)
2185                          /* User quit */                          /* User quit */
2186                          return 0;                          return 0;
2187    
2188                    if (g_seamless_active)
2189                            sw_check_timers();
2190    
2191                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2192                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2193                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
# Line 1819  ui_select(int rdp_socket) Line 2207  ui_select(int rdp_socket)
2207    
2208                  /* add redirection handles */                  /* add redirection handles */
2209                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2210                    seamless_select_timeout(&tv);
2211    
2212                  n++;                  n++;
2213    
# Line 1912  ui_paint_bitmap(int x, int y, int cx, in Line 2301  ui_paint_bitmap(int x, int y, int cx, in
2301          {          {
2302                  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);
2303                  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);
2304                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2305                                            (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
2306                                             x - sw->xoffset, y - sw->yoffset));
2307          }          }
2308          else          else
2309          {          {
2310                  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);
2311                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2312                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
2313                                             x - sw->xoffset, y - sw->yoffset));
2314          }          }
2315    
2316          XFree(image);          XFree(image);
# Line 2036  ui_set_cursor(HCURSOR cursor) Line 2431  ui_set_cursor(HCURSOR cursor)
2431  {  {
2432          g_current_cursor = (Cursor) cursor;          g_current_cursor = (Cursor) cursor;
2433          XDefineCursor(g_display, g_wnd, g_current_cursor);          XDefineCursor(g_display, g_wnd, g_current_cursor);
2434            ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
2435  }  }
2436    
2437  void  void
# Line 2177  ui_set_colourmap(HCOLOURMAP map) Line 2573  ui_set_colourmap(HCOLOURMAP map)
2573                  g_colmap = (uint32 *) map;                  g_colmap = (uint32 *) map;
2574          }          }
2575          else          else
2576            {
2577                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2578                    ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
2579            }
2580  }  }
2581    
2582  void  void
2583  ui_set_clip(int x, int y, int cx, int cy)  ui_set_clip(int x, int y, int cx, int cy)
2584  {  {
2585          XRectangle rect;          g_clip_rectangle.x = x;
2586            g_clip_rectangle.y = y;
2587          rect.x = x;          g_clip_rectangle.width = cx;
2588          rect.y = y;          g_clip_rectangle.height = cy;
2589          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);  
2590  }  }
2591    
2592  void  void
2593  ui_reset_clip(void)  ui_reset_clip(void)
2594  {  {
2595          XRectangle rect;          g_clip_rectangle.x = 0;
2596            g_clip_rectangle.y = 0;
2597          rect.x = 0;          g_clip_rectangle.width = g_width;
2598          rect.y = 0;          g_clip_rectangle.height = g_height;
2599          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);  
2600  }  }
2601    
2602  void  void
# Line 2282  ui_patblt(uint8 opcode, Line 2677  ui_patblt(uint8 opcode,
2677    
2678          if (g_ownbackstore)          if (g_ownbackstore)
2679                  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);
2680            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2681                                    (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
2682                                     x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2683  }  }
2684    
2685  void  void
# Line 2292  ui_screenblt(uint8 opcode, Line 2690  ui_screenblt(uint8 opcode,
2690          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2691          if (g_ownbackstore)          if (g_ownbackstore)
2692          {          {
2693                  if (g_Unobscured)                  XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
2694                  {                            g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2695                          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);  
                 }  
2696          }          }
2697          else          else
2698          {          {
2699                  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);
2700          }          }
2701    
2702            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2703                                    (g_display, g_ownbackstore ? g_backstore : g_wnd,
2704                                     sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2705    
2706          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2707  }  }
2708    
# Line 2319  ui_memblt(uint8 opcode, Line 2713  ui_memblt(uint8 opcode,
2713  {  {
2714          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2715          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);
2716            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2717                                    (g_display, (Pixmap) src, sw->wnd, g_gc,
2718                                     srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2719          if (g_ownbackstore)          if (g_ownbackstore)
2720                  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);
2721          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2365  ui_line(uint8 opcode, Line 2762  ui_line(uint8 opcode,
2762          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2763          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2764          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2765            ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
2766                                                startx - sw->xoffset, starty - sw->yoffset,
2767                                                endx - sw->xoffset, endy - sw->yoffset));
2768          if (g_ownbackstore)          if (g_ownbackstore)
2769                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2770          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
# Line 2462  ui_polyline(uint8 opcode, Line 2862  ui_polyline(uint8 opcode,
2862          if (g_ownbackstore)          if (g_ownbackstore)
2863                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,                  XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2864                             CoordModePrevious);                             CoordModePrevious);
2865    
2866            ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
2867                                    (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2868    
2869          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2870  }  }
2871    
# Line 2682  ui_draw_text(uint8 font, uint8 flags, ui Line 3086  ui_draw_text(uint8 font, uint8 flags, ui
3086          if (g_ownbackstore)          if (g_ownbackstore)
3087          {          {
3088                  if (boxcx > 1)                  if (boxcx > 1)
3089                    {
3090                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
3091                                    boxy, boxcx, boxcy, boxx, boxy);                                    boxy, boxcx, boxcy, boxx, boxy);
3092                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3093                                                    (g_display, g_backstore, sw->wnd, g_gc,
3094                                                     boxx, boxy,
3095                                                     boxcx, boxcy,
3096                                                     boxx - sw->xoffset, boxy - sw->yoffset));
3097                    }
3098                  else                  else
3099                    {
3100                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,                          XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
3101                                    clipy, clipcx, clipcy, clipx, clipy);                                    clipy, clipcx, clipcy, clipx, clipy);
3102                            ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3103                                                    (g_display, g_backstore, sw->wnd, g_gc,
3104                                                     clipx, clipy,
3105                                                     clipcx, clipcy, clipx - sw->xoffset,
3106                                                     clipy - sw->yoffset));
3107                    }
3108          }          }
3109  }  }
3110    
# Line 2732  ui_desktop_restore(uint32 offset, int x, Line 3150  ui_desktop_restore(uint32 offset, int x,
3150          {          {
3151                  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);
3152                  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);
3153                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3154                                            (g_display, g_backstore, sw->wnd, g_gc,
3155                                             x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3156          }          }
3157          else          else
3158          {          {
3159                  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);
3160                    ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3161                                            (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
3162                                             x - sw->xoffset, y - sw->yoffset));
3163          }          }
3164    
3165          XFree(image);          XFree(image);
# Line 2751  void Line 3175  void
3175  ui_end_update(void)  ui_end_update(void)
3176  {  {
3177  }  }
3178    
3179    
3180    void
3181    ui_seamless_begin()
3182    {
3183            if (!g_seamless_rdp)
3184                    return;
3185    
3186            if (g_seamless_started)
3187                    return;
3188    
3189            g_seamless_started = True;
3190            ui_seamless_toggle();
3191    }
3192    
3193    
3194    void
3195    ui_seamless_toggle()
3196    {
3197            if (!g_seamless_rdp)
3198                    return;
3199    
3200            if (!g_seamless_started)
3201                    return;
3202    
3203            if (g_seamless_active)
3204            {
3205                    /* Deactivate */
3206                    while (g_seamless_windows)
3207                    {
3208                            XDestroyWindow(g_display, g_seamless_windows->wnd);
3209                            sw_remove_window(g_seamless_windows);
3210                    }
3211                    XMapWindow(g_display, g_wnd);
3212            }
3213            else
3214            {
3215                    /* Activate */
3216                    XUnmapWindow(g_display, g_wnd);
3217                    seamless_send_sync();
3218            }
3219    
3220            g_seamless_active = !g_seamless_active;
3221    }
3222    
3223    
3224    void
3225    ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3226    {
3227            Window wnd;
3228            XSetWindowAttributes attribs;
3229            XClassHint *classhints;
3230            XSizeHints *sizehints;
3231            long input_mask;
3232            seamless_window *sw, *sw_parent;
3233    
3234            if (!g_seamless_active)
3235                    return;
3236    
3237            /* Ignore CREATEs for existing windows */
3238            sw = sw_get_window_by_id(id);
3239            if (sw)
3240                    return;
3241    
3242            get_window_attribs(&attribs);
3243            attribs.override_redirect = False;
3244    
3245            wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3246                                InputOutput, g_visual,
3247                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3248                                CWBorderPixel, &attribs);
3249    
3250            XStoreName(g_display, wnd, "SeamlessRDP");
3251            ewmh_set_wm_name(wnd, "SeamlessRDP");
3252    
3253            mwm_hide_decorations(wnd);
3254    
3255            classhints = XAllocClassHint();
3256            if (classhints != NULL)
3257            {
3258                    classhints->res_name = "rdesktop";
3259                    classhints->res_class = "SeamlessRDP";
3260                    XSetClassHint(g_display, wnd, classhints);
3261                    XFree(classhints);
3262            }
3263    
3264            /* WM_NORMAL_HINTS */
3265            sizehints = XAllocSizeHints();
3266            if (sizehints != NULL)
3267            {
3268                    sizehints->flags = USPosition;
3269                    XSetWMNormalHints(g_display, wnd, sizehints);
3270                    XFree(sizehints);
3271            }
3272    
3273            /* Handle popups without parents through some ewm hints */
3274            if (parent == 0xFFFFFFFF)
3275                    ewmh_set_window_popup(wnd);
3276            /* Set WM_TRANSIENT_FOR, if necessary */
3277            else if (parent != 0x00000000)
3278            {
3279                    sw_parent = sw_get_window_by_id(parent);
3280                    if (sw_parent)
3281                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3282                    else
3283                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3284            }
3285    
3286    
3287            /* FIXME: Support for Input Context:s */
3288    
3289            get_input_mask(&input_mask);
3290            input_mask |= PropertyChangeMask;
3291    
3292            XSelectInput(g_display, wnd, input_mask);
3293    
3294            /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3295               seamless window, we could try to close the window on the
3296               serverside, instead of terminating rdesktop */
3297            XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3298    
3299            sw = xmalloc(sizeof(seamless_window));
3300            sw->wnd = wnd;
3301            sw->id = id;
3302            sw->behind = 0;
3303            sw->xoffset = 0;
3304            sw->yoffset = 0;
3305            sw->width = 0;
3306            sw->height = 0;
3307            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3308            sw->desktop = 0;
3309            sw->position_timer = xmalloc(sizeof(struct timeval));
3310            timerclear(sw->position_timer);
3311            sw->outstanding_position = False;
3312            sw->next = g_seamless_windows;
3313            g_seamless_windows = sw;
3314    }
3315    
3316    
3317    void
3318    ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3319    {
3320            seamless_window *sw;
3321    
3322            if (!g_seamless_active)
3323                    return;
3324    
3325            sw = sw_get_window_by_id(id);
3326            if (!sw)
3327            {
3328                    warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3329                    return;
3330            }
3331    
3332            XDestroyWindow(g_display, sw->wnd);
3333            sw_remove_window(sw);
3334    }
3335    
3336    
3337    void
3338    ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3339    {
3340            seamless_window *sw;
3341    
3342            if (!g_seamless_active)
3343                    return;
3344    
3345            sw = sw_get_window_by_id(id);
3346            if (!sw)
3347            {
3348                    warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3349                    return;
3350            }
3351    
3352            /* We ignore server updates until it has handled our request. */
3353            if (sw->outstanding_position)
3354                    return;
3355    
3356            if (!width || !height)
3357                    /* X11 windows must be at least 1x1 */
3358                    return;
3359    
3360            sw->xoffset = x;
3361            sw->yoffset = y;
3362            sw->width = width;
3363            sw->height = height;
3364    
3365            /* If we move the window in a maximized state, then KDE won't
3366               accept restoration */
3367            switch (sw->state)
3368            {
3369                    case SEAMLESSRDP_MINIMIZED:
3370                    case SEAMLESSRDP_MAXIMIZED:
3371                            return;
3372            }
3373    
3374            /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3375            XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3376    }
3377    
3378    
3379    void
3380    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3381    {
3382            seamless_window *sw;
3383    
3384            if (!g_seamless_active)
3385                    return;
3386    
3387            sw = sw_get_window_by_id(id);
3388            if (!sw)
3389            {
3390                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3391                    return;
3392            }
3393    
3394            if (behind)
3395            {
3396                    seamless_window *sw_behind;
3397                    Window wnds[2];
3398    
3399                    sw_behind = sw_get_window_by_id(behind);
3400                    if (!sw_behind)
3401                    {
3402                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3403                                    behind);
3404                            return;
3405                    }
3406    
3407                    wnds[1] = sw_behind->wnd;
3408                    wnds[0] = sw->wnd;
3409    
3410                    XRestackWindows(g_display, wnds, 2);
3411            }
3412            else
3413            {
3414                    XRaiseWindow(g_display, sw->wnd);
3415            }
3416    
3417            sw_restack_window(sw, behind);
3418    }
3419    
3420    
3421    void
3422    ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3423    {
3424            seamless_window *sw;
3425    
3426            if (!g_seamless_active)
3427                    return;
3428    
3429            sw = sw_get_window_by_id(id);
3430            if (!sw)
3431            {
3432                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3433                    return;
3434            }
3435    
3436            /* FIXME: Might want to convert the name for non-EWMH WMs */
3437            XStoreName(g_display, sw->wnd, title);
3438            ewmh_set_wm_name(sw->wnd, title);
3439    }
3440    
3441    
3442    void
3443    ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
3444    {
3445            seamless_window *sw;
3446    
3447            if (!g_seamless_active)
3448                    return;
3449    
3450            sw = sw_get_window_by_id(id);
3451            if (!sw)
3452            {
3453                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3454                    return;
3455            }
3456    
3457            switch (state)
3458            {
3459                    case SEAMLESSRDP_NORMAL:
3460                    case SEAMLESSRDP_MAXIMIZED:
3461                            ewmh_change_state(sw->wnd, state);
3462                            XMapWindow(g_display, sw->wnd);
3463                            break;
3464                    case SEAMLESSRDP_MINIMIZED:
3465                            /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3466                               the Window Manager should probably just ignore the request, since
3467                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3468                               such as minimization, rather than an independent state." Besides,
3469                               XIconifyWindow is easier. */
3470                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3471                            {
3472                                    XWMHints *hints;
3473                                    hints = XAllocWMHints();
3474                                    hints->flags = StateHint;
3475                                    hints->initial_state = IconicState;
3476                                    XSetWMHints(g_display, sw->wnd, hints);
3477                                    XFree(hints);
3478                                    XMapWindow(g_display, sw->wnd);
3479                            }
3480                            else
3481                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3482                            break;
3483                    default:
3484                            warning("SeamlessRDP: Invalid state %d\n", state);
3485                            break;
3486            }
3487    
3488            sw->state = state;
3489    }
3490    
3491    
3492    void
3493    ui_seamless_syncbegin(unsigned long flags)
3494    {
3495            if (!g_seamless_active)
3496                    return;
3497    
3498            /* Destroy all seamless windows */
3499            while (g_seamless_windows)
3500            {
3501                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3502                    sw_remove_window(g_seamless_windows);
3503            }
3504    }
3505    
3506    
3507    void
3508    ui_seamless_ack(unsigned int serial)
3509    {
3510            seamless_window *sw;
3511            for (sw = g_seamless_windows; sw; sw = sw->next)
3512            {
3513                    if (sw->outpos_serial == serial)
3514                    {
3515                            sw->xoffset = sw->outpos_xoffset;
3516                            sw->yoffset = sw->outpos_yoffset;
3517                            sw->width = sw->outpos_width;
3518                            sw->height = sw->outpos_height;
3519                            sw->outstanding_position = False;
3520                            break;
3521                    }
3522            }
3523    
3524            return;
3525    }

Legend:
Removed from v.1058  
changed lines
  Added in v.1170

  ViewVC Help
Powered by ViewVC 1.1.26