winemac: Associate an event queue with each thread that creates windows and with...
[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 "macdrv.h"
25 #include "wine/server.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
28
29
30 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
31
32
33 /***********************************************************************
34  *              process_attach
35  */
36 static BOOL process_attach(void)
37 {
38     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
39
40     macdrv_err_on = ERR_ON(macdrv);
41     if (macdrv_start_cocoa_app())
42     {
43         ERR("Failed to start Cocoa app main loop\n");
44         return FALSE;
45     }
46
47     return TRUE;
48 }
49
50
51 /***********************************************************************
52  *              thread_detach
53  */
54 static void thread_detach(void)
55 {
56     struct macdrv_thread_data *data = macdrv_thread_data();
57
58     if (data)
59     {
60         macdrv_destroy_event_queue(data->queue);
61         HeapFree(GetProcessHeap(), 0, data);
62     }
63 }
64
65
66 /***********************************************************************
67  *              set_queue_display_fd
68  *
69  * Store the event queue fd into the message queue
70  */
71 static void set_queue_display_fd(int fd)
72 {
73     HANDLE handle;
74     int ret;
75
76     if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle))
77     {
78         MESSAGE("macdrv: Can't allocate handle for event queue fd\n");
79         ExitProcess(1);
80     }
81     SERVER_START_REQ(set_queue_fd)
82     {
83         req->handle = wine_server_obj_handle(handle);
84         ret = wine_server_call(req);
85     }
86     SERVER_END_REQ;
87     if (ret)
88     {
89         MESSAGE("macdrv: Can't store handle for event queue fd\n");
90         ExitProcess(1);
91     }
92     CloseHandle(handle);
93 }
94
95
96 /***********************************************************************
97  *              macdrv_init_thread_data
98  */
99 struct macdrv_thread_data *macdrv_init_thread_data(void)
100 {
101     struct macdrv_thread_data *data = macdrv_thread_data();
102
103     if (data) return data;
104
105     if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
106     {
107         ERR("could not create data\n");
108         ExitProcess(1);
109     }
110
111     if (!(data->queue = macdrv_create_event_queue()))
112     {
113         ERR("macdrv: Can't create event queue.\n");
114         ExitProcess(1);
115     }
116
117     set_queue_display_fd(macdrv_get_event_queue_fd(data->queue));
118     TlsSetValue(thread_data_tls_index, data);
119
120     return data;
121 }
122
123
124 /***********************************************************************
125  *              DllMain
126  */
127 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
128 {
129     BOOL ret = TRUE;
130
131     switch(reason)
132     {
133     case DLL_PROCESS_ATTACH:
134         ret = process_attach();
135         break;
136     case DLL_THREAD_DETACH:
137         thread_detach();
138         break;
139     }
140     return ret;
141 }