Release 1.5.29.
[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 #include <IOKit/pwr_mgt/IOPMLib.h>
26
27 #include "macdrv.h"
28 #include "winuser.h"
29 #include "wine/server.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
32
33 #ifndef kIOPMAssertionTypePreventUserIdleDisplaySleep
34 #define kIOPMAssertionTypePreventUserIdleDisplaySleep CFSTR("PreventUserIdleDisplaySleep")
35 #endif
36 #ifndef kCFCoreFoundationVersionNumber10_7
37 #define kCFCoreFoundationVersionNumber10_7      635.00
38 #endif
39
40 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
41
42
43 /**************************************************************************
44  *              debugstr_cf
45  */
46 const char* debugstr_cf(CFTypeRef t)
47 {
48     CFStringRef s;
49     const char* ret;
50
51     if (!t) return "(null)";
52
53     if (CFGetTypeID(t) == CFStringGetTypeID())
54         s = t;
55     else
56         s = CFCopyDescription(t);
57     ret = CFStringGetCStringPtr(s, kCFStringEncodingUTF8);
58     if (ret) ret = debugstr_a(ret);
59     if (!ret)
60     {
61         const UniChar* u = CFStringGetCharactersPtr(s);
62         if (u)
63             ret = debugstr_wn((const WCHAR*)u, CFStringGetLength(s));
64     }
65     if (!ret)
66     {
67         UniChar buf[200];
68         int len = min(CFStringGetLength(s), sizeof(buf)/sizeof(buf[0]));
69         CFStringGetCharacters(s, CFRangeMake(0, len), buf);
70         ret = debugstr_wn(buf, len);
71     }
72     if (s != t) CFRelease(s);
73     return ret;
74 }
75
76
77 /***********************************************************************
78  *              set_app_icon
79  */
80 static void set_app_icon(void)
81 {
82     CFArrayRef images = create_app_icon_images();
83     if (images)
84     {
85         macdrv_set_application_icon(images);
86         CFRelease(images);
87     }
88 }
89
90
91 /***********************************************************************
92  *              process_attach
93  */
94 static BOOL process_attach(void)
95 {
96     SessionAttributeBits attributes;
97     OSStatus status;
98
99     assert(NUM_EVENT_TYPES <= sizeof(macdrv_event_mask) * 8);
100
101     status = SessionGetInfo(callerSecuritySession, NULL, &attributes);
102     if (status != noErr || !(attributes & sessionHasGraphicAccess))
103         return FALSE;
104
105     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
106
107     macdrv_err_on = ERR_ON(macdrv);
108     if (macdrv_start_cocoa_app(GetTickCount64()))
109     {
110         ERR("Failed to start Cocoa app main loop\n");
111         return FALSE;
112     }
113
114     set_app_icon();
115     macdrv_clipboard_process_attach();
116
117     return TRUE;
118 }
119
120
121 /***********************************************************************
122  *              thread_detach
123  */
124 static void thread_detach(void)
125 {
126     struct macdrv_thread_data *data = macdrv_thread_data();
127
128     if (data)
129     {
130         macdrv_destroy_event_queue(data->queue);
131         if (data->keyboard_layout_uchr)
132             CFRelease(data->keyboard_layout_uchr);
133         HeapFree(GetProcessHeap(), 0, data);
134     }
135 }
136
137
138 /***********************************************************************
139  *              set_queue_display_fd
140  *
141  * Store the event queue fd into the message queue
142  */
143 static void set_queue_display_fd(int fd)
144 {
145     HANDLE handle;
146     int ret;
147
148     if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle))
149     {
150         MESSAGE("macdrv: Can't allocate handle for event queue fd\n");
151         ExitProcess(1);
152     }
153     SERVER_START_REQ(set_queue_fd)
154     {
155         req->handle = wine_server_obj_handle(handle);
156         ret = wine_server_call(req);
157     }
158     SERVER_END_REQ;
159     if (ret)
160     {
161         MESSAGE("macdrv: Can't store handle for event queue fd\n");
162         ExitProcess(1);
163     }
164     CloseHandle(handle);
165 }
166
167
168 /***********************************************************************
169  *              macdrv_init_thread_data
170  */
171 struct macdrv_thread_data *macdrv_init_thread_data(void)
172 {
173     struct macdrv_thread_data *data = macdrv_thread_data();
174
175     if (data) return data;
176
177     if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
178     {
179         ERR("could not create data\n");
180         ExitProcess(1);
181     }
182
183     if (!(data->queue = macdrv_create_event_queue(macdrv_handle_event)))
184     {
185         ERR("macdrv: Can't create event queue.\n");
186         ExitProcess(1);
187     }
188
189     data->keyboard_layout_uchr = macdrv_copy_keyboard_layout(&data->keyboard_type, &data->iso_keyboard);
190     macdrv_compute_keyboard_layout(data);
191
192     set_queue_display_fd(macdrv_get_event_queue_fd(data->queue));
193     TlsSetValue(thread_data_tls_index, data);
194
195     return data;
196 }
197
198
199 /***********************************************************************
200  *              DllMain
201  */
202 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
203 {
204     BOOL ret = TRUE;
205
206     switch(reason)
207     {
208     case DLL_PROCESS_ATTACH:
209         IME_RegisterClasses(hinst);
210         ret = process_attach();
211         break;
212     case DLL_THREAD_DETACH:
213         thread_detach();
214         break;
215     }
216     return ret;
217 }
218
219 /***********************************************************************
220  *              SystemParametersInfo (MACDRV.@)
221  */
222 BOOL CDECL macdrv_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
223 {
224     switch (action)
225     {
226     case SPI_GETSCREENSAVEACTIVE:
227         if (ptr_param)
228         {
229             CFDictionaryRef assertionStates;
230             IOReturn status = IOPMCopyAssertionsStatus(&assertionStates);
231             if (status == kIOReturnSuccess)
232             {
233                 CFNumberRef count = CFDictionaryGetValue(assertionStates, kIOPMAssertionTypeNoDisplaySleep);
234                 CFNumberRef count2 = CFDictionaryGetValue(assertionStates, kIOPMAssertionTypePreventUserIdleDisplaySleep);
235                 long longCount = 0, longCount2 = 0;
236
237                 if (count)
238                     CFNumberGetValue(count, kCFNumberLongType, &longCount);
239                 if (count2)
240                     CFNumberGetValue(count2, kCFNumberLongType, &longCount2);
241
242                 *(BOOL *)ptr_param = !longCount && !longCount2;
243                 CFRelease(assertionStates);
244             }
245             else
246             {
247                 WARN("Could not determine screen saver state, error code %d\n", status);
248                 *(BOOL *)ptr_param = TRUE;
249             }
250             return TRUE;
251         }
252         break;
253
254     case SPI_SETSCREENSAVEACTIVE:
255         {
256             static IOPMAssertionID powerAssertion = kIOPMNullAssertionID;
257             if (int_param)
258             {
259                 if (powerAssertion != kIOPMNullAssertionID)
260                 {
261                     IOPMAssertionRelease(powerAssertion);
262                     powerAssertion = kIOPMNullAssertionID;
263                 }
264             }
265             else if (powerAssertion == kIOPMNullAssertionID)
266             {
267                 CFStringRef assertName;
268                 /*Are we running Lion or later?*/
269                 if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_7)
270                     assertName = kIOPMAssertionTypePreventUserIdleDisplaySleep;
271                 else
272                     assertName = kIOPMAssertionTypeNoDisplaySleep;
273                 IOPMAssertionCreateWithName( assertName, kIOPMAssertionLevelOn,
274                                              CFSTR("Wine Process requesting no screen saver"),
275                                              &powerAssertion);
276             }
277         }
278         break;
279     }
280     return FALSE;
281 }