winemac: Add support for delay-rendered (a.k.a. promised) clipboard data.
[wine] / dlls / winemac.drv / macdrv_main.c
1 /*
2  * MACDRV initialization code
3  *
4  * Copyright 1998 Patrik Stridvall
5  * Copyright 2000 Alexandre Julliard
6  * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 #include "config.h"
23
24 #include <Security/AuthSession.h>
25
26 #include "macdrv.h"
27 #include "wine/server.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
30
31
32 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
33
34
35 /**************************************************************************
36  *              debugstr_cf
37  */
38 const char* debugstr_cf(CFTypeRef t)
39 {
40     CFStringRef s;
41     const char* ret;
42
43     if (!t) return "(null)";
44
45     if (CFGetTypeID(t) == CFStringGetTypeID())
46         s = t;
47     else
48         s = CFCopyDescription(t);
49     ret = CFStringGetCStringPtr(s, kCFStringEncodingUTF8);
50     if (ret) ret = debugstr_a(ret);
51     if (!ret)
52     {
53         const UniChar* u = CFStringGetCharactersPtr(s);
54         if (u)
55             ret = debugstr_wn((const WCHAR*)u, CFStringGetLength(s));
56     }
57     if (!ret)
58     {
59         UniChar buf[200];
60         int len = min(CFStringGetLength(s), sizeof(buf)/sizeof(buf[0]));
61         CFStringGetCharacters(s, CFRangeMake(0, len), buf);
62         ret = debugstr_wn(buf, len);
63     }
64     if (s != t) CFRelease(s);
65     return ret;
66 }
67
68
69 /***********************************************************************
70  *              process_attach
71  */
72 static BOOL process_attach(void)
73 {
74     SessionAttributeBits attributes;
75     OSStatus status;
76
77     assert(NUM_EVENT_TYPES <= sizeof(macdrv_event_mask) * 8);
78
79     status = SessionGetInfo(callerSecuritySession, NULL, &attributes);
80     if (status != noErr || !(attributes & sessionHasGraphicAccess))
81         return FALSE;
82
83     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
84
85     macdrv_err_on = ERR_ON(macdrv);
86     if (macdrv_start_cocoa_app(GetTickCount64()))
87     {
88         ERR("Failed to start Cocoa app main loop\n");
89         return FALSE;
90     }
91
92     macdrv_clipboard_process_attach();
93
94     return TRUE;
95 }
96
97
98 /***********************************************************************
99  *              thread_detach
100  */
101 static void thread_detach(void)
102 {
103     struct macdrv_thread_data *data = macdrv_thread_data();
104
105     if (data)
106     {
107         macdrv_destroy_event_queue(data->queue);
108         if (data->keyboard_layout_uchr)
109             CFRelease(data->keyboard_layout_uchr);
110         HeapFree(GetProcessHeap(), 0, data);
111     }
112 }
113
114
115 /***********************************************************************
116  *              set_queue_display_fd
117  *
118  * Store the event queue fd into the message queue
119  */
120 static void set_queue_display_fd(int fd)
121 {
122     HANDLE handle;
123     int ret;
124
125     if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle))
126     {
127         MESSAGE("macdrv: Can't allocate handle for event queue fd\n");
128         ExitProcess(1);
129     }
130     SERVER_START_REQ(set_queue_fd)
131     {
132         req->handle = wine_server_obj_handle(handle);
133         ret = wine_server_call(req);
134     }
135     SERVER_END_REQ;
136     if (ret)
137     {
138         MESSAGE("macdrv: Can't store handle for event queue fd\n");
139         ExitProcess(1);
140     }
141     CloseHandle(handle);
142 }
143
144
145 /***********************************************************************
146  *              macdrv_init_thread_data
147  */
148 struct macdrv_thread_data *macdrv_init_thread_data(void)
149 {
150     struct macdrv_thread_data *data = macdrv_thread_data();
151
152     if (data) return data;
153
154     if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
155     {
156         ERR("could not create data\n");
157         ExitProcess(1);
158     }
159
160     if (!(data->queue = macdrv_create_event_queue(macdrv_handle_event)))
161     {
162         ERR("macdrv: Can't create event queue.\n");
163         ExitProcess(1);
164     }
165
166     data->keyboard_layout_uchr = macdrv_copy_keyboard_layout(&data->keyboard_type, &data->iso_keyboard);
167     macdrv_compute_keyboard_layout(data);
168
169     set_queue_display_fd(macdrv_get_event_queue_fd(data->queue));
170     TlsSetValue(thread_data_tls_index, data);
171
172     return data;
173 }
174
175
176 /***********************************************************************
177  *              DllMain
178  */
179 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
180 {
181     BOOL ret = TRUE;
182
183     switch(reason)
184     {
185     case DLL_PROCESS_ATTACH:
186         ret = process_attach();
187         break;
188     case DLL_THREAD_DETACH:
189         thread_detach();
190         break;
191     }
192     return ret;
193 }