From eba417a47721975a475a01367e3e21dd5fb3356b Mon Sep 17 00:00:00 2001 From: Ken Thomases Date: Sun, 23 Oct 2016 13:03:34 -0500 Subject: [PATCH] winemac: Detect loss of ownership of the Mac pasteboard and update the clipboard manager status. Signed-off-by: Ken Thomases Signed-off-by: Alexandre Julliard --- dlls/winemac.drv/clipboard.c | 17 +++++++++++++++-- dlls/winemac.drv/cocoa_clipboard.m | 20 ++++++++++++++++---- dlls/winemac.drv/cocoa_window.m | 7 +++++++ dlls/winemac.drv/event.c | 5 +++++ dlls/winemac.drv/macdrv.h | 1 + dlls/winemac.drv/macdrv_cocoa.h | 5 +++-- 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/dlls/winemac.drv/clipboard.c b/dlls/winemac.drv/clipboard.c index 358794dd6a2..fc0d60ccb97 100644 --- a/dlls/winemac.drv/clipboard.c +++ b/dlls/winemac.drv/clipboard.c @@ -1551,7 +1551,7 @@ static void set_mac_pasteboard_types_from_win32_clipboard(void) if (!(formats = get_clipboard_formats(&count))) return; - macdrv_clear_pasteboard(); + macdrv_clear_pasteboard(clipboard_cocoa_window); for (i = 0; i < count; i++) { @@ -1657,7 +1657,7 @@ static BOOL update_clipboard(void) if (GetTickCount64() - last_clipboard_update > CLIPBOARD_UPDATE_DELAY) ret = grab_win32_clipboard(); } - else if (!macdrv_is_pasteboard_owner()) + else if (!macdrv_is_pasteboard_owner(clipboard_cocoa_window)) ret = grab_win32_clipboard(); updating = FALSE; @@ -2079,6 +2079,19 @@ BOOL query_pasteboard_data(HWND hwnd, CFStringRef type) } +/************************************************************************** + * macdrv_lost_pasteboard_ownership + * + * Handler for the LOST_PASTEBOARD_OWNERSHIP event. + */ +void macdrv_lost_pasteboard_ownership(HWND hwnd) +{ + TRACE("win %p\n", hwnd); + if (!macdrv_is_pasteboard_owner(clipboard_cocoa_window)) + grab_win32_clipboard(); +} + + /************************************************************************** * macdrv_init_clipboard */ diff --git a/dlls/winemac.drv/cocoa_clipboard.m b/dlls/winemac.drv/cocoa_clipboard.m index 1d1cb88d4c6..3b6ec4145d0 100644 --- a/dlls/winemac.drv/cocoa_clipboard.m +++ b/dlls/winemac.drv/cocoa_clipboard.m @@ -21,6 +21,7 @@ #include "macdrv_cocoa.h" #import "cocoa_app.h" #import "cocoa_event.h" +#import "cocoa_window.h" static int owned_change_count = -1; @@ -29,17 +30,23 @@ static NSDictionary* BitmapOutputTypeMap; static dispatch_once_t BitmapOutputTypesInitOnce; +static NSString* const OwnershipSentinel = @"org.winehq.wine.winemac.pasteboard-ownership-sentinel"; + /*********************************************************************** * macdrv_is_pasteboard_owner */ -int macdrv_is_pasteboard_owner(void) +int macdrv_is_pasteboard_owner(macdrv_window w) { __block int ret; + WineWindow* window = (WineWindow*)w; OnMainThread(^{ NSPasteboard* pb = [NSPasteboard generalPasteboard]; ret = ([pb changeCount] == owned_change_count); + + [window.queue discardEventsMatchingMask:event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP) + forWindow:window]; }); return ret; @@ -157,13 +164,18 @@ CFDataRef macdrv_copy_pasteboard_data(CFTypeRef pasteboard, CFStringRef type) * * Takes ownership of the Mac pasteboard and clears it of all data types. */ -void macdrv_clear_pasteboard(void) +void macdrv_clear_pasteboard(macdrv_window w) { - OnMainThreadAsync(^{ + WineWindow* window = (WineWindow*)w; + + OnMainThread(^{ @try { NSPasteboard* pb = [NSPasteboard generalPasteboard]; - owned_change_count = [pb declareTypes:[NSArray array] owner:nil]; + owned_change_count = [pb declareTypes:[NSArray arrayWithObject:OwnershipSentinel] + owner:window]; + [window.queue discardEventsMatchingMask:event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP) + forWindow:window]; } @catch (id e) { diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index e63899142a1..a68ba03b072 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -2824,6 +2824,13 @@ - (void) pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type macdrv_release_query(query); } + - (void) pasteboardChangedOwner:(NSPasteboard*)sender + { + macdrv_event* event = macdrv_create_event(LOST_PASTEBOARD_OWNERSHIP, self); + [queue postEvent:event]; + macdrv_release_event(event); + } + /* * ---------- NSDraggingDestination methods ---------- diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c index 2b3d6ce6f7f..7d3aab3cd02 100644 --- a/dlls/winemac.drv/event.c +++ b/dlls/winemac.drv/event.c @@ -40,6 +40,7 @@ static const char *dbgstr_event(int type) "KEY_PRESS", "KEY_RELEASE", "KEYBOARD_CHANGED", + "LOST_PASTEBOARD_OWNERSHIP", "MOUSE_BUTTON", "MOUSE_MOVED", "MOUSE_MOVED_ABSOLUTE", @@ -107,6 +108,7 @@ static macdrv_event_mask get_event_mask(DWORD mask) event_mask |= event_mask_for_type(APP_QUIT_REQUESTED); event_mask |= event_mask_for_type(DISPLAYS_CHANGED); event_mask |= event_mask_for_type(IM_SET_TEXT); + event_mask |= event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP); event_mask |= event_mask_for_type(STATUS_ITEM_MOUSE_BUTTON); event_mask |= event_mask_for_type(STATUS_ITEM_MOUSE_MOVE); event_mask |= event_mask_for_type(WINDOW_DID_UNMINIMIZE); @@ -230,6 +232,9 @@ void macdrv_handle_event(const macdrv_event *event) case KEYBOARD_CHANGED: macdrv_keyboard_changed(event); break; + case LOST_PASTEBOARD_OWNERSHIP: + macdrv_lost_pasteboard_ownership(hwnd); + break; case MOUSE_BUTTON: macdrv_mouse_button(hwnd, event); break; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 8afd0645614..a3ded739d0e 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -196,6 +196,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect) extern void macdrv_init_clipboard(void) DECLSPEC_HIDDEN; extern BOOL query_pasteboard_data(HWND hwnd, CFStringRef type) DECLSPEC_HIDDEN; +extern void macdrv_lost_pasteboard_ownership(HWND hwnd) DECLSPEC_HIDDEN; extern const char *debugstr_format(UINT id) DECLSPEC_HIDDEN; extern HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format) DECLSPEC_HIDDEN; extern BOOL macdrv_pasteboard_has_format(CFTypeRef pasteboard, UINT desired_format) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index b3e9106db0d..21e95654376 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -267,6 +267,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display, KEY_PRESS, KEY_RELEASE, KEYBOARD_CHANGED, + LOST_PASTEBOARD_OWNERSHIP, MOUSE_BUTTON, MOUSE_MOVED, MOUSE_MOVED_ABSOLUTE, @@ -539,8 +540,8 @@ extern void macdrv_get_input_source_info(CFDataRef* uchr,CGEventSourceKeyboardTy /* clipboard */ extern CFArrayRef macdrv_copy_pasteboard_types(CFTypeRef pasteboard) DECLSPEC_HIDDEN; extern CFDataRef macdrv_copy_pasteboard_data(CFTypeRef pasteboard, CFStringRef type) DECLSPEC_HIDDEN; -extern int macdrv_is_pasteboard_owner(void) DECLSPEC_HIDDEN; -extern void macdrv_clear_pasteboard(void) DECLSPEC_HIDDEN; +extern int macdrv_is_pasteboard_owner(macdrv_window w) DECLSPEC_HIDDEN; +extern void macdrv_clear_pasteboard(macdrv_window w) DECLSPEC_HIDDEN; extern int macdrv_set_pasteboard_data(CFStringRef type, CFDataRef data, macdrv_window w) DECLSPEC_HIDDEN;