Reimplemented Get/SetActiveWindow, Get/SetFocus and
Get/SetForegroundWindow by storing the information in the
server. Implemented correct inter-process window activation.

diff --git a/server/protocol.def b/server/protocol.def
index 43f4fa0..6e72e97 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1762,6 +1762,7 @@
     user_handle_t  handle;      /* handle to the window */
 @REPLY
     user_handle_t  full_handle; /* full 32-bit handle */
+    user_handle_t  last_active; /* last active popup */
     process_id_t   pid;         /* process owning the window */
     thread_id_t    tid;         /* thread owning the window */
     atom_t         atom;        /* class atom */
@@ -1931,3 +1932,26 @@
     user_handle_t  caret;         /* handle to the caret window */
     rectangle_t    rect;          /* caret rectangle */
 @END
+
+/* Set the system foreground window */
+@REQ(set_foreground_window)
+    user_handle_t  handle;        /* handle to the foreground window */
+@REPLY
+    user_handle_t  previous;      /* handle to the previous foreground window */
+    int            send_msg_old;  /* whether we have to send a msg to the old window */
+    int            send_msg_new;  /* whether we have to send a msg to the new window */
+@END
+
+/* Set the current thread focus window */
+@REQ(set_focus_window)
+    user_handle_t  handle;        /* handle to the focus window */
+@REPLY
+    user_handle_t  previous;      /* handle to the previous focus window */
+@END
+
+/* Set the current thread active window */
+@REQ(set_active_window)
+    user_handle_t  handle;        /* handle to the active window */
+@REPLY
+    user_handle_t  previous;      /* handle to the previous active window */
+@END
diff --git a/server/queue.c b/server/queue.c
index 5a08668..5d51e62 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -621,6 +621,25 @@
     if (window == input->caret) input->caret = 0;
 }
 
+/* check if the specified window can be set in the input data of a given queue */
+static int check_queue_input_window( struct msg_queue *queue, user_handle_t window )
+{
+    struct thread *thread;
+    int ret = 0;
+
+    if (!window) return 1;  /* we can always clear the data */
+
+    if ((thread = get_window_thread( window )))
+    {
+        ret = (queue->input == thread->queue->input);
+        if (!ret) set_error( STATUS_ACCESS_DENIED );
+        release_object( thread );
+    }
+    else set_error( STATUS_INVALID_HANDLE );
+
+    return ret;
+}
+
 /* attach two thread input data structures */
 int attach_thread_input( struct thread *thread_from, struct thread *thread_to )
 {
@@ -1292,3 +1311,61 @@
     reply->foreground = foreground_input ? foreground_input->active : 0;
     if (thread) release_object( thread );
 }
+
+
+/* set the system foreground window */
+DECL_HANDLER(set_foreground_window)
+{
+    struct msg_queue *queue = get_current_queue();
+
+    reply->previous = foreground_input ? foreground_input->active : 0;
+    reply->send_msg_old = (reply->previous && foreground_input != queue->input);
+    reply->send_msg_new = FALSE;
+
+    if (req->handle)
+    {
+        struct thread *thread;
+
+        if (is_top_level_window( req->handle ) &&
+            ((thread = get_window_thread( req->handle ))))
+        {
+            foreground_input = thread->queue->input;
+            reply->send_msg_new = (foreground_input != queue->input);
+            release_object( thread );
+        }
+        else set_error( STATUS_INVALID_HANDLE );
+    }
+    else foreground_input = NULL;
+}
+
+
+/* set the current thread focus window */
+DECL_HANDLER(set_focus_window)
+{
+    struct msg_queue *queue = get_current_queue();
+
+    reply->previous = 0;
+    if (queue && check_queue_input_window( queue, req->handle ))
+    {
+        reply->previous = queue->input->focus;
+        queue->input->focus = get_user_full_handle( req->handle );
+    }
+}
+
+
+/* set the current thread active window */
+DECL_HANDLER(set_active_window)
+{
+    struct msg_queue *queue = get_current_queue();
+
+    reply->previous = 0;
+    if (queue && check_queue_input_window( queue, req->handle ))
+    {
+        if (!req->handle || make_window_active( req->handle ))
+        {
+            reply->previous = queue->input->active;
+            queue->input->active = get_user_full_handle( req->handle );
+        }
+        else set_error( STATUS_INVALID_HANDLE );
+    }
+}
diff --git a/server/request.h b/server/request.h
index 3f1a036..a6076d7 100644
--- a/server/request.h
+++ b/server/request.h
@@ -261,6 +261,9 @@
 DECL_HANDLER(get_window_properties);
 DECL_HANDLER(attach_thread_input);
 DECL_HANDLER(get_thread_input);
+DECL_HANDLER(set_foreground_window);
+DECL_HANDLER(set_focus_window);
+DECL_HANDLER(set_active_window);
 
 #ifdef WANT_REQUEST_HANDLERS
 
@@ -425,6 +428,9 @@
     (req_handler)req_get_window_properties,
     (req_handler)req_attach_thread_input,
     (req_handler)req_get_thread_input,
+    (req_handler)req_set_foreground_window,
+    (req_handler)req_set_focus_window,
+    (req_handler)req_set_active_window,
 };
 #endif  /* WANT_REQUEST_HANDLERS */
 
diff --git a/server/trace.c b/server/trace.c
index 776370f..e680e58 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2005,6 +2005,7 @@
 static void dump_get_window_info_reply( const struct get_window_info_reply *req )
 {
     fprintf( stderr, " full_handle=%08x,", req->full_handle );
+    fprintf( stderr, " last_active=%08x,", req->last_active );
     fprintf( stderr, " pid=%08x,", req->pid );
     fprintf( stderr, " tid=%08x,", req->tid );
     fprintf( stderr, " atom=%04x", req->atom );
@@ -2200,6 +2201,38 @@
     dump_rectangle( &req->rect );
 }
 
+static void dump_set_foreground_window_request( const struct set_foreground_window_request *req )
+{
+    fprintf( stderr, " handle=%08x", req->handle );
+}
+
+static void dump_set_foreground_window_reply( const struct set_foreground_window_reply *req )
+{
+    fprintf( stderr, " previous=%08x,", req->previous );
+    fprintf( stderr, " send_msg_old=%d,", req->send_msg_old );
+    fprintf( stderr, " send_msg_new=%d", req->send_msg_new );
+}
+
+static void dump_set_focus_window_request( const struct set_focus_window_request *req )
+{
+    fprintf( stderr, " handle=%08x", req->handle );
+}
+
+static void dump_set_focus_window_reply( const struct set_focus_window_reply *req )
+{
+    fprintf( stderr, " previous=%08x", req->previous );
+}
+
+static void dump_set_active_window_request( const struct set_active_window_request *req )
+{
+    fprintf( stderr, " handle=%08x", req->handle );
+}
+
+static void dump_set_active_window_reply( const struct set_active_window_reply *req )
+{
+    fprintf( stderr, " previous=%08x", req->previous );
+}
+
 static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_process_request,
     (dump_func)dump_get_new_process_info_request,
@@ -2359,6 +2392,9 @@
     (dump_func)dump_get_window_properties_request,
     (dump_func)dump_attach_thread_input_request,
     (dump_func)dump_get_thread_input_request,
+    (dump_func)dump_set_foreground_window_request,
+    (dump_func)dump_set_focus_window_request,
+    (dump_func)dump_set_active_window_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -2520,6 +2556,9 @@
     (dump_func)dump_get_window_properties_reply,
     (dump_func)0,
     (dump_func)dump_get_thread_input_reply,
+    (dump_func)dump_set_foreground_window_reply,
+    (dump_func)dump_set_focus_window_reply,
+    (dump_func)dump_set_active_window_reply,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -2681,6 +2720,9 @@
     "get_window_properties",
     "attach_thread_input",
     "get_thread_input",
+    "set_foreground_window",
+    "set_focus_window",
+    "set_active_window",
 };
 
 /* ### make_requests end ### */
diff --git a/server/user.h b/server/user.h
index b1cc439..c153d78 100644
--- a/server/user.h
+++ b/server/user.h
@@ -54,6 +54,8 @@
 
 extern void destroy_thread_windows( struct thread *thread );
 extern int is_child_window( user_handle_t parent, user_handle_t child );
+extern int is_top_level_window( user_handle_t window );
+extern int make_window_active( user_handle_t window );
 extern struct thread *get_window_thread( user_handle_t handle );
 extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread );
 
diff --git a/server/window.c b/server/window.c
index ad51288..4631707 100644
--- a/server/window.c
+++ b/server/window.c
@@ -62,6 +62,7 @@
     user_handle_t    handle;          /* full handle for this window */
     struct thread   *thread;          /* thread owning the window */
     atom_t           atom;            /* class atom */
+    user_handle_t    last_active;     /* last active popup */
     rectangle_t      window_rect;     /* window rectangle */
     rectangle_t      client_rect;     /* client rectangle */
     unsigned int     style;           /* window style */
@@ -268,6 +269,7 @@
     win->first_unlinked = NULL;
     win->thread         = current;
     win->atom           = atom;
+    win->last_active    = win->handle;
     win->style          = 0;
     win->ex_style       = 0;
     win->id             = 0;
@@ -321,6 +323,27 @@
     return 0;
 }
 
+/* check whether window is a top-level window */
+int is_top_level_window( user_handle_t window )
+{
+    struct window *win = get_user_object( window, USER_WINDOW );
+    return (win && win->parent == top_window);
+}
+
+/* make a window active if possible */
+int make_window_active( user_handle_t window )
+{
+    struct window *owner, *win = get_window( window );
+
+    if (!win) return 0;
+
+    /* set last active for window and its owner */
+    win->last_active = win->handle;
+    if ((owner = get_user_object( win->owner, USER_WINDOW ))) owner->last_active = win->handle;
+    return 1;
+}
+
+
 /* return the thread owning a window */
 struct thread *get_window_thread( user_handle_t handle )
 {
@@ -478,6 +501,8 @@
     if (win)
     {
         reply->full_handle = win->handle;
+        reply->last_active = win->handle;
+        if (get_user_object( win->last_active, USER_WINDOW )) reply->last_active = win->last_active;
         if (win->thread)
         {
             reply->tid  = get_thread_id( win->thread );