1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "pch.h"
30
31 #include "toolkit.h"
32
33 #include <cx/allocator.h>
34 #include <cx/mempool.h>
35
36 #include "../common/context.h"
37 #include "../common/document.h"
38 #include "../common/toolbar.h"
39 #include "../common/properties.h"
40
41 #include "icons.h"
42
43 #include "MainWindow.xaml.h"
44
45 #include "App.xaml.h"
46
47 using namespace winrt;
48 using namespace Microsoft::
UI::Xaml;
49 using namespace Microsoft::
UI::Xaml::Controls;
50 using namespace Microsoft::
UI::Xaml::XamlTypeInfo;
51 using namespace Microsoft::
UI::Xaml::Markup;
52 using namespace Windows::
UI::Xaml::Interop;
53 using namespace winrt::Windows::Foundation;
54 using namespace Windows::
UI::Core;
55
56 static const char* application_name;
57
58 static ui_callback startup_func;
59 static void* startup_data;
60
61 static ui_callback open_func;
62 void* open_data;
63
64 static ui_callback exit_func;
65 void* exit_data;
66
67 static ui_callback appclose_fnc;
68
69 static void* appclose_udata;
70
71
72 static UiObject* active_window;
73
74 static winrt::Microsoft::
UI::Dispatching::DispatcherQueue uiDispatcherQueue = { nullptr };
75
76 void ui_app_run_startup() {
77 uiDispatcherQueue = winrt::Microsoft::
UI::Dispatching::DispatcherQueue::GetForCurrentThread();
78
79 if (startup_func) {
80 startup_func(
NULL, startup_data);
81 }
82 }
83
84 class App : public ApplicationT<App, IXamlMetadataProvider> {
85 public:
86 void OnLaunched(LaunchActivatedEventArgs
const&) {
87 Resources().MergedDictionaries().Append(XamlControlsResources());
88 if (startup_func) {
89 startup_func(
NULL, startup_data);
90 }
91
92
93
94 }
95 IXamlType GetXamlType(TypeName
const& type) {
96 return provider.GetXamlType(type);
97 }
98 IXamlType GetXamlType(hstring
const& fullname) {
99 return provider.GetXamlType(fullname);
100 }
101 com_array<XmlnsDefinition> GetXmlnsDefinitions() {
102 return provider.GetXmlnsDefinitions();
103 }
104 private:
105 XamlControlsXamlMetaDataProvider provider;
106 };
107
108 UiWidget::UiWidget(winrt::Microsoft::
UI::Xaml::UIElement& elm) : uielement(elm) {}
109
110 extern "C" void destroy_ui_window_wrapper(
void* ptr) {
111 UiWindow* win = (UiWindow*)ptr;
112 delete win;
113 }
114
115 extern "C" void destroy_ui_widget_wrapper(
void* ptr) {
116 UiWidget* widget = (UiWidget*)ptr;
117 delete widget;
118 }
119
120 extern "C" void destroy_ui_container_wrapper(
void* ptr) {
121 UiContainer* ctn = (UiContainer*)ptr;
122 delete ctn;
123 }
124
125 void ui_context_add_window_destructor(UiContext* ctx, UiWindow* win) {
126 cxMempoolRegister(ctx->mp, win, destroy_ui_window_wrapper);
127 }
128
129 void ui_context_add_widget_destructor(UiContext* ctx, UiWidget* widget) {
130 cxMempoolRegister(ctx->mp, widget, destroy_ui_widget_wrapper);
131 }
132
133 void ui_context_add_container_destructor(UiContext* ctx, UiContainer *container) {
134 cxMempoolRegister(ctx->mp, container, destroy_ui_container_wrapper);
135 }
136
137
138 UiEvent ui_create_int_event(UiObject* obj,
int64_t i) {
139 UiEvent evt;
140 evt.obj = obj;
141 evt.window = obj->window;
142 evt.document = obj->ctx->document;
143 evt.eventdata = nullptr;
144 evt.intval = i;
145 return evt;
146 }
147
148
149 #include <MddBootstrap.h>
150
151 void ui_appsdk_bootstrap(
void) {
152 const UINT32 majorMinorVersion{ 0x00010002 };
153 PCWSTR versionTag{
""L };
154 const PACKAGE_VERSION minVersion{};
155
156 const HRESULT hr = MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion);
157 if (
FAILED(hr)) {
158 exit(
102);
159 }
160 }
161
162 void ui_init(
const char* appname,
int argc,
char** argv) {
163 application_name = appname;
164
165
166
167 uic_init_global_context();
168 uic_docmgr_init();
169 uic_menu_init();
170 uic_toolbar_init();
171
172 uic_load_app_properties();
173 }
174
175 const char* ui_appname() {
176 return application_name;
177 }
178
179 void ui_onstartup(ui_callback f,
void* userdata) {
180 startup_func = f;
181 startup_data = userdata;
182 }
183
184 void ui_onopen(ui_callback f,
void* userdata) {
185 open_func = f;
186 open_data = userdata;
187 }
188
189 void ui_onexit(ui_callback f,
void* userdata) {
190 exit_func = f;
191 exit_data = userdata;
192 }
193
194 void ui_main() {
195
196
197
198
199
200
201
202
203
204
205 {
206 void (
WINAPI * pfnXamlCheckProcessRequirements)();
207 auto module = ::LoadLibrary(
"Microsoft.ui.xaml.dll"L);
208 if (module)
209 {
210 pfnXamlCheckProcessRequirements = reinterpret_cast<decltype(pfnXamlCheckProcessRequirements)>(GetProcAddress(module,
"XamlCheckProcessRequirements"));
211 if (pfnXamlCheckProcessRequirements)
212 {
213 (*pfnXamlCheckProcessRequirements)();
214 }
215
216 ::FreeLibrary(module);
217 }
218 }
219
220 winrt::init_apartment(winrt::apartment_type::single_threaded);
221 ::winrt::Microsoft::
UI::Xaml::Application::Start(
222 [](
auto&&)
223 {
224 ::winrt::make<::winrt::winui::implementation::App>();
225 });
226 }
227
228 class UiWin {
229 public:
230 Window window;
231 };
232
233 void ui_show(UiObject* obj) {
234 if (obj->wobj) {
235 obj->wobj->window.Activate();
236 }
else if(obj->widget && obj->widget->Show) {
237 obj->widget->Show();
238 }
239 }
240
241 void ui_close(UiObject* obj) {
242 if (obj->wobj) {
243 obj->wobj->window.Close();
244 }
245 }
246
247 static void ui_job_thread(UiJob* job) {
248 if (!job->job_func(job->job_data) && job->finish_callback) {
249 bool isQueued = uiDispatcherQueue.TryEnqueue([job]()
250 {
251 UiEvent event;
252 event.obj = job->obj;
253 event.window = job->obj->window;
254 event.document = job->obj->ctx->document;
255 event.intval =
0;
256 event.eventdata =
NULL;
257 job->finish_callback(&event, job->finish_data);
258 delete job;
259 });
260 if (!isQueued) {
261
262 exit(-
1);
263 }
264 }
265 else {
266 delete job;
267 }
268 }
269
270 UIEXPORT void ui_job(UiObject* obj, ui_threadfunc tf,
void* td, ui_callback f,
void* fd) {
271 UiJob* job = new UiJob;
272 job->obj = obj;
273 job->job_func = tf;
274 job->job_data = td;
275 job->finish_callback = f;
276 job->finish_data = fd;
277
278 std::thread jobThread(ui_job_thread, job);
279 jobThread.detach();
280 }
281
282 UIEXPORT void ui_call_mainthread(ui_threadfunc tf,
void* td) {
283 bool isQueued = uiDispatcherQueue.TryEnqueue([tf, td]()
284 {
285 (
void)tf(td);
286 });
287 if (!isQueued) {
288
289 exit(-
1);
290 }
291 }
292
293 static UiJob kill_job;
294
295 static void ui_threadpool_run(UiThreadpool* pool) {
296 for (;;) {
297 UiJob* job = pool->GetJob();
298 if (job == &kill_job) {
299 return;
300 }
301 else if (job) {
302 ui_job_thread(job);
303 }
304 }
305 }
306
307 UiThreadpool::UiThreadpool(
int nthreads) {
308 for (
int i =
0; i < nthreads; i++) {
309 std::thread thread(ui_threadpool_run, this);
310 thread.detach();
311 }
312 }
313
314 void UiThreadpool::EnqueueJob(UiJob* job)
315 {
316 std::unique_lock<std::mutex> lock(mutex);
317 queue.push(job);
318 lock.unlock();
319 condition.notify_one();
320 }
321
322 UiJob* UiThreadpool::GetJob() {
323 std::unique_lock<std::mutex> lock(mutex);
324
325 UiJob* job = nullptr;
326 while (!job) {
327 if (queue.empty()) {
328 condition.wait(lock);
329 continue;
330 }
331 else
332 {
333 job = queue.front();
334 queue.pop();
335 }
336 }
337
338 return job;
339 }
340
341 UIEXPORT UiThreadpool* ui_threadpool_create(
int nthreads) {
342 return new UiThreadpool(nthreads);
343 }
344
345 UIEXPORT void ui_threadpool_destroy(UiThreadpool* pool) {
346
347 }
348
349 UIEXPORT void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc tf,
void* td, ui_callback f,
void* fd) {
350 UiJob* job = new UiJob;
351 job->obj = obj;
352 job->job_func = tf;
353 job->job_data = td;
354 job->finish_callback = f;
355 job->finish_data = fd;
356 pool->EnqueueJob(job);
357 }
358
359
360
361 void ui_set_widget_groups(UiContext *ctx,
UIWIDGET widget,
const int *groups) {
362 if(!groups) {
363 return;
364 }
365 size_t ngroups = uic_group_array_size(groups);
366 ui_set_widget_ngroups(ctx, widget, groups, ngroups);
367 }
368
369 void ui_set_widget_ngroups(UiContext *ctx,
UIWIDGET widget,
const int *groups,
size_t ngroups) {
370 if(ngroups >
0) {
371 uic_add_group_widget_i(ctx, widget, (ui_enablefunc)ui_set_enabled, groups, ngroups);
372 ui_set_enabled(widget,
FALSE);
373 }
374 }
375
376
377 UIEXPORT void ui_set_enabled(
UIWIDGET widget,
int enabled) {
378 Control ctrl = widget->uielement.as<Control>();
379 if (ctrl) {
380 ctrl.IsEnabled(enabled);
381 }
382 }
383