/[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 1089 by astrand, Fri Mar 10 08:50:43 2006 UTC revision 1151 by ossman_, Fri Mar 17 08:52:29 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 parent;
58          int xoffset, yoffset;          int xoffset, yoffset;
59          int width, height;          int width, height;
60            int state;              /* normal/minimized/maximized. */
61            unsigned int desktop;
62          struct _seamless_window *next;          struct _seamless_window *next;
63  } seamless_window;  } seamless_window;
64  static seamless_window *g_seamless_windows = NULL;  static seamless_window *g_seamless_windows = NULL;
65    static BOOL g_seamless_started = False; /* Server end is up and running */
66    static BOOL g_seamless_active = False;  /* We are currently in seamless mode */
67  extern BOOL g_seamless_rdp;  extern BOOL g_seamless_rdp;
68    
69  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
# Line 83  static XModifierKeymap *g_mod_map; Line 88  static XModifierKeymap *g_mod_map;
88  static Cursor g_current_cursor;  static Cursor g_current_cursor;
89  static HCURSOR g_null_cursor = NULL;  static HCURSOR g_null_cursor = NULL;
90  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
91    extern Atom g_net_wm_state_atom;
92    extern Atom g_net_wm_desktop_atom;
93  static BOOL g_focused;  static BOOL g_focused;
94  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
95  /* Indicates that:  /* Indicates that:
# Line 298  seamless_remove_window(seamless_window * Line 305  seamless_remove_window(seamless_window *
305  }  }
306    
307    
308    /* Move all windows except wnd to new desktop */
309    static void
310    seamless_all_to_desktop(Window wnd, unsigned int desktop)
311    {
312            seamless_window *sw;
313            for (sw = g_seamless_windows; sw; sw = sw->next)
314            {
315                    if (sw->wnd == wnd)
316                            continue;
317                    if (sw->desktop != desktop)
318                    {
319                            ewmh_move_to_desktop(sw->wnd, desktop);
320                            sw->desktop = desktop;
321                    }
322            }
323    }
324    
325    
326  static void  static void
327  mwm_hide_decorations(Window wnd)  mwm_hide_decorations(Window wnd)
328  {  {
# Line 1396  ui_init(void) Line 1421  ui_init(void)
1421                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1422    
1423          xclip_init();          xclip_init();
1424            ewmh_init();
1425          if (g_seamless_rdp)          if (g_seamless_rdp)
1426                  seamless_init();                  seamless_init();
1427    
# Line 1541  ui_create_window(void) Line 1567  ui_create_window(void)
1567          }          }
1568    
1569          XSelectInput(g_display, g_wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
1570          if (!g_seamless_rdp)  
1571            XMapWindow(g_display, g_wnd);
1572            /* wait for VisibilityNotify */
1573            do
1574          {          {
1575                  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;  
1576          }          }
1577            while (xevent.type != VisibilityNotify);
1578            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1579    
1580          g_focused = False;          g_focused = False;
1581          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 1615  xwin_toggle_fullscreen(void) Line 1639  xwin_toggle_fullscreen(void)
1639  {  {
1640          Pixmap contents = 0;          Pixmap contents = 0;
1641    
1642          if (g_seamless_rdp)          if (g_seamless_active)
1643                  /* Turn off SeamlessRDP mode */                  /* Turn off SeamlessRDP mode */
1644                  ui_seamless_toggle();                  ui_seamless_toggle();
1645    
# Line 1720  handle_button_event(XEvent xevent, BOOL Line 1744  handle_button_event(XEvent xevent, BOOL
1744          }          }
1745  }  }
1746    
1747    static void
1748    ui_seamless_handle_restack(seamless_window * sw)
1749    {
1750            Status status;
1751            Window root, parent, *children;
1752            unsigned int nchildren, i;
1753            seamless_window *sw_below;
1754    
1755            status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
1756                                &root, &parent, &children, &nchildren);
1757            if (!status || !nchildren)
1758                    return;
1759    
1760            sw_below = NULL;
1761    
1762            i = 0;
1763            while (children[i] != sw->wnd)
1764            {
1765                    i++;
1766                    if (i >= nchildren)
1767                            return;
1768            }
1769    
1770            for (i++; i < nchildren; i++)
1771            {
1772                    sw_below = seamless_get_window_by_wnd(children[i]);
1773                    if (sw_below)
1774                            break;
1775            }
1776    
1777            if (sw_below)
1778                    seamless_send_zchange(sw->id, sw_below->id, 0);
1779            else
1780                    seamless_send_zchange(sw->id, 0, 0);
1781    }
1782    
1783  /* Process events in Xlib queue  /* Process events in Xlib queue
1784     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1785  static int  static int
# Line 1731  xwin_process_events(void) Line 1791  xwin_process_events(void)
1791          char str[256];          char str[256];
1792          Status status;          Status status;
1793          int events = 0;          int events = 0;
1794            seamless_window *sw;
1795    
1796          while ((XPending(g_display) > 0) && events++ < 20)          while ((XPending(g_display) > 0) && events++ < 20)
1797          {          {
# Line 1893  xwin_process_events(void) Line 1954  xwin_process_events(void)
1954                                  }                                  }
1955                                  else                                  else
1956                                  {                                  {
                                         seamless_window *sw;  
1957                                          sw = seamless_get_window_by_wnd(xevent.xexpose.window);                                          sw = seamless_get_window_by_wnd(xevent.xexpose.window);
1958                                          if (sw)                                          if (sw)
1959                                                  XCopyArea(g_display, g_backstore,                                                  XCopyArea(g_display, g_backstore,
# Line 1903  xwin_process_events(void) Line 1963  xwin_process_events(void)
1963                                                            xevent.xexpose.width,                                                            xevent.xexpose.width,
1964                                                            xevent.xexpose.height, xevent.xexpose.x,                                                            xevent.xexpose.height, xevent.xexpose.x,
1965                                                            xevent.xexpose.y);                                                            xevent.xexpose.y);
1966                                            else
1967                                            {
1968                                                    error("Expose for unknown window 0x%lx\n",
1969                                                          xevent.xexpose.window);
1970                                            }
1971                                  }                                  }
1972    
1973                                  break;                                  break;
# Line 1933  xwin_process_events(void) Line 1998  xwin_process_events(void)
1998                                  break;                                  break;
1999                          case PropertyNotify:                          case PropertyNotify:
2000                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
2001                                    if (xevent.xproperty.window == g_wnd)
2002                                            break;
2003                                    if (xevent.xproperty.window == DefaultRootWindow(g_display))
2004                                            break;
2005    
2006                                    /* seamless */
2007                                    sw = seamless_get_window_by_wnd(xevent.xproperty.window);
2008                                    if (!sw)
2009                                            break;
2010    
2011                                    if ((xevent.xproperty.atom == g_net_wm_state_atom)
2012                                        && (xevent.xproperty.state == PropertyNewValue))
2013                                    {
2014                                            sw->state = ewmh_get_window_state(sw->wnd);
2015                                            seamless_send_state(sw->id, sw->state, 0);
2016                                    }
2017    
2018                                    if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
2019                                        && (xevent.xproperty.state == PropertyNewValue))
2020                                    {
2021                                            sw->desktop = ewmh_get_window_desktop(sw->wnd);
2022                                            seamless_all_to_desktop(sw->wnd, sw->desktop);
2023                                    }
2024    
2025                                  break;                                  break;
2026                          case MapNotify:                          case MapNotify:
2027                                  if (!g_seamless_rdp)                                  if (!g_seamless_active)
2028                                          rdp_send_client_window_status(1);                                          rdp_send_client_window_status(1);
2029                                  break;                                  break;
2030                          case UnmapNotify:                          case UnmapNotify:
2031                                  if (!g_seamless_rdp)                                  if (!g_seamless_active)
2032                                          rdp_send_client_window_status(0);                                          rdp_send_client_window_status(0);
2033                                  break;                                  break;
2034                            case ConfigureNotify:
2035                                    /* seamless */
2036                                    sw = seamless_get_window_by_wnd(xevent.xconfigure.window);
2037                                    if (!sw)
2038                                            break;
2039    
2040                                    ui_seamless_handle_restack(sw);
2041                  }                  }
2042          }          }
2043          /* Keep going */          /* Keep going */
# Line 2953  ui_end_update(void) Line 3049  ui_end_update(void)
3049  }  }
3050    
3051  void  void
3052    ui_seamless_begin()
3053    {
3054            if (!g_seamless_rdp)
3055                    return;
3056    
3057            if (g_seamless_started)
3058                    return;
3059    
3060            g_seamless_started = True;
3061    
3062            ui_seamless_toggle();
3063    }
3064    
3065    void
3066  ui_seamless_toggle()  ui_seamless_toggle()
3067  {  {
3068          if (g_seamless_rdp)          if (!g_seamless_rdp)
3069                    return;
3070    
3071            if (!g_seamless_started)
3072                    return;
3073    
3074            if (g_seamless_active)
3075          {          {
3076                  /* Deactivate */                  /* Deactivate */
3077                  while (g_seamless_windows)                  while (g_seamless_windows)
# Line 2968  ui_seamless_toggle() Line 3084  ui_seamless_toggle()
3084          else          else
3085          {          {
3086                  /* 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;  
                 }  
   
3087                  XUnmapWindow(g_display, g_wnd);                  XUnmapWindow(g_display, g_wnd);
3088                  seamless_send_sync();                  seamless_send_sync();
3089          }          }
3090    
3091          g_seamless_rdp = !g_seamless_rdp;          g_seamless_active = !g_seamless_active;
3092  }  }
3093    
3094  void  void
3095  ui_seamless_create_window(unsigned long id, unsigned long flags)  ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags)
3096  {  {
3097          Window wnd;          Window wnd;
3098          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
3099          XClassHint *classhints;          XClassHint *classhints;
3100            XSizeHints *sizehints;
3101          long input_mask;          long input_mask;
3102          seamless_window *sw;          seamless_window *sw, *sw_parent;
3103    
3104          get_window_attribs(&attribs);          if (!g_seamless_active)
3105                    return;
3106    
3107            /* Ignore CREATEs for existing windows */
3108            sw = seamless_get_window_by_id(id);
3109            if (sw)
3110                    return;
3111    
3112            get_window_attribs(&attribs);
3113          attribs.override_redirect = False;          attribs.override_redirect = False;
3114    
3115          /* FIXME: Do not assume that -1, -1 is outside screen Consider          wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
            wait with showing the window until STATE and others have  
            been recieved. */  
         wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, 0,  
3116                              InputOutput, g_visual,                              InputOutput, g_visual,
3117                              CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |                              CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
3118                              CWBorderPixel, &attribs);                              CWBorderPixel, &attribs);
3119    
3120          XStoreName(g_display, wnd, "rdesktop-seamless");          XStoreName(g_display, wnd, "SeamlessRDP");
3121            ewmh_set_wm_name(wnd, "SeamlessRDP");
3122    
3123          mwm_hide_decorations(wnd);          mwm_hide_decorations(wnd);
3124    
3125          classhints = XAllocClassHint();          classhints = XAllocClassHint();
3126          if (classhints != NULL)          if (classhints != NULL)
3127          {          {
3128                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = "rdesktop";
3129                    classhints->res_class = "SeamlessRDP";
3130                  XSetClassHint(g_display, wnd, classhints);                  XSetClassHint(g_display, wnd, classhints);
3131                  XFree(classhints);                  XFree(classhints);
3132          }          }
3133    
3134            /* WM_NORMAL_HINTS */
3135            sizehints = XAllocSizeHints();
3136            if (sizehints != NULL)
3137            {
3138                    sizehints->flags = USPosition;
3139                    XSetWMNormalHints(g_display, wnd, sizehints);
3140                    XFree(sizehints);
3141            }
3142    
3143            /* Set WM_TRANSIENT_FOR, if necessary */
3144            if ((parent != 0x00000000) && (parent != 0xFFFFFFFF))
3145            {
3146                    sw_parent = seamless_get_window_by_id(parent);
3147                    if (sw_parent)
3148                            XSetTransientForHint(g_display, wnd, sw_parent->wnd);
3149                    else
3150                            warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3151            }
3152    
3153    
3154          /* FIXME: Support for Input Context:s */          /* FIXME: Support for Input Context:s */
3155    
3156          get_input_mask(&input_mask);          get_input_mask(&input_mask);
3157            input_mask |= PropertyChangeMask;
3158    
3159          XSelectInput(g_display, wnd, input_mask);          XSelectInput(g_display, wnd, input_mask);
3160    
         XMapWindow(g_display, wnd);  
   
3161          /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a          /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3162             seamless window, we could try to close the window on the             seamless window, we could try to close the window on the
3163             serverside, instead of terminating rdesktop */             serverside, instead of terminating rdesktop */
# Line 3035  ui_seamless_create_window(unsigned long Line 3166  ui_seamless_create_window(unsigned long
3166          sw = malloc(sizeof(seamless_window));          sw = malloc(sizeof(seamless_window));
3167          sw->wnd = wnd;          sw->wnd = wnd;
3168          sw->id = id;          sw->id = id;
3169            sw->parent = parent;
3170          sw->xoffset = 0;          sw->xoffset = 0;
3171          sw->yoffset = 0;          sw->yoffset = 0;
3172          sw->width = 0;          sw->width = 0;
3173          sw->height = 0;          sw->height = 0;
3174            sw->state = SEAMLESSRDP_NOTYETMAPPED;
3175            sw->desktop = 0;
3176          sw->next = g_seamless_windows;          sw->next = g_seamless_windows;
3177          g_seamless_windows = sw;          g_seamless_windows = sw;
3178  }  }
# Line 3048  void Line 3182  void
3182  ui_seamless_destroy_window(unsigned long id, unsigned long flags)  ui_seamless_destroy_window(unsigned long id, unsigned long flags)
3183  {  {
3184          seamless_window *sw;          seamless_window *sw;
         sw = seamless_get_window_by_id(id);  
3185    
3186            if (!g_seamless_active)
3187                    return;
3188    
3189            sw = seamless_get_window_by_id(id);
3190          if (!sw)          if (!sw)
3191          {          {
3192                  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 3066  ui_seamless_move_window(unsigned long id Line 3203  ui_seamless_move_window(unsigned long id
3203  {  {
3204          seamless_window *sw;          seamless_window *sw;
3205    
3206          sw = seamless_get_window_by_id(id);          if (!g_seamless_active)
3207                    return;
3208    
3209            sw = seamless_get_window_by_id(id);
3210          if (!sw)          if (!sw)
3211          {          {
3212                  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);
# Line 3089  ui_seamless_move_window(unsigned long id Line 3228  ui_seamless_move_window(unsigned long id
3228          sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);          sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
3229          sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);          sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
3230    
3231            /* If we move the window in a maximized state, then KDE won't
3232               accept restoration */
3233            switch (sw->state)
3234            {
3235                    case SEAMLESSRDP_MINIMIZED:
3236                    case SEAMLESSRDP_MAXIMIZED:
3237                            return;
3238            }
3239    
3240          /* FIXME: Perhaps use ewmh_net_moveresize_window instead */          /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3241          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);
3242  }  }
3243    
3244    void
3245    ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3246    {
3247            seamless_window *sw;
3248    
3249            if (!g_seamless_active)
3250                    return;
3251    
3252            sw = seamless_get_window_by_id(id);
3253            if (!sw)
3254            {
3255                    warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3256                    return;
3257            }
3258    
3259            if (behind)
3260            {
3261                    seamless_window *sw_behind;
3262                    Window wnds[2];
3263    
3264                    sw_behind = seamless_get_window_by_id(behind);
3265                    if (!sw_behind)
3266                    {
3267                            warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3268                                    behind);
3269                            return;
3270                    }
3271    
3272                    wnds[1] = sw_behind->wnd;
3273                    wnds[0] = sw->wnd;
3274    
3275                    XRestackWindows(g_display, wnds, 2);
3276            }
3277            else
3278            {
3279                    XRaiseWindow(g_display, sw->wnd);
3280            }
3281    }
3282    
3283  void  void
3284  ui_seamless_settitle(unsigned long id, const char *title)  ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
3285  {  {
3286          seamless_window *sw;          seamless_window *sw;
3287    
3288            if (!g_seamless_active)
3289                    return;
3290    
3291          sw = seamless_get_window_by_id(id);          sw = seamless_get_window_by_id(id);
3292            if (!sw)
3293            {
3294                    warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3295                    return;
3296            }
3297    
3298            /* FIXME: Might want to convert the name for non-EWMH WMs */
3299          XStoreName(g_display, sw->wnd, title);          XStoreName(g_display, sw->wnd, title);
3300            ewmh_set_wm_name(sw->wnd, title);
3301  }  }
3302    
3303    
# Line 3110  ui_seamless_setstate(unsigned long id, u Line 3306  ui_seamless_setstate(unsigned long id, u
3306  {  {
3307          seamless_window *sw;          seamless_window *sw;
3308    
3309            if (!g_seamless_active)
3310                    return;
3311    
3312          sw = seamless_get_window_by_id(id);          sw = seamless_get_window_by_id(id);
3313            if (!sw)
3314            {
3315                    warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3316                    return;
3317            }
3318    
3319          switch (state)          switch (state)
3320          {          {
3321                  case SEAMLESSRDP_NORMAL:                  case SEAMLESSRDP_NORMAL:
3322                  case SEAMLESSRDP_MAXIMIZED:                  case SEAMLESSRDP_MAXIMIZED:
3323                          /* FIXME */                          ewmh_change_state(sw->wnd, state);
3324                            XMapWindow(g_display, sw->wnd);
3325                          break;                          break;
3326                  case SEAMLESSRDP_MINIMIZED:                  case SEAMLESSRDP_MINIMIZED:
3327                          XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));                          /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3328                               the Window Manager should probably just ignore the request, since
3329                               _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3330                               such as minimization, rather than an independent state." Besides,
3331                               XIconifyWindow is easier. */
3332                            if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3333                            {
3334                                    XWMHints *hints;
3335                                    hints = XAllocWMHints();
3336                                    hints->flags = StateHint;
3337                                    hints->initial_state = IconicState;
3338                                    XSetWMHints(g_display, sw->wnd, hints);
3339                                    XFree(hints);
3340                                    XMapWindow(g_display, sw->wnd);
3341                            }
3342                            else
3343                                    XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
3344                          break;                          break;
3345                  default:                  default:
3346                          warning("SeamlessRDP: Invalid state %d\n", state);                          warning("SeamlessRDP: Invalid state %d\n", state);
3347                          break;                          break;
3348          }          }
3349    
3350            /* Handle popups without parents through some ewm hints */
3351            if ((sw->state == SEAMLESSRDP_NOTYETMAPPED) && (sw->parent == 0xFFFFFFFF))
3352                    ewmh_set_window_popup(sw->wnd);
3353    
3354            sw->state = state;
3355    }
3356    
3357    
3358    void
3359    ui_seamless_syncbegin(unsigned long flags)
3360    {
3361            if (!g_seamless_active)
3362                    return;
3363    
3364            /* Destroy all seamless windows */
3365            while (g_seamless_windows)
3366            {
3367                    XDestroyWindow(g_display, g_seamless_windows->wnd);
3368                    seamless_remove_window(g_seamless_windows);
3369            }
3370  }  }

Legend:
Removed from v.1089  
changed lines
  Added in v.1151

  ViewVC Help
Powered by ViewVC 1.1.26