/[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 1140 by ossman_, Wed Mar 15 15:27:24 2006 UTC revision 1193 by ossman_, Wed Mar 22 16:20:55 2006 UTC
# Line 28  Line 28 
28  #include "rdesktop.h"  #include "rdesktop.h"
29  #include "xproto.h"  #include "xproto.h"
30    
31    /* We can't include Xproto.h because of conflicting defines for BOOL */
32    #define X_ConfigureWindow              12
33    
34  extern int g_width;  extern int g_width;
35  extern int g_height;  extern int g_height;
36  extern int g_xpos;  extern int g_xpos;
# Line 50  static Screen *g_screen; Line 53  static Screen *g_screen;
53  Window g_wnd;  Window g_wnd;
54    
55  /* SeamlessRDP support */  /* SeamlessRDP support */
56    typedef struct _seamless_group
57    {
58            Window wnd;
59            unsigned long id;
60            unsigned int refcnt;
61    } seamless_group;
62  typedef struct _seamless_window  typedef struct _seamless_window
63  {  {
64          Window wnd;          Window wnd;
65          unsigned long id;          unsigned long id;
66            unsigned long behind;
67            seamless_group *group;
68          int xoffset, yoffset;          int xoffset, yoffset;
69          int width, height;          int width, height;
70          int state;              /* normal/minimized/maximized. */          int state;              /* normal/minimized/maximized. */
71          unsigned int desktop;          unsigned int desktop;
72            struct timeval *position_timer;
73    
74            BOOL outstanding_position;
75            unsigned int outpos_serial;
76            int outpos_xoffset, outpos_yoffset;
77            int outpos_width, outpos_height;
78    
79          struct _seamless_window *next;          struct _seamless_window *next;
80  } seamless_window;  } seamless_window;
81  static seamless_window *g_seamless_windows = NULL;  static seamless_window *g_seamless_windows = NULL;
82    static unsigned long g_seamless_focused = 0;
83    static BOOL g_seamless_started = False; /* Server end is up and running */
84    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
85    static BOOL g_seamless_hidden = False;  /* Desktop is hidden on server */
86  extern BOOL g_seamless_rdp;  extern BOOL g_seamless_rdp;
87    
88  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
# Line 259  static int rop2_map[] = { Line 281  static int rop2_map[] = {
281  #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); }
282    
283  static seamless_window *  static seamless_window *
284  seamless_get_window_by_id(unsigned long id)  sw_get_window_by_id(unsigned long id)
285  {  {
286          seamless_window *sw;          seamless_window *sw;
287          for (sw = g_seamless_windows; sw; sw = sw->next)          for (sw = g_seamless_windows; sw; sw = sw->next)
# Line 272  seamless_get_window_by_id(unsigned long Line 294  seamless_get_window_by_id(unsigned long
294    
295    
296  static seamless_window *  static seamless_window *
297  seamless_get_window_by_wnd(Window wnd)  sw_get_window_by_wnd(Window wnd)
298  {  {
299          seamless_window *sw;          seamless_window *sw;
300          for (sw = g_seamless_windows; sw; sw = sw->next)          for (sw = g_seamless_windows; sw; sw = sw->next)
# Line 285  seamless_get_window_by_wnd(Window wnd) Line 307  seamless_get_window_by_wnd(Window wnd)
307    
308    
309  static void  static void
310  seamless_remove_window(seamless_window * win)  sw_remove_window(seamless_window * win)
311  {  {
312          seamless_window *sw, **prevnext = &g_seamless_windows;          seamless_window *sw, **prevnext = &g_seamless_windows;
313          for (sw = g_seamless_windows; sw; sw = sw->next)          for (sw = g_seamless_windows; sw; sw = sw->next)
# Line 293  seamless_remove_window(seamless_window * Line 315  seamless_remove_window(seamless_window *
315                  if (sw == win)                  if (sw == win)
316                  {                  {
317                          *prevnext = sw->next;                          *prevnext = sw->next;
318                            sw->group->refcnt--;
319                            if (sw->group->refcnt == 0)
320                            {
321                                    XDestroyWindow(g_display, sw->group->wnd);
322                                    xfree(sw->group);
323                            }
324                            xfree(sw->position_timer);
325                          xfree(sw);                          xfree(sw);
326                          return;                          return;
327                  }                  }
# Line 304  seamless_remove_window(seamless_window * Line 333  seamless_remove_window(seamless_window *
333    
334  /* Move all windows except wnd to new desktop */  /* Move all windows except wnd to new desktop */
335  static void  static void
336  seamless_all_to_desktop(Window wnd, unsigned int desktop)  sw_all_to_desktop(Window wnd, unsigned int desktop)
337  {  {
338          seamless_window *sw;          seamless_window *sw;
339          for (sw = g_seamless_windows; sw; sw = sw->next)          for (sw = g_seamless_windows; sw; sw = sw->next)
# Line 320  seamless_all_to_desktop(Window wnd, unsi Line 349  seamless_all_to_desktop(Window wnd, unsi
349  }  }
350    
351    
352    /* Send our position */
353    static void
354    sw_update_position(seamless_window * sw)
355    {
356            XWindowAttributes wa;
357            int x, y;
358            Window child_return;
359            unsigned int serial;
360    
361            XGetWindowAttributes(g_display, sw->wnd, &wa);
362            XTranslateCoordinates(g_display, sw->wnd, wa.root,
363                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
364    
365            serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
366    
367            sw->outstanding_position = True;
368            sw->outpos_serial = serial;
369    
370            sw->outpos_xoffset = x;
371            sw->outpos_yoffset = y;
372            sw->outpos_width = wa.width;
373            sw->outpos_height = wa.height;
374    }
375    
376    
377    /* Check if it's time to send our position */
378    static void
379    sw_check_timers()
380    {
381            seamless_window *sw;
382            struct timeval now;
383    
384            gettimeofday(&now, NULL);
385            for (sw = g_seamless_windows; sw; sw = sw->next)
386            {
387                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
388                    {
389                            timerclear(sw->position_timer);
390                            sw_update_position(sw);
391                    }
392            }
393    }
394    
395    
396    static void
397    sw_restack_window(seamless_window * sw, unsigned long behind)
398    {
399            seamless_window *sw_above;
400    
401            /* Remove window from stack */
402            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
403            {
404                    if (sw_above->behind == sw->id)
405                            break;
406            }
407    
408            if (sw_above)
409                    sw_above->behind = sw->behind;
410    
411            /* And then add it at the new position */
412    
413            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
414            {
415                    if (sw_above->behind == behind)
416                            break;
417            }
418    
419            if (sw_above)
420                    sw_above->behind = sw->id;
421    
422            sw->behind = behind;
423    }
424    
425    
426    static void
427    sw_handle_restack(seamless_window * sw)
428    {
429            Status status;
430            Window root, parent, *children;
431            unsigned int nchildren, i;
432            seamless_window *sw_below;
433    
434            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
435                                &root, &parent, &children, &nchildren);
436            if (!status || !nchildren)
437                    return;
438    
439            sw_below = NULL;
440    
441            i = 0;
442            while (children[i] != sw->wnd)
443            {
444                    i++;
445                    if (i >= nchildren)
446                            goto end;
447            }
448    
449            for (i++; i < nchildren; i++)
450            {
451                    sw_below = sw_get_window_by_wnd(children[i]);
452                    if (sw_below)
453                            break;
454            }
455    
456            if (!sw_below && !sw->behind)
457                    goto end;
458            if (sw_below && (sw_below->id == sw->behind))
459                    goto end;
460    
461            if (sw_below)
462            {
463                    seamless_send_zchange(sw->id, sw_below->id, 0);
464                    sw_restack_window(sw, sw_below->id);
465            }
466            else
467            {
468                    seamless_send_zchange(sw->id, 0, 0);
469                    sw_restack_window(sw, 0);
470            }
471    
472          end:
473            XFree(children);
474    }
475    
476    
477    static seamless_group *
478    sw_find_group(unsigned long id, BOOL dont_create)
479    {
480            seamless_window *sw;
481            seamless_group *sg;
482            XSetWindowAttributes attribs;
483    
484            for (sw = g_seamless_windows; sw; sw = sw->next)
485            {
486                    if (sw->group->id == id)
487                            return sw->group;
488            }
489    
490            if (dont_create)
491                    return NULL;
492    
493            sg = xmalloc(sizeof(seamless_group));
494    
495            sg->wnd =
496                    XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0,
497                                  CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
498    
499            sg->id = id;
500            sg->refcnt = 0;
501    
502            return sg;
503    }
504    
505    
506  static void  static void
507  mwm_hide_decorations(Window wnd)  mwm_hide_decorations(Window wnd)
508  {  {
# Line 1317  select_visual() Line 1500  select_visual()
1500          return True;          return True;
1501  }  }
1502    
1503    static XErrorHandler g_old_error_handler;
1504    
1505    static int
1506    error_handler(Display * dpy, XErrorEvent * eev)
1507    {
1508            if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1509            {
1510                    fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1511                    fprintf(stderr,
1512                            "This is most likely caused by a broken window manager (commonly KWin).\n");
1513                    return 0;
1514            }
1515    
1516            return g_old_error_handler(dpy, eev);
1517    }
1518    
1519  BOOL  BOOL
1520  ui_init(void)  ui_init(void)
1521  {  {
# Line 1334  ui_init(void) Line 1533  ui_init(void)
1533                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1534          }          }
1535    
1536            g_old_error_handler = XSetErrorHandler(error_handler);
1537    
1538          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1539          screen_num = DefaultScreen(g_display);          screen_num = DefaultScreen(g_display);
1540          g_x_socket = ConnectionNumber(g_display);          g_x_socket = ConnectionNumber(g_display);
# Line 1430  ui_init(void) Line 1631  ui_init(void)
1631  void  void
1632  ui_deinit(void)  ui_deinit(void)
1633  {  {
1634            while (g_seamless_windows)
1635            {
1636                    XDestroyWindow(g_display, g_seamless_windows->wnd);
1637                    sw_remove_window(g_seamless_windows);
1638            }
1639    
1640          if (g_IM != NULL)          if (g_IM != NULL)
1641                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1642    
# Line 1564  ui_create_window(void) Line 1771  ui_create_window(void)
1771          }          }
1772    
1773          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1774          if (!g_seamless_rdp)  
1775            XMapWindow(g_display, g_wnd);
1776            /* wait for VisibilityNotify */
1777            do
1778          {          {
1779                  XMapWindow(g_display, g_wnd);                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
                 /* wait for VisibilityNotify */  
                 do  
                 {  
                         XMaskEvent(g_display, VisibilityChangeMask, &xevent);  
                 }  
                 while (xevent.type != VisibilityNotify);  
                 g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;  
1780          }          }
1781            while (xevent.type != VisibilityNotify);
1782            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1783    
1784          g_focused = False;          g_focused = False;
1785          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1638  xwin_toggle_fullscreen(void) Line 1843  xwin_toggle_fullscreen(void)
1843  {  {
1844          Pixmap contents = 0;          Pixmap contents = 0;
1845    
1846          if (g_seamless_rdp)          if (g_seamless_active)
1847                  /* Turn off SeamlessRDP mode */                  /* Turn off SeamlessRDP mode */
1848                  ui_seamless_toggle();                  ui_seamless_toggle();
1849    
# Line 1743  handle_button_event(XEvent xevent, BOOL Line 1948  handle_button_event(XEvent xevent, BOOL
1948          }          }
1949  }  }
1950    
1951    
1952  /* Process events in Xlib queue  /* Process events in Xlib queue
1953     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1954  static int  static int
# Line 1875  xwin_process_events(void) Line 2081  xwin_process_events(void)
2081                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
2082                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
2083                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
2084    
2085                                    sw = sw_get_window_by_wnd(xevent.xfocus.window);
2086                                    if (!sw)
2087                                            break;
2088    
2089                                    if (sw->id != g_seamless_focused)
2090                                    {
2091                                            seamless_send_focus(sw->id, 0);
2092                                            g_seamless_focused = sw->id;
2093                                    }
2094                                  break;                                  break;
2095    
2096                          case FocusOut:                          case FocusOut:
# Line 1917  xwin_process_events(void) Line 2133  xwin_process_events(void)
2133                                  }                                  }
2134                                  else                                  else
2135                                  {                                  {
2136                                          sw = seamless_get_window_by_wnd(xevent.xexpose.window);                                          sw = sw_get_window_by_wnd(xevent.xexpose.window);
2137                                          if (sw)                                          if (!sw)
2138                                                  XCopyArea(g_display, g_backstore,                                                  break;
2139                                                            xevent.xexpose.window, g_gc,                                          XCopyArea(g_display, g_backstore,
2140                                                            xevent.xexpose.x + sw->xoffset,                                                    xevent.xexpose.window, g_gc,
2141                                                            xevent.xexpose.y + sw->yoffset,                                                    xevent.xexpose.x + sw->xoffset,
2142                                                            xevent.xexpose.width,                                                    xevent.xexpose.y + sw->yoffset,
2143                                                            xevent.xexpose.height, xevent.xexpose.x,                                                    xevent.xexpose.width,
2144                                                            xevent.xexpose.y);                                                    xevent.xexpose.height, xevent.xexpose.x,
2145                                          else                                                    xevent.xexpose.y);
                                         {  
                                                 error("Expose for unknown window 0x%lx\n",  
                                                       xevent.xexpose.window);  
                                         }  
2146                                  }                                  }
2147    
2148                                  break;                                  break;
# Line 1967  xwin_process_events(void) Line 2179  xwin_process_events(void)
2179                                          break;                                          break;
2180    
2181                                  /* seamless */                                  /* seamless */
2182                                  sw = seamless_get_window_by_wnd(xevent.xproperty.window);                                  sw = sw_get_window_by_wnd(xevent.xproperty.window);
2183                                  if (!sw)                                  if (!sw)
2184                                          break;                                          break;
2185    
# Line 1982  xwin_process_events(void) Line 2194  xwin_process_events(void)
2194                                      && (xevent.xproperty.state == PropertyNewValue))                                      && (xevent.xproperty.state == PropertyNewValue))
2195                                  {                                  {
2196                                          sw->desktop = ewmh_get_window_desktop(sw->wnd);                                          sw->desktop = ewmh_get_window_desktop(sw->wnd);
2197                                          seamless_all_to_desktop(sw->wnd, sw->desktop);                                          sw_all_to_desktop(sw->wnd, sw->desktop);
2198                                  }                                  }
2199    
2200                                  break;                                  break;
2201                          case MapNotify:                          case MapNotify:
2202                                  if (!g_seamless_rdp)                                  if (!g_seamless_active)
2203                                          rdp_send_client_window_status(1);                                          rdp_send_client_window_status(1);
2204                                  break;                                  break;
2205                          case UnmapNotify:                          case UnmapNotify:
2206                                  if (!g_seamless_rdp)                                  if (!g_seamless_active)
2207                                          rdp_send_client_window_status(0);                                          rdp_send_client_window_status(0);
2208                                  break;                                  break;
2209                            case ConfigureNotify:
2210                                    if (!g_seamless_active)
2211                                            break;
2212    
2213                                    sw = sw_get_window_by_wnd(xevent.xconfigure.window);
2214                                    if (!sw)
2215                                            break;
2216    
2217                                    gettimeofday(sw->position_timer, NULL);
2218                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2219                                        1000000)
2220                                    {
2221                                            sw->position_timer->tv_usec +=
2222                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2223                                            sw->position_timer->tv_sec += 1;
2224                                    }
2225                                    else
2226                                    {
2227                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2228                                    }
2229    
2230                                    sw_handle_restack(sw);
2231                                    break;
2232                  }                  }
2233          }          }
2234          /* Keep going */          /* Keep going */
# Line 2017  ui_select(int rdp_socket) Line 2252  ui_select(int rdp_socket)
2252                          /* User quit */                          /* User quit */
2253                          return 0;                          return 0;
2254    
2255                    if (g_seamless_active)
2256                            sw_check_timers();
2257    
2258                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2259                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2260                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
# Line 2036  ui_select(int rdp_socket) Line 2274  ui_select(int rdp_socket)
2274    
2275                  /* add redirection handles */                  /* add redirection handles */
2276                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2277                    seamless_select_timeout(&tv);
2278    
2279                  n++;                  n++;
2280    
# Line 3004  ui_end_update(void) Line 3243  ui_end_update(void)
3243  {  {
3244  }  }
3245    
3246    
3247    void
3248    ui_seamless_begin(BOOL hidden)
3249    {
3250            if (!g_seamless_rdp)
3251                    return;
3252    
3253            if (g_seamless_started)
3254                    return;
3255    
3256            g_seamless_started = True;
3257            g_seamless_hidden = hidden;
3258    
3259            if (!hidden)
3260                    ui_seamless_toggle();
3261    }
3262    
3263    
3264    void
3265    ui_seamless_hide_desktop()
3266    {
3267            if (!g_seamless_rdp)
3268                    return;
3269    
3270            if (!g_seamless_started)
3271                    return;
3272    
3273            if (g_seamless_active)
3274                    ui_seamless_toggle();
3275    
3276            g_seamless_hidden = True;
3277    }
3278    
3279    
3280    void
3281    ui_seamless_unhide_desktop()
3282    {
3283            if (!g_seamless_rdp)
3284                    return;
3285    
3286            if (!g_seamless_started)
3287                    return;
3288    
3289            g_seamless_hidden = False;
3290    
3291            ui_seamless_toggle();
3292    }
3293    
3294    
3295  void  void
3296  ui_seamless_toggle()  ui_seamless_toggle()
3297  {  {
3298          if (g_seamless_rdp)          if (!g_seamless_rdp)
3299                    return;
3300    
3301            if (!g_seamless_started)
3302                    return;
3303    
3304            if (g_seamless_hidden)
3305                    return;
3306    
3307            if (g_seamless_active)
3308          {          {
3309                  /* Deactivate */                  /* Deactivate */
3310                  while (g_seamless_windows)                  while (g_seamless_windows)
3311                  {                  {
3312                          XDestroyWindow(g_display, g_seamless_windows->wnd);                          XDestroyWindow(g_display, g_seamless_windows->wnd);
3313                          seamless_remove_window(g_seamless_windows);                          sw_remove_window(g_seamless_windows);
3314                  }                  }
3315                  XMapWindow(g_display, g_wnd);                  XMapWindow(g_display, g_wnd);
3316          }          }
3317          else          else
3318          {          {
3319                  /* Activate */                  /* Activate */
                 if (g_win_button_size)  
                 {  
                         error("SeamlessRDP mode cannot be activated when using single application mode\n");  
                         return;  
                 }  
                 if (!g_using_full_workarea)  
                 {  
                         error("SeamlessRDP mode requires a session that covers the whole screen");  
                         return;  
                 }  
   
3320                  XUnmapWindow(g_display, g_wnd);                  XUnmapWindow(g_display, g_wnd);
3321                  seamless_send_sync();                  seamless_send_sync();
3322          }          }
3323    
3324          g_seamless_rdp = !g_seamless_rdp;          g_seamless_active = !g_seamless_active;
3325  }  }
3326    
3327    
3328  void  void
3329  ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)  ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
3330                              unsigned long flags)
3331  {  {
3332          Window wnd;          Window wnd;
3333          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
3334          XClassHint *classhints;          XClassHint *classhints;
3335          XSizeHints *sizehints;          XSizeHints *sizehints;
3336            XWMHints *wmhints;
3337          long input_mask;          long input_mask;
3338          seamless_window *sw, *sw_parent;          seamless_window *sw, *sw_parent;
3339    
3340            if (!g_seamless_active)
3341                    return;
3342    
3343          /* Ignore CREATEs for existing windows */          /* Ignore CREATEs for existing windows */
3344          sw = seamless_get_window_by_id(id);          sw = sw_get_window_by_id(id);
3345          if (sw)          if (sw)
3346                  return;                  return;
3347    
3348          get_window_attribs(&attribs);          get_window_attribs(&attribs);
         attribs.override_redirect = False;  
   
3349          wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,          wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
3350                              InputOutput, g_visual,                              InputOutput, g_visual,
3351                              CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |                              CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
                             CWBorderPixel, &attribs);  
3352    
3353          XStoreName(g_display, wnd, "SeamlessRDP");          XStoreName(g_display, wnd, "SeamlessRDP");
3354          ewmh_set_wm_name(wnd, "SeamlessRDP");          ewmh_set_wm_name(wnd, "SeamlessRDP");
# Line 3084  ui_seamless_create_window(unsigned long Line 3373  ui_seamless_create_window(unsigned long
3373                  XFree(sizehints);                  XFree(sizehints);
3374          }          }
3375    
3376          /* Handle popups without parents through some ewm hints */          /* Parent-less transient windows */
3377          if (parent == 0xFFFFFFFF)          if (parent == 0xFFFFFFFF)
3378            {
3379                    XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3380                    /* Some buggy wm:s (kwin) do not handle the above, so fake it
3381                       using some other hints. */
3382                  ewmh_set_window_popup(wnd);                  ewmh_set_window_popup(wnd);
3383          /* Set WM_TRANSIENT_FOR, if necessary */          }
3384            /* Normal transient windows */
3385          else if (parent != 0x00000000)          else if (parent != 0x00000000)
3386          {          {
3387                  sw_parent = seamless_get_window_by_id(parent);                  sw_parent = sw_get_window_by_id(parent);
3388                  if (sw_parent)                  if (sw_parent)
3389                          XSetTransientForHint(g_display, wnd, sw_parent->wnd);                          XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3390                  else                  else
3391                          warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);                          warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3392          }          }
3393    
3394            if (flags & SEAMLESSRDP_CREATE_MODAL)
3395            {
3396                    /* We do this to support buggy wm:s (*cough* metacity *cough*)
3397                       somewhat at least */
3398                    if (parent == 0x00000000)
3399                            XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
3400                    ewmh_set_window_modal(wnd);
3401            }
3402    
3403          /* FIXME: Support for Input Context:s */          /* FIXME: Support for Input Context:s */
3404    
# Line 3110  ui_seamless_create_window(unsigned long Line 3412  ui_seamless_create_window(unsigned long
3412             serverside, instead of terminating rdesktop */             serverside, instead of terminating rdesktop */
3413          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3414    
3415          sw = malloc(sizeof(seamless_window));          sw = xmalloc(sizeof(seamless_window));
3416          sw->wnd = wnd;          sw->wnd = wnd;
3417          sw->id = id;          sw->id = id;
3418            sw->behind = 0;
3419            sw->group = sw_find_group(group, False);
3420            sw->group->refcnt++;
3421          sw->xoffset = 0;          sw->xoffset = 0;
3422          sw->yoffset = 0;          sw->yoffset = 0;
3423          sw->width = 0;          sw->width = 0;
3424          sw->height = 0;          sw->height = 0;
3425          sw->state = SEAMLESSRDP_NOTYETMAPPED;          sw->state = SEAMLESSRDP_NOTYETMAPPED;
3426          sw->desktop = 0;          sw->desktop = 0;
3427            sw->position_timer = xmalloc(sizeof(struct timeval));
3428            timerclear(sw->position_timer);
3429    
3430            sw->outstanding_position = False;
3431            sw->outpos_serial = 0;
3432            sw->outpos_xoffset = sw->outpos_yoffset = 0;
3433            sw->outpos_width = sw->outpos_height = 0;
3434    
3435          sw->next = g_seamless_windows;          sw->next = g_seamless_windows;
3436          g_seamless_windows = sw;          g_seamless_windows = sw;
3437    
3438            /* WM_HINTS */
3439            wmhints = XAllocWMHints();
3440            if (wmhints)
3441            {
3442                    wmhints->flags = WindowGroupHint;
3443                    wmhints->window_group = sw->group->wnd;
3444                    XSetWMHints(g_display, sw->wnd, wmhints);
3445                    XFree(wmhints);
3446            }
3447  }  }
3448    
3449    
# Line 3129  ui_seamless_destroy_window(unsigned long Line 3452  ui_seamless_destroy_window(unsigned long
3452  {  {
3453          seamless_window *sw;          seamless_window *sw;
3454    
3455          sw = seamless_get_window_by_id(id);          if (!g_seamless_active)
3456                    return;
3457    
3458            sw = sw_get_window_by_id(id);
3459          if (!sw)          if (!sw)
3460          {          {
3461                  warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);                  warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
# Line 3137  ui_seamless_destroy_window(unsigned long Line 3463  ui_seamless_destroy_window(unsigned long
3463          }          }
3464    
3465          XDestroyWindow(g_display, sw->wnd);          XDestroyWindow(g_display, sw->wnd);
3466          seamless_remove_window(sw);          sw_remove_window(sw);
3467  }  }
3468    
3469    
# Line 3146  ui_seamless_move_window(unsigned long id Line 3472  ui_seamless_move_window(unsigned long id
3472  {  {
3473          seamless_window *sw;          seamless_window *sw;
3474    
3475          sw = seamless_get_window_by_id(id);          if (!g_seamless_active)
3476                    return;
3477    
3478            sw = sw_get_window_by_id(id);
3479          if (!sw)          if (!sw)
3480          {          {
3481                  warning("ui_seamless_move_window: No information for window 0x%lx\n", id);                  warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3482                  return;                  return;
3483          }          }
3484    
3485            /* We ignore server updates until it has handled our request. */
3486            if (sw->outstanding_position)
3487                    return;
3488    
3489          if (!width || !height)          if (!width || !height)
3490                  /* X11 windows must be at least 1x1 */                  /* X11 windows must be at least 1x1 */
3491                  return;                  return;
3492    
3493          /* About MAX and MIN: Windows allows moving a window outside          sw->xoffset = x;
3494             the desktop. This happens, for example, when maximizing an          sw->yoffset = y;
3495             application. In this case, the position is set to something          sw->width = width;
3496             like -4,-4,1288,1032. Many WMs does not allow windows          sw->height = height;
            outside the desktop, however. Therefore, clip the window  
            ourselves. */  
         sw->xoffset = MAX(0, x);  
         sw->yoffset = MAX(0, y);  
         sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);  
         sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);  
