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 );