/[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 1166 by ossman_, Mon Mar 20 12:36:14 2006 UTC
# Line 54  typedef struct _seamless_window Line 54  typedef struct _seamless_window
54  {  {
55          Window wnd;          Window wnd;
56          unsigned long id;          unsigned long id;
57            unsigned long behind;
58          int xoffset, yoffset;          int xoffset, yoffset;
59          int width, height;          int width, height;
60          int state;              /* normal/minimized/maximized. */          int state;              /* normal/minimized/maximized. */
61          unsigned int desktop;          unsigned int desktop;
62            struct timeval *position_timer;
63          struct _seamless_window *next;          struct _seamless_window *next;
64  } seamless_window;  } seamless_window;
65  static seamless_window *g_seamless_windows = NULL;  static seamless_window *g_seamless_windows = NULL;
66    static unsigned long g_seamless_focused = 0;
67    static BOOL g_seamless_started = False; /* Server end is up and running */
68    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
69  extern BOOL g_seamless_rdp;  extern BOOL g_seamless_rdp;
70    
71  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
# Line 320  seamless_all_to_desktop(Window wnd, unsi Line 325  seamless_all_to_desktop(Window wnd, unsi
325  }  }
326    
327    
328    /* Send our position */
329    static void
330    seamless_update_position(seamless_window * sw)
331    {
332            XWindowAttributes wa;
333            int x, y;
334            Window child_return;
335    
336            XGetWindowAttributes(g_display, sw->wnd, &wa);
337            XTranslateCoordinates(g_display, sw->wnd, wa.root,
338                                  -wa.border_width, -wa.border_width, &x, &y, &child_return);
339    
340            seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
341            sw->xoffset = x;
342            sw->yoffset = y;
343            sw->width = wa.width;
344            sw->height = wa.height;
345    }
346    
347    
348    /* Check if it's time to send our position */
349    static void
350    seamless_check_timers()
351    {
352            seamless_window *sw;
353            struct timeval now;
354    
355            gettimeofday(&now, NULL);
356            for (sw = g_seamless_windows; sw; sw = sw->next)
357            {
358                    if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
359                    {
360                            timerclear(sw->position_timer);
361                            seamless_update_position(sw);
362                    }
363            }
364    }
365    
366    
367    static void
368    seamless_restack_window(seamless_window * sw, unsigned long behind)
369    {
370            seamless_window *sw_above;
371    
372            /* Remove window from stack */
373            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
374            {
375                    if (sw_above->behind == sw->id)
376                            break;
377            }
378    
379            if (sw_above)
380                    sw_above->behind = sw->behind;
381    
382            /* And then add it at the new position */
383    
384            for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
385            {
386                    if (sw_above->behind == behind)
387                            break;
388            }
389    
390            if (sw_above)
391                    sw_above->behind = sw->id;
392    
393            sw->behind = behind;
394    }
395    
396    
397  static void  static void
398  mwm_hide_decorations(Window wnd)  mwm_hide_decorations(Window wnd)
399  {  {
# Line 1564  ui_create_window(void) Line 1638  ui_create_window(void)
1638          }          }
1639    
1640          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1641          if (!g_seamless_rdp)  
1642            XMapWindow(g_display, g_wnd);
1643            /* wait for VisibilityNotify */
1644            do
1645          {          {
1646                  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;  
1647          }          }
1648            while (xevent.type != VisibilityNotify);
1649            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1650    
1651          g_focused = False;          g_focused = False;
1652          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1638  xwin_toggle_fullscreen(void) Line 1710  xwin_toggle_fullscreen(void)
1710  {  {
1711          Pixmap contents = 0;          Pixmap contents = 0;
1712    
1713          if (g_seamless_rdp)          if (g_seamless_active)
1714                  /* Turn off SeamlessRDP mode */                  /* Turn off SeamlessRDP mode */
1715                  ui_seamless_toggle();                  ui_seamless_toggle();
1716    
# Line 1743  handle_button_event(XEvent xevent, BOOL Line 1815  handle_button_event(XEvent xevent, BOOL
1815          }          }
1816  }  }
1817    
1818    static void
1819    ui_seamless_handle_restack(seamless_window * sw)
1820    {
1821            Status status;
1822            Window root, parent, *children;
1823            unsigned int nchildren, i;
1824            seamless_window *sw_below;
1825    
1826            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
1827                                &root, &parent, &children, &nchildren);
1828            if (!status || !nchildren)
1829                    return;
1830    
1831            sw_below = NULL;
1832    
1833            i = 0;
1834            while (children[i] != sw->wnd)
1835            {
1836                    i++;
1837                    if (i >= nchildren)
1838                            return;
1839            }
1840    
1841            for (i++; i < nchildren; i++)
1842            {
1843                    sw_below = seamless_get_window_by_wnd(children[i]);
1844                    if (sw_below)
1845                            break;
1846            }
1847    
1848            if (!sw_below && !sw->behind)
1849                    return;
1850            if (sw_below && (sw_below->id == sw->behind))
1851                    return;
1852    
1853            if (sw_below)
1854            {
1855                    seamless_send_zchange(sw->id, sw_below->id, 0);
1856                    seamless_restack_window(sw, sw_below->id);
1857            }
1858            else
1859            {
1860                    seamless_send_zchange(sw->id, 0, 0);
1861                    seamless_restack_window(sw, 0);
1862            }
1863    }
1864    
1865  /* Process events in Xlib queue  /* Process events in Xlib queue
1866     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1867  static int  static int
# Line 1875  xwin_process_events(void) Line 1994  xwin_process_events(void)
1994                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
1995                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
1996                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
1997    
1998                                    sw = seamless_get_window_by_wnd(xevent.xfocus.window);
1999                                    if (!sw)
2000                                            break;
2001    
2002                                    if (sw->id != g_seamless_focused)
2003                                    {
2004                                            seamless_send_focus(sw->id, 0);
2005                                            g_seamless_focused = sw->id;
2006                                    }
2007                                  break;                                  break;
2008    
2009                          case FocusOut:                          case FocusOut:
# Line 1987  xwin_process_events(void) Line 2116  xwin_process_events(void)
2116    
2117                                  break;                                  break;
2118                          case MapNotify:                          case MapNotify:
2119                                  if (!g_seamless_rdp)                                  if (!g_seamless_active)
2120                                          rdp_send_client_window_status(1);                                          rdp_send_client_window_status(1);
2121                                  break;                                  break;
2122                          case UnmapNotify:                          case UnmapNotify:
2123                                  if (!g_seamless_rdp)                                  if (!g_seamless_active)
2124                                          rdp_send_client_window_status(0);                                          rdp_send_client_window_status(0);
2125                                  break;                                  break;
2126                            case ConfigureNotify:
2127                                    if (!g_seamless_active)
2128                                            break;
2129    
2130                                    sw = seamless_get_window_by_wnd(xevent.xconfigure.window);
2131                                    if (!sw)
2132                                    {
2133                                            error("ConfigureNotify for unknown window 0x%lx\n",
2134                                                  xevent.xconfigure.window);
2135                                    }
2136    
2137                                    gettimeofday(sw->position_timer, NULL);
2138                                    if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2139                                        1000000)
2140                                    {
2141                                            sw->position_timer->tv_usec +=
2142                                                    SEAMLESSRDP_POSITION_TIMER - 1000000;
2143                                            sw->position_timer->tv_sec += 1;
2144                                    }
2145                                    else
2146                                    {
2147                                            sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2148                                    }
2149    
2150                                    ui_seamless_handle_restack(sw);
2151                                    break;
2152                  }                  }
2153          }          }
2154          /* Keep going */          /* Keep going */
# Line 2017  ui_select(int rdp_socket) Line 2172  ui_select(int rdp_socket)
2172                          /* User quit */                          /* User quit */
2173                          return 0;                          return 0;
2174    
2175                    if (g_seamless_active)
2176                            seamless_check_timers();
2177    
2178                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
2179                  FD_ZERO(&wfds);                  FD_ZERO(&wfds);
2180                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
# Line 2036  ui_select(int rdp_socket) Line 2194  ui_select(int rdp_socket)
2194    
2195                  /* add redirection handles */                  /* add redirection handles */
2196                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);                  rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
2197                    seamless_select_timeout(&tv);
2198    
2199                  n++;                  n++;
2200    
# Line 3005  ui_end_update(void) Line 3164  ui_end_update(void)
3164  }  }
3165    
3166  void  void
3167    ui_seamless_begin()
3168    {
3169            if (!g_seamless_rdp)
3170                    return;
3171    
3172            if (g_seamless_started)
3173                    return;
3174    
3175            g_seamless_started = True;
3176    
3177            ui_seamless_toggle();
3178    }
3179    
3180    void
3181  ui_seamless_toggle()  ui_seamless_toggle()
3182  {  {
3183          if (g_seamless_rdp)          if (!g_seamless_rdp)
3184                    return;
3185    
3186            if (!g_seamless_started)
3187                    return;
3188    
3189            if (g_seamless_active)
3190          {          {
3191                  /* Deactivate */                  /* Deactivate */
3192                  while (g_seamless_windows)                  while (g_seamless_windows)
# Line 3020  ui_seamless_toggle() Line 3199  ui_seamless_toggle()
3199          else          else
3200          {          {
3201                  /* 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;  
                 }  
   
3202                  XUnmapWindow(g_display, g_wnd);                  XUnmapWindow(g_display, g_wnd);
3203                  seamless_send_sync();                  seamless_send_sync();
3204          }          }
3205    
3206          g_seamless_rdp = !g_seamless_rdp;          g_seamless_active = !g_seamless_active;
3207  }  }
3208    
3209  void  void
# Line 3048  ui_seamless_create_window(unsigned long Line 3216  ui_seamless_create_window(unsigned long
3216          long input_mask;          long input_mask;
3217          seamless_window *sw, *sw_parent;          seamless_window *sw, *sw_parent;
3218    
3219            if (!g_seamless_active)
3220                    return;
3221    
3222          /* Ignore CREATEs for existing windows */          /* Ignore CREATEs for existing windows */
3223          sw = seamless_get_window_by_id(id);          sw = seamless_get_window_by_id(id);
3224          if (sw)          if (sw)
# Line 3110  ui_seamless_create_window(unsigned long Line 3281  ui_seamless_create_window(unsigned long
3281             serverside, instead of terminating rdesktop */             serverside, instead of terminating rdesktop */
3282          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3283    
3284          sw = malloc(sizeof(seamless_window));          sw = xmalloc(sizeof(seamless_window));
3285          sw->wnd = wnd;          sw->wnd = wnd;
3286          sw->id = id;          sw->id = id;
3287            sw->behind = 0;
3288          sw->xoffset = 0;          sw->xoffset = 0;
3289          sw->yoffset = 0;          sw->yoffset = 0;
3290          sw->width = 0;          sw->width = 0;
3291          sw->height = 0;          sw->height = 0;
3292          sw->state = SEAMLESSRDP_NOTYETMAPPED;          sw->state = SEAMLESSRDP_NOTYETMAPPED;
3293          sw->desktop = 0;          sw->desktop = 0;
3294            sw->position_timer = xmalloc(sizeof(struct timeval));
3295            timerclear(sw->position_timer);
3296          sw->next = g_seamless_windows;          sw->next = g_seamless_windows;
3297          g_seamless_windows = sw;          g_seamless_windows = sw;
3298  }  }
# Line 3129  ui_seamless_destroy_window(unsigned long Line 3303  ui_seamless_destroy_window(unsigned long
3303  {  {
3304          seamless_window *sw;          seamless_window *sw;
3305    
3306            if (!g_seamless_active)
3307                    return;
3308    
3309          sw = seamless_get_window_by_id(id);          sw = seamless_get_window_by_id(id);
3310          if (!sw)          if (!sw)
3311          {          {
# Line 3146  ui_seamless_move_window(unsigned long id Line 3323  ui_seamless_move_window(unsigned long id
3323  {  {
3324          seamless_window *sw;          seamless_window *sw;
3325    
3326            if (!g_seamless_active)
3327                    return;
3328    
3329          sw = seamless_get_window_by_id(id);          sw = seamless_get_window_by_id(id);
3330          if (!sw)          if (!sw)
3331          {          {
# Line 3157  ui_seamless_move_window(unsigned long id Line 3337  ui_seamless_move_window(unsigned long id
3337                  /* X11 windows must be at least 1x1 */                  /* X11 windows must be at least 1x1 */
3338                  return;                  return;
3339    
3340          /* About MAX and MIN: Windows allows moving a window outside          sw->xoffset = x;
3341             the desktop. This happens, for example, when maximizing an          sw->yoffset = y;
3342             application. In this case, the position is set to something          sw->width = width;
3343             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);  
3344    
3345          /* 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
3346             accept restoration */             accept restoration */
# Line 3181  ui_seamless_move_window(unsigned long id Line 3355  ui_seamless_move_window(unsigned long id
3355          XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);          XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3356  }  }
3357    
3358    void
3359    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3360    {
3361            seamless_window *sw;
3362    
3363            if (!g_seamless_active)
3364                    return;
3365    
3366            sw = seamless_get_window_by_id(id);
3367            if (!sw)
3368            {
3369                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3370                    return;
3371            }
3372    
3373            if (behind)
3374            {
3375                    seamless_window *sw_behind;
3376                    Window wnds[2];
3377    
3378                    sw_behind = seamless_get_window_by_id(behind);
3379                    if (!sw_behind)
3380                    {
3381                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3382                                    behind);
3383                            return;
3384                    }
3385    
3386                    wnds[1] = sw_behind->wnd;
3387                    wnds[0] = sw->wnd;
3388    
3389                    XRestackWindows(g_display, wnds, 2);
3390            }
3391            else
3392            {
3393                    XRaiseWindow(g_display, sw->wnd);
3394            }
3395    
3396            seamless_restack_window(sw, behind);
3397    }
3398    
3399  void  void
3400  ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)  ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3401  {  {
3402          seamless_window *sw;          seamless_window *sw;
3403    
3404            if (!g_seamless_active)
3405                    return;
3406    
3407          sw = seamless_get_window_by_id(id);          sw = seamless_get_window_by_id(id);
3408          if (!sw)          if (!sw)
3409          {          {
# Line 3205  ui_seamless_setstate(unsigned long id, u Line 3422  ui_seamless_setstate(unsigned long id, u
3422  {  {
3423          seamless_window *sw;          seamless_window *sw;
3424    
3425            if (!g_seamless_active)
3426                    return;
3427    
3428          sw = seamless_get_window_by_id(id);          sw = seamless_get_window_by_id(id);
3429          if (!sw)          if (!sw)
3430          {          {
# Line 3212  ui_seamless_setstate(unsigned long id, u Line 3432  ui_seamless_setstate(unsigned long id, u
3432                  return;                  return;
3433          }          }
3434    
         if (sw->state == SEAMLESSRDP_NOTYETMAPPED)  
         {  
                 XMapWindow(g_display, sw->wnd);  
         }  
   
         sw->state = state;  
   
3435          switch (state)          switch (state)
3436          {          {
3437                  case SEAMLESSRDP_NORMAL:                  case SEAMLESSRDP_NORMAL:
3438                  case SEAMLESSRDP_MAXIMIZED:                  case SEAMLESSRDP_MAXIMIZED:
3439                          ewmh_change_state(sw->wnd, state);                          ewmh_change_state(sw->wnd, state);
3440                            XMapWindow(g_display, sw->wnd);
3441                          break;                          break;
3442                  case SEAMLESSRDP_MINIMIZED:                  case SEAMLESSRDP_MINIMIZED:
3443                          /* 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 3445  ui_seamless_setstate(unsigned long id, u
3445                             _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
3446                             such as minimization, rather than an independent state." Besides,                             such as minimization, rather than an independent state." Besides,
3447                             XIconifyWindow is easier. */                             XIconifyWindow is easier. */
3448                          XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));                          if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3449                            {
3450                                    XWMHints *hints;
3451                                    hints = XAllocWMHints();
3452                                    hints->flags = StateHint;
3453                                    hints->initial_state = IconicState;
3454                                    XSetWMHints(g_display, sw->wnd, hints);
3455                                    XFree(hints);
3456                                    XMapWindow(g_display, sw->wnd);
3457                            }
3458                            else
3459                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3460                          break;                          break;
3461                  default:                  default:
3462                          warning("SeamlessRDP: Invalid state %d\n", state);                          warning("SeamlessRDP: Invalid state %d\n", state);
3463                          break;                          break;
3464          }          }
3465    
3466            sw->state = state;
3467  }  }
3468    
3469    
3470  void  void
3471  ui_seamless_syncbegin(unsigned long flags)  ui_seamless_syncbegin(unsigned long flags)
3472  {  {
3473            if (!g_seamless_active)
3474                    return;
3475    
3476          /* Destroy all seamless windows */          /* Destroy all seamless windows */
3477          while (g_seamless_windows)          while (g_seamless_windows)
3478          {          {
# Line 3250  ui_seamless_syncbegin(unsigned long flag Line 3480  ui_seamless_syncbegin(unsigned long flag
3480                  seamless_remove_window(g_seamless_windows);                  seamless_remove_window(g_seamless_windows);
3481          }          }
3482  }  }
3483    
3484    void
3485    ui_seamless_ack(unsigned int serial)
3486    {
3487    }

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

  ViewVC Help
Powered by ViewVC 1.1.26