3497    
3498          /* If we move the window in a maximized state, then KDE won't          /* If we move the window in a maximized state, then KDE won't
3499             accept restoration */             accept restoration */
# Line 3183  ui_seamless_move_window(unsigned long id Line 3510  ui_seamless_move_window(unsigned long id
3510    
3511    
3512  void  void
3513    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3514    {
3515            seamless_window *sw;
3516    
3517            if (!g_seamless_active)
3518                    return;
3519    
3520            sw = sw_get_window_by_id(id);
3521            if (!sw)
3522            {
3523                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3524                    return;
3525            }
3526    
3527            if (behind)
3528            {
3529                    seamless_window *sw_behind;
3530                    Window wnds[2];
3531    
3532                    sw_behind = sw_get_window_by_id(behind);
3533                    if (!sw_behind)
3534                    {
3535                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3536                                    behind);
3537                            return;
3538                    }
3539    
3540                    wnds[1] = sw_behind->wnd;
3541                    wnds[0] = sw->wnd;
3542    
3543                    XRestackWindows(g_display, wnds, 2);
3544            }
3545            else
3546            {
3547                    XRaiseWindow(g_display, sw->wnd);
3548            }
3549    
3550            sw_restack_window(sw, behind);
3551    }
3552    
3553    
3554    void
3555  ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)  ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3556  {  {
3557          seamless_window *sw;          seamless_window *sw;
3558    
3559          sw = seamless_get_window_by_id(id);          if (!g_seamless_active)
3560                    return;
3561    
3562            sw = sw_get_window_by_id(id);
3563          if (!sw)          if (!sw)
3564          {          {
3565                  warning("ui_seamless_settitle: No information for window 0x%lx\n", id);                  warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
# Line 3205  ui_seamless_setstate(unsigned long id, u Line 3577  ui_seamless_setstate(unsigned long id, u
3577  {  {
3578          seamless_window *sw;          seamless_window *sw;
3579    
3580          sw = seamless_get_window_by_id(id);          if (!g_seamless_active)
3581                    return;
3582    
3583            sw = sw_get_window_by_id(id);
3584          if (!sw)          if (!sw)
3585          {          {
3586                  warning("ui_seamless_setstate: No information for window 0x%lx\n", id);                  warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3587                  return;                  return;
3588          }          }
3589    
         if (sw->state == SEAMLESSRDP_NOTYETMAPPED)  
         {  
                 XMapWindow(g_display, sw->wnd);  
         }  
   
         sw->state = state;  
   
3590          switch (state)          switch (state)
3591          {          {
3592                  case SEAMLESSRDP_NORMAL:                  case SEAMLESSRDP_NORMAL:
3593                  case SEAMLESSRDP_MAXIMIZED:                  case SEAMLESSRDP_MAXIMIZED:
3594                          ewmh_change_state(sw->wnd, state);                          ewmh_change_state(sw->wnd, state);
3595                            XMapWindow(g_display, sw->wnd);
3596                          break;                          break;
3597                  case SEAMLESSRDP_MINIMIZED:                  case SEAMLESSRDP_MINIMIZED:
3598                          /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN                          /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
# Line 3231  ui_seamless_setstate(unsigned long id, u Line 3600  ui_seamless_setstate(unsigned long id, u
3600                             _NET_WM_STATE_HIDDEN is a function of some other aspect of the window                             _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3601                             such as minimization, rather than an independent state." Besides,                             such as minimization, rather than an independent state." Besides,
3602                             XIconifyWindow is easier. */                             XIconifyWindow is easier. */
3603                          XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));                          if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3604                            {
3605                                    XWMHints *hints;
3606                                    hints = XGetWMHints(g_display, sw->wnd);
3607                                    if (hints)
3608                                    {
3609                                            hints->flags |= StateHint;
3610                                            hints->initial_state = IconicState;
3611                                            XSetWMHints(g_display, sw->wnd, hints);
3612                                            XFree(hints);
3613                                    }
3614                                    XMapWindow(g_display, sw->wnd);
3615                            }
3616                            else
3617                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3618                          break;                          break;
3619                  default:                  default:
3620                          warning("SeamlessRDP: Invalid state %d\n", state);                          warning("SeamlessRDP: Invalid state %d\n", state);
3621                          break;                          break;
3622          }          }
3623    
3624            sw->state = state;
3625  }  }
3626    
3627    
3628  void  void
3629  ui_seamless_syncbegin(unsigned long flags)  ui_seamless_syncbegin(unsigned long flags)
3630  {  {
3631            if (!g_seamless_active)
3632                    return;
3633    
3634          /* Destroy all seamless windows */          /* Destroy all seamless windows */
3635          while (g_seamless_windows)          while (g_seamless_windows)
3636          {          {
3637                  XDestroyWindow(g_display, g_seamless_windows->wnd);                  XDestroyWindow(g_display, g_seamless_windows->wnd);
3638                  seamless_remove_window(g_seamless_windows);                  sw_remove_window(g_seamless_windows);
3639            }
3640    }
3641    
3642    
3643    void
3644    ui_seamless_ack(unsigned int serial)
3645    {
3646            seamless_window *sw;
3647            for (sw = g_seamless_windows; sw; sw = sw->next)
3648            {
3649                    if (sw->outstanding_position && (sw->outpos_serial == serial))
3650                    {
3651                            sw->xoffset = sw->outpos_xoffset;
3652                            sw->yoffset = sw->outpos_yoffset;
3653                            sw->width = sw->outpos_width;
3654                            sw->height = sw->outpos_height;
3655                            sw->outstanding_position = False;
3656    
3657                            /* Do a complete redraw of the window as part of the
3658                               completion of the move. This is to remove any
3659                               artifacts caused by our lack of synchronization. */
3660                            XCopyArea(g_display, g_backstore,
3661                                      sw->wnd, g_gc,
3662                                      sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3663    
3664                            break;
3665                    }
3666          }          }
3667  }  }

Legend:
Removed from v.1140  
changed lines
  Added in v.1193

  ViewVC Help
Powered by ViewVC 1.1.26