kerberos: Add support for SECPKG_CRED_BOTH.
[wine.git] / dlls / winemac.drv / cocoa_clipboard.m
blob4994442f1df5ad79e86492d08d51e4b49c436dc1
1 /*
2  * MACDRV Cocoa clipboard code
3  *
4  * Copyright 2012, 2013 Ken Thomases for CodeWeavers Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
21 #include "macdrv_cocoa.h"
22 #import "cocoa_app.h"
23 #import "cocoa_event.h"
24 #import "cocoa_window.h"
26 #pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
28 #if !defined(MAC_OS_X_VERSION_10_14) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_14
29 /* For older SDKs, #define the new names of constants deprecated/renamed in macOS 10.14. */
30 #define NSBitmapImageFileTypeBMP        NSBMPFileType
31 #define NSBitmapImageFileTypeGIF        NSGIFFileType
32 #define NSBitmapImageFileTypeJPEG       NSJPEGFileType
33 #define NSBitmapImageFileTypePNG        NSPNGFileType
34 #define NSBitmapImageFileTypeTIFF       NSTIFFFileType
35 #endif
37 static int owned_change_count = -1;
38 static int change_count = -1;
40 static NSDictionary<NSString *, NSNumber *> *BitmapOutputTypeMap;
41 static dispatch_once_t BitmapOutputTypesInitOnce;
43 static NSString* const OwnershipSentinel = @"org.winehq.wine.winemac.pasteboard-ownership-sentinel";
46 /***********************************************************************
47  *              macdrv_is_pasteboard_owner
48  */
49 int macdrv_is_pasteboard_owner(macdrv_window w)
51     __block int ret;
52     WineWindow* window = (WineWindow*)w;
54     OnMainThread(^{
55         NSPasteboard* pb = [NSPasteboard generalPasteboard];
56         ret = ([pb changeCount] == owned_change_count);
58         [window.queue discardEventsMatchingMask:event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP)
59                                       forWindow:window];
60     });
62     return ret;
65 /***********************************************************************
66  *              macdrv_has_pasteboard_changed
67  */
68 int macdrv_has_pasteboard_changed(void)
70     __block int new_change_count;
71     int ret;
73     OnMainThread(^{
74         NSPasteboard* pb = [NSPasteboard generalPasteboard];
75         new_change_count = [pb changeCount];
76     });
78     ret = (change_count != new_change_count);
79     change_count = new_change_count;
80     return ret;
83 /***********************************************************************
84  *              macdrv_copy_pasteboard_types
85  *
86  * Returns an array of UTI strings for the types of data available on
87  * the pasteboard, or NULL on error.  The caller is responsible for
88  * releasing the returned array with CFRelease().
89  */
90 CFArrayRef macdrv_copy_pasteboard_types(CFTypeRef pasteboard)
92 @autoreleasepool
94     NSPasteboard* pb = (NSPasteboard*)pasteboard;
95     __block CFArrayRef ret = NULL;
97     dispatch_once(&BitmapOutputTypesInitOnce, ^{
98         BitmapOutputTypeMap =
99         @{
100                    @"public.tiff" : @(NSBitmapImageFileTypeTIFF),
101                     @"public.png" : @(NSBitmapImageFileTypePNG),
102              @"com.microsoft.bmp" : @(NSBitmapImageFileTypeBMP),
103             @"com.compuserve.gif" : @(NSBitmapImageFileTypeGIF),
104                    @"public.jpeg" : @(NSBitmapImageFileTypeJPEG),
105         };
106         [BitmapOutputTypeMap retain];
107     });
109     OnMainThread(^{
110         @try
111         {
112             NSPasteboard* local_pb = pb;
113             NSArray* types;
115             if (!local_pb) local_pb = [NSPasteboard generalPasteboard];
116             types = [local_pb types];
118             // If there are any types understood by NSBitmapImageRep, then we
119             // can offer all of the types that it can output, too.  For example,
120             // if TIFF is on the pasteboard, we can offer PNG, BMP, etc. to the
121             // Windows program.  We'll convert on demand.
122             if ([types firstObjectCommonWithArray:[NSBitmapImageRep imageTypes]] ||
123                 [types firstObjectCommonWithArray:[NSBitmapImageRep imagePasteboardTypes]])
124             {
125                 NSMutableArray<NSString *> *newTypes = [[BitmapOutputTypeMap allKeys] mutableCopy];
126                 [newTypes removeObjectsInArray:types];
127                 types = [types arrayByAddingObjectsFromArray:newTypes];
128                 [newTypes release];
129             }
131             ret = (CFArrayRef)[types copy];
132         }
133         @catch (id e)
134         {
135             ERR(@"Exception discarded while copying pasteboard types: %@\n", e);
136         }
137     });
139     return ret;
144 /***********************************************************************
145  *              macdrv_copy_pasteboard_data
147  * Returns the pasteboard data for a specified type, or NULL on error or
148  * if there's no such type on the pasteboard.  The caller is responsible
149  * for releasing the returned data object with CFRelease().
150  */
151 CFDataRef macdrv_copy_pasteboard_data(CFTypeRef pasteboard, CFStringRef type)
153     NSPasteboard* pb = (NSPasteboard*)pasteboard;
154     __block NSData* ret = nil;
156     OnMainThread(^{
157         @try
158         {
159             NSPasteboard* local_pb = pb;
160             if (!local_pb) local_pb = [NSPasteboard generalPasteboard];
161             if ([local_pb availableTypeFromArray:@[(NSString*)type]])
162                 ret = [[local_pb dataForType:(NSString*)type] copy];
163             else
164             {
165                 NSNumber* bitmapType = BitmapOutputTypeMap[(NSString*)type];
166                 if (bitmapType)
167                 {
168                     NSArray* reps = [NSBitmapImageRep imageRepsWithPasteboard:local_pb];
169                     ret = [NSBitmapImageRep representationOfImageRepsInArray:reps
170                                                                    usingType:[bitmapType unsignedIntegerValue]
171                                                                   properties:nil];
172                     ret = [ret copy];
173                 }
174             }
175         }
176         @catch (id e)
177         {
178             ERR(@"Exception discarded while copying pasteboard types: %@\n", e);
179         }
180     });
182     return (CFDataRef)ret;
186 /***********************************************************************
187  *              macdrv_clear_pasteboard
189  * Takes ownership of the Mac pasteboard and clears it of all data types.
190  */
191 void macdrv_clear_pasteboard(macdrv_window w)
193     WineWindow* window = (WineWindow*)w;
195     OnMainThread(^{
196         @try
197         {
198             NSPasteboard* pb = [NSPasteboard generalPasteboard];
199             owned_change_count = [pb declareTypes:@[OwnershipSentinel]
200                                             owner:window];
201             [window.queue discardEventsMatchingMask:event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP)
202                                           forWindow:window];
203         }
204         @catch (id e)
205         {
206             ERR(@"Exception discarded while clearing pasteboard: %@\n", e);
207         }
208     });
212 /***********************************************************************
213  *              macdrv_set_pasteboard_data
215  * Sets the pasteboard data for a specified type.  Replaces any data of
216  * that type already on the pasteboard.  If data is NULL, promises the
217  * type.
219  * Returns 0 on error, non-zero on success.
220  */
221 int macdrv_set_pasteboard_data(CFStringRef type, CFDataRef data, macdrv_window w)
223     __block int ret = 0;
224     WineWindow* window = (WineWindow*)w;
226     OnMainThread(^{
227         @try
228         {
229             NSPasteboard* pb = [NSPasteboard generalPasteboard];
230             NSInteger change_count = [pb addTypes:@[(NSString*)type]
231                                             owner:window];
232             if (change_count)
233             {
234                 owned_change_count = change_count;
235                 if (data)
236                     ret = [pb setData:(NSData*)data forType:(NSString*)type];
237                 else
238                     ret = 1;
239             }
240         }
241         @catch (id e)
242         {
243             ERR(@"Exception discarded while copying pasteboard types: %@\n", e);
244         }
245     });
247     return ret;