1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2014-2018. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #if defined(_WIN32)
22 #include <wx/msw/private.h> // for wxSetInstance
23 #endif
24
25 #include "wxe_impl.h"
26
27 ErlNifTid wxe_thread;
28
29 ErlNifMutex *wxe_status_m;
30 ErlNifCond *wxe_status_c;
31
32 int wxe_status = WXE_NOT_INITIATED;
33
34 ErlNifMutex * wxe_batch_locker_m;
35 ErlNifCond * wxe_batch_locker_c;
36 ErlNifPid init_caller;
37
38 #ifdef __DARWIN__
39 extern "C" {
40 int erl_drv_stolen_main_thread_join(ErlNifTid tid, void **respp);
41 int erl_drv_steal_main_thread(char *name,
42 ErlNifTid *dtid,
43 void* (*func)(void*),
44 void* arg,
45 ErlNifThreadOpts *opts);
46 }
47 #endif
48
49 void *wxe_main_loop(void * );
50
51 /* ************************************************************
52 * START AND STOP of driver thread
53 * ************************************************************/
54
start_native_gui(ErlNifEnv * env)55 int start_native_gui(ErlNifEnv *env)
56 {
57 int res;
58 wxe_status_m = enif_mutex_create((char *) "wxe_status_m");
59 wxe_status_c = enif_cond_create((char *)"wxe_status_c");
60
61 wxe_batch_locker_m = enif_mutex_create((char *)"wxe_batch_locker_m");
62 wxe_batch_locker_c = enif_cond_create((char *)"wxe_batch_locker_c");
63 enif_self(env, &init_caller);
64
65 #ifdef __DARWIN__
66 res = erl_drv_steal_main_thread((char *)"wxwidgets",
67 &wxe_thread,wxe_main_loop,(void *) NULL,NULL);
68 #else
69 ErlNifThreadOpts *opts = enif_thread_opts_create((char *)"wx thread");
70 opts->suggested_stack_size = 8192;
71 res = enif_thread_create((char *)"wxwidgets",
72 &wxe_thread,wxe_main_loop,(void *) NULL,opts);
73 enif_thread_opts_destroy(opts);
74 #endif
75 if(res == 0) {
76 enif_mutex_lock(wxe_status_m);
77 for(;wxe_status == WXE_NOT_INITIATED;) {
78 enif_cond_wait(wxe_status_c, wxe_status_m);
79 }
80 enif_mutex_unlock(wxe_status_m);
81 return wxe_status;
82 } else {
83 wxString msg;
84 msg.Printf(wxT("Erlang failed to create wxe-thread %d\r\n"), res);
85 send_msg("error", &msg);
86 return -1;
87 }
88 }
89
stop_native_gui(ErlNifEnv * env)90 void stop_native_gui(ErlNifEnv* env)
91 {
92 if(wxe_status == WXE_INITIATED) {
93 meta_command(env, WXE_SHUTDOWN, NULL);
94 }
95 #ifdef __DARWIN__
96 erl_drv_stolen_main_thread_join(wxe_thread, NULL);
97 #else
98 enif_thread_join(wxe_thread, NULL);
99 #endif
100 enif_mutex_destroy(wxe_status_m);
101 enif_cond_destroy(wxe_status_c);
102 enif_mutex_destroy(wxe_batch_locker_m);
103 enif_cond_destroy(wxe_batch_locker_c);
104 }
105
106 /* ************************************************************
107 * wxWidgets Thread
108 * ************************************************************/
109
wxe_main_loop(void * _unused)110 void *wxe_main_loop(void * _unused)
111 {
112 int result;
113 int argc = 1;
114 wxChar temp[128] = L"Erlang";
115
116 size_t app_len = 127;
117 char app_title_buf[128];
118 int res = enif_getenv("WX_APP_TITLE", app_title_buf, &app_len);
119 if (res == 0) {
120 wxString title = wxString::FromUTF8(app_title_buf);
121 int size = title.Length() < 127 ? title.Length() : 126;
122 for(int i = 0; i < size; i++) {
123 temp[i] = title[i];
124 }
125 temp[size] = 0;
126 }
127
128 wxChar * argv[] = {(wxChar *)temp, NULL};
129
130 #ifdef _WIN32
131 // Setup that wxWidgets should look for cursors and icons in
132 // this dll and not in werl.exe (which is the default)
133 HMODULE WXEHandle = GetModuleHandle(_T("wxe_driver"));
134 wxSetInstance((HINSTANCE) WXEHandle);
135 #endif
136
137 wxe_ps_init();
138 result = wxEntry(argc, argv);
139 // fprintf(stderr, "WXWidgets quits main loop %d \r\n", result);
140 if(result >= 0 && wxe_status == WXE_INITIATED) {
141 /* We are done try to make a clean exit */
142 wxe_status = WXE_EXITED;
143 #ifndef __DARWIN__
144 enif_thread_exit(NULL);
145 #endif
146 return NULL;
147 } else {
148 enif_mutex_lock(wxe_status_m);
149 wxe_status = WXE_ERROR;
150 enif_cond_signal(wxe_status_c);
151 enif_mutex_unlock(wxe_status_m);
152 // driver_pdl_dec_refc(pdl);
153 return NULL;
154 }
155 }
156