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