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) ...@@ -185,8 +185,8 @@ BOOL WINAPI CloseClipboard(void)
{ {
if (owner) USER_Driver->pEndClipboardUpdate(); if (owner) USER_Driver->pEndClipboardUpdate();
bCBHasChanged = FALSE; bCBHasChanged = FALSE;
if (viewer) SendNotifyMessageW(viewer, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0);
} }
if (viewer) SendNotifyMessageW( viewer, WM_DRAWCLIPBOARD, (WPARAM)GetClipboardOwner(), 0 );
return TRUE; return TRUE;
} }
......
...@@ -45,6 +45,7 @@ struct clipboard ...@@ -45,6 +45,7 @@ struct clipboard
user_handle_t owner_win; /* window that owns the clipboard data */ user_handle_t owner_win; /* window that owns the clipboard data */
user_handle_t viewer; /* first window in clipboard viewer list */ user_handle_t viewer; /* first window in clipboard viewer list */
unsigned int seqno; /* clipboard change sequence number */ 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 */ timeout_t seqno_timestamp; /* time stamp of last seqno increment */
unsigned int listen_size; /* size of listeners array */ unsigned int listen_size; /* size of listeners array */
unsigned int listen_count; /* count of listeners */ unsigned int listen_count; /* count of listeners */
...@@ -167,6 +168,21 @@ static int remove_listener( struct clipboard *clipboard, user_handle_t window ) ...@@ -167,6 +168,21 @@ static int remove_listener( struct clipboard *clipboard, user_handle_t window )
return 0; 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 */ /* cleanup clipboard information upon window destruction */
void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window ) 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 ) ...@@ -174,18 +190,18 @@ void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window )
if (!clipboard) return; if (!clipboard) return;
if (clipboard->open_win == window) remove_listener( clipboard, window );
{ if (clipboard->viewer == window) clipboard->viewer = 0;
clipboard->open_win = 0;
clipboard->open_thread = NULL;
}
if (clipboard->owner_win == window) if (clipboard->owner_win == window)
{ {
clipboard->owner_win = 0; clipboard->owner_win = 0;
clipboard->owner_thread = NULL; clipboard->owner_thread = NULL;
} }
if (clipboard->viewer == window) clipboard->viewer = 0; if (clipboard->open_win == window)
remove_listener( clipboard, 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 */ /* Called when thread terminates to allow release of clipboard */
...@@ -199,16 +215,16 @@ void cleanup_clipboard_thread(struct thread *thread) ...@@ -199,16 +215,16 @@ void cleanup_clipboard_thread(struct thread *thread)
if ((clipboard = winstation->clipboard)) if ((clipboard = winstation->clipboard))
{ {
if (thread == clipboard->open_thread)
{
clipboard->open_win = 0;
clipboard->open_thread = NULL;
}
if (thread == clipboard->owner_thread) if (thread == clipboard->owner_thread)
{ {
clipboard->owner_win = 0; clipboard->owner_win = 0;
clipboard->owner_thread = NULL; 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 ); release_object( winstation );
} }
...@@ -256,6 +272,8 @@ DECL_HANDLER(open_clipboard) ...@@ -256,6 +272,8 @@ DECL_HANDLER(open_clipboard)
set_error( STATUS_INVALID_LOCK_SEQUENCE ); set_error( STATUS_INVALID_LOCK_SEQUENCE );
return; return;
} }
if (!clipboard->open_thread) clipboard->open_seqno = clipboard->seqno; /* first open */
clipboard->open_win = win; clipboard->open_win = win;
clipboard->open_thread = current; clipboard->open_thread = current;
...@@ -276,10 +294,8 @@ DECL_HANDLER(close_clipboard) ...@@ -276,10 +294,8 @@ DECL_HANDLER(close_clipboard)
return; return;
} }
if (req->changed) clipboard->seqno++; 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); 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 ...@@ -2112,6 +2112,33 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa
release_object( thread ); 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 */ /* post a win event */
void post_win_event( struct thread *thread, unsigned int event, void post_win_event( struct thread *thread, unsigned int event,
user_handle_t win, unsigned int object_id, user_handle_t win, unsigned int object_id,
......
...@@ -112,6 +112,8 @@ extern int attach_thread_input( struct thread *thread_from, struct thread *threa ...@@ -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 detach_thread_input( struct thread *thread_from );
extern void post_message( user_handle_t win, unsigned int message, extern void post_message( user_handle_t win, unsigned int message,
lparam_t wparam, lparam_t lparam ); 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, extern void post_win_event( struct thread *thread, unsigned int event,
user_handle_t win, unsigned int object_id, user_handle_t win, unsigned int object_id,
unsigned int child_id, client_ptr_t proc, 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