Commit c6f12bd9 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Notify all listeners when the contents of the clipboard have changed.

parent 7594afeb
......@@ -185,8 +185,8 @@ BOOL WINAPI CloseClipboard(void)
{
if (owner) USER_Driver->pEndClipboardUpdate();
bCBHasChanged = FALSE;
if (viewer) SendNotifyMessageW(viewer, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0);
}
if (viewer) SendNotifyMessageW( viewer, WM_DRAWCLIPBOARD, (WPARAM)GetClipboardOwner(), 0 );
return TRUE;
}
......
......@@ -45,6 +45,7 @@ struct clipboard
user_handle_t owner_win; /* window that owns the clipboard data */
user_handle_t viewer; /* first window in clipboard viewer list */
unsigned int seqno; /* clipboard change sequence number */
unsigned int open_seqno; /* sequence number at open time */
timeout_t seqno_timestamp; /* time stamp of last seqno increment */
unsigned int listen_size; /* size of listeners array */
unsigned int listen_count; /* count of listeners */
......@@ -167,6 +168,21 @@ static int remove_listener( struct clipboard *clipboard, user_handle_t window )
return 0;
}
/* close the clipboard, and return the viewer window that should be notified if any */
static user_handle_t close_clipboard( struct clipboard *clipboard )
{
unsigned int i;
clipboard->open_win = 0;
clipboard->open_thread = NULL;
if (clipboard->seqno == clipboard->open_seqno) return 0; /* unchanged */
for (i = 0; i < clipboard->listen_count; i++)
post_message( clipboard->listeners[i], WM_CLIPBOARDUPDATE, 0, 0 );
return clipboard->viewer;
}
/* cleanup clipboard information upon window destruction */
void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window )
{
......@@ -174,18 +190,18 @@ void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window )
if (!clipboard) return;
if (clipboard->open_win == window)
{
clipboard->open_win = 0;
clipboard->open_thread = NULL;
}
remove_listener( clipboard, window );
if (clipboard->viewer == window) clipboard->viewer = 0;
if (clipboard->owner_win == window)
{
clipboard->owner_win = 0;
clipboard->owner_thread = NULL;
}
if (clipboard->viewer == window) clipboard->viewer = 0;
remove_listener( clipboard, window );
if (clipboard->open_win == window)
{
user_handle_t viewer = close_clipboard( clipboard );
if (viewer) send_notify_message( viewer, WM_DRAWCLIPBOARD, clipboard->owner_win, 0 );
}
}
/* Called when thread terminates to allow release of clipboard */
......@@ -199,16 +215,16 @@ void cleanup_clipboard_thread(struct thread *thread)
if ((clipboard = winstation->clipboard))
{
if (thread == clipboard->open_thread)
{
clipboard->open_win = 0;
clipboard->open_thread = NULL;
}
if (thread == clipboard->owner_thread)
{
clipboard->owner_win = 0;
clipboard->owner_thread = NULL;
}
if (thread == clipboard->open_thread)
{
user_handle_t viewer = close_clipboard( clipboard );
if (viewer) send_notify_message( viewer, WM_DRAWCLIPBOARD, clipboard->owner_win, 0 );
}
}
release_object( winstation );
}
......@@ -256,6 +272,8 @@ DECL_HANDLER(open_clipboard)
set_error( STATUS_INVALID_LOCK_SEQUENCE );
return;
}
if (!clipboard->open_thread) clipboard->open_seqno = clipboard->seqno; /* first open */
clipboard->open_win = win;
clipboard->open_thread = current;
......@@ -276,10 +294,8 @@ DECL_HANDLER(close_clipboard)
return;
}
if (req->changed) clipboard->seqno++;
clipboard->open_thread = NULL;
clipboard->open_win = 0;
reply->viewer = clipboard->viewer;
reply->viewer = close_clipboard( clipboard );
reply->owner = (clipboard->owner_thread && clipboard->owner_thread->process == current->process);
}
......
......@@ -2112,6 +2112,33 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa
release_object( thread );
}
/* send a notify message to a window */
void send_notify_message( user_handle_t win, unsigned int message, lparam_t wparam, lparam_t lparam )
{
struct message *msg;
struct thread *thread = get_window_thread( win );
if (!thread) return;
if (thread->queue && (msg = mem_alloc( sizeof(*msg) )))
{
msg->type = MSG_NOTIFY;
msg->win = get_user_full_handle( win );
msg->msg = message;
msg->wparam = wparam;
msg->lparam = lparam;
msg->result = NULL;
msg->data = NULL;
msg->data_size = 0;
get_message_defaults( thread->queue, &msg->x, &msg->y, &msg->time );
list_add_tail( &thread->queue->msg_list[SEND_MESSAGE], &msg->entry );
set_queue_bits( thread->queue, QS_SENDMESSAGE );
}
release_object( thread );
}
/* post a win event */
void post_win_event( struct thread *thread, unsigned int event,
user_handle_t win, unsigned int object_id,
......
......@@ -112,6 +112,8 @@ extern int attach_thread_input( struct thread *thread_from, struct thread *threa
extern void detach_thread_input( struct thread *thread_from );
extern void post_message( user_handle_t win, unsigned int message,
lparam_t wparam, lparam_t lparam );
extern void send_notify_message( user_handle_t win, unsigned int message,
lparam_t wparam, lparam_t lparam );
extern void post_win_event( struct thread *thread, unsigned int event,
user_handle_t win, unsigned int object_id,
unsigned int child_id, client_ptr_t proc,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment