[2/6]server: switch_desktop server (try 2)

shanmukha sainath addepalli sainath.addepalli at gmail.com
Sat Dec 12 05:05:52 CST 2009


Hi,

    Difference from Previous patch:
           1. Corrections in formatting.
           2. While calculating the reply data size, initially it was
calculated for only one desktop windows. Now the size will be
allocated by calculating windows of both desktops.
           3. Active Desktop should be set after getting the windows
list (which is to be shown or to be hidden).

                      In this patch, we will define a member
active_desktop in winstation structure. Active Desktop is the desktop
which user interacts.
    The switch_desktop server identifies the windows of current
desktop which are to be hidden and windows of the new desktop which
are to be shown. Then it sets active_desktop as the new desktop.


-- 
Regards
Sainath A
-------------- next part --------------
From 0744af11dd946a9ac0bdbc0dc467135c0606d51f Mon Sep 17 00:00:00 2001
From: Sainath Addepalli <sainath.addepalli at gmail.com>
Date: Sat, 12 Dec 2009 13:20:30 +0530
Subject: SwitchDesktop server declaration

---
 server/protocol.def |   11 ++++
 server/user.h       |    2 +
 server/window.c     |  142 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 154 insertions(+), 1 deletions(-)

diff --git a/server/protocol.def b/server/protocol.def
index bba6788..8c7d303 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3217,6 +3217,17 @@ enum message_type
 @END
 
 
+/* Switch to another desktop */
+ at REQ(switch_desktop)
+    obj_handle_t   handle;        /* handle to the desktop to be switched */
+    VARARG(children,user_handles);/* window handles */
+ at REPLY
+    VARARG(children,user_handles);/* Window handles to be shown or hide */
+    int         old_desktop_count;/* Number of windows on current desktop */
+    int         new_desktop_count;/* Number of windows on new desktop */
+ at END
+
+
 /* Retrieve layered info for a window */
 @REQ(get_window_layered_info)
     user_handle_t  handle;        /* handle to the window */
diff --git a/server/user.h b/server/user.h
index e9ad116..8d4cc17 100644
--- a/server/user.h
+++ b/server/user.h
@@ -49,6 +49,7 @@ struct winstation
     struct list        desktops;           /* list of desktops of this winstation */
     struct clipboard  *clipboard;          /* clipboard information */
     struct atom_table *atom_table;         /* global atom table */
+    struct desktop    *active_desktop;      /* Active Desktop of this winstation */
 };
 
 struct desktop
@@ -162,5 +163,6 @@ extern void set_process_default_desktop( struct process *process, struct desktop
                                          obj_handle_t handle );
 extern void close_process_desktop( struct process *process );
 extern void close_thread_desktop( struct thread *thread );
+extern int is_active_desktop( struct desktop *desktop );
 
 #endif  /* __WINE_SERVER_USER_H */
diff --git a/server/window.c b/server/window.c
index a0e0788..803b6df 100644
--- a/server/window.c
+++ b/server/window.c
@@ -261,6 +261,24 @@ static int add_handle_to_array( struct user_handle_array *array, user_handle_t h
     return 1;
 }
 
+/* Find a window handle in given array */
+/* return 1 if the handle is in the array and 0 if not */
+static int find_handle_in_array( struct user_handle_array *array, user_handle_t handle )
+{
+    int i = 0;
+
+    if (!handle)
+    {
+        set_error( STATUS_INVALID_PARAMETER );
+        return 0;
+    }
+    for(i = 0; i < array->count; i++ )
+    {
+        if (array->handles[i] == handle) return 1;
+    }
+    return 0;
+}
+
 /* set a window property */
 static void set_property( struct window *win, atom_t atom, lparam_t data, enum property_type type )
 {
@@ -697,6 +715,9 @@ static int all_windows_from_point( struct window *top, int x, int y, struct user
 {
     struct window *ptr;
 
+    /* If the top window doesn't belong to active desktop then return */
+    if(!( top->desktop == top->desktop->winstation->active_desktop )) return 1;
+
     /* make point relative to top window */
     for (ptr = top->parent; ptr && !is_desktop_window(ptr); ptr = ptr->parent)
     {
@@ -736,9 +757,14 @@ struct thread *get_window_thread( user_handle_t handle )
 /* check if any area of a window needs repainting */
 static inline int win_needs_repaint( struct window *win )
 {
-    return win->update_region || (win->paint_flags & PAINT_INTERNAL);
+    return (is_active_desktop( win->desktop )) && (win->update_region || (win->paint_flags & PAINT_INTERNAL));
 }
 
+/* check whether the desktop is active desktop or not */
+int is_active_desktop( struct desktop *desktop )
+{
+    return (desktop->winstation->active_desktop == desktop);
+}
 
 /* find a child of the specified window that needs repainting */
 static struct window *find_child_to_repaint( struct window *parent, struct thread *thread )
@@ -1241,6 +1267,9 @@ static void redraw_window( struct window *win, struct region *region, int frame,
     struct region *tmp;
     struct window *child;
 
+    /* We don't redraw windows that doesn't belong to active desktop */
+    if (win->desktop != win->desktop->winstation->active_desktop) return;
+
     if (flags & RDW_INVALIDATE)
     {
         if (!(tmp = crop_region_to_win_rect( win, region, frame ))) return;
@@ -2526,3 +2555,114 @@ DECL_HANDLER(set_window_layered_info)
     }
     else set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
 }
+
+
+/* Switch to another Desktop */
+DECL_HANDLER(switch_desktop)
+{
+    struct winstation *winstation;
+    struct desktop *old_desktop, *new_desktop;
+    struct window *top_win = NULL, *next_win = NULL;
+    user_handle_t *handles_windows = NULL, *handles = NULL;
+    static struct user_handle_array array;
+    int i=0, count=0;
+    unsigned int old_win = 0, new_win = 0;
+    data_size_t len;
+
+    if (!(winstation = get_process_winstation( current->process, 0  /*FIXME: access rights? */ ))) return;
+
+    if (!(new_desktop = get_desktop_obj( current->process, req->handle, 0 )))
+    {
+        release_object( winstation );
+        return;
+    }
+    handles = (user_handle_t *)get_req_data();
+
+    /* We will retrieve the current desktop from active_desktop */
+    old_desktop = winstation->active_desktop;
+
+    if(!old_desktop)
+    {
+        release_object( new_desktop );
+        release_object( winstation );
+        return;
+    }
+
+    /* Hiding current desktop windows */
+
+    top_win = old_desktop->top_window;
+    if (!top_win)
+    {
+        set_error( STATUS_INVALID_HANDLE );
+        release_object( new_desktop );
+        release_object( winstation );
+        return;
+    }
+
+    /* Getting the list of windows in old desktop */
+    old_win = get_children_windows( top_win, 0, 0, NULL, 0 );
+    get_children_windows( top_win, 0, 0, handles, old_win );
+
+    /* Getting the windows count in new desktop*/
+    new_win = get_children_windows( new_desktop->top_window, 0, 0, NULL, 0 );
+
+    /* Caluculating the size of the reply data to be allocated*/
+    len = min( get_reply_max_size(),  (old_win + new_win) * sizeof(user_handle_t) );
+
+    /*  We shouldn't show the default hidden windows while we switching desktops.
+     *  To prevent this, we store the window handles, we hide, in an array */
+    if (len && ((handles_windows = set_reply_data_size( len ))))
+    {
+        count = 0;
+        for(i = 0;i < old_win; i++)
+        {
+            next_win = get_window( handles[i] );
+            if (next_win->style & WS_VISIBLE)
+            {
+                handles_windows[count] = next_win->handle;
+                if (!(find_handle_in_array( &array, next_win->handle )))
+                    add_handle_to_array( &array, next_win->handle );
+                count++;
+            }
+        }
+    }
+    reply->old_desktop_count = count;
+
+    /* Showing another desktop windows */
+
+    top_win = new_desktop->top_window;
+
+    if (!top_win)
+    {
+        set_error( STATUS_INVALID_HANDLE );
+        release_object( new_desktop );
+        release_object( winstation );
+        return;
+    }
+
+    get_children_windows( top_win, 0, 0, handles, new_win );
+
+    /*  Finding windows to be shown
+     *  While showing the windows of a desktop we will check whether they are present
+     *  in the array or not. We only need to show those windows which we hided previously */
+    for(i = 0; i < new_win; i++)
+    {
+        next_win = get_window( handles[i] );
+        if (next_win->style & ~WS_VISIBLE)
+        {
+            if (find_handle_in_array( &array, next_win->handle ))
+            {
+                handles_windows[count] = next_win->handle;
+                count++;
+            }
+        }
+    }
+    reply->new_desktop_count = count - reply->old_desktop_count;
+
+    /* Now Set Active Desktop to the new desktop*/
+    winstation->active_desktop = new_desktop;
+
+    release_object( new_desktop );
+    release_object( winstation );
+    return;
+}
-- 
1.6.0.4


More information about the wine-patches mailing list