windowpp 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/bin/windowpp.js +86 -0
  2. package/cmake/embed_assets.py +144 -0
  3. package/framework/CMakeLists.txt +176 -0
  4. package/framework/include/windowpp/windowpp.h +704 -0
  5. package/framework/src/AppData/API/AppData.ts +137 -0
  6. package/framework/src/AppData/appdata_bridge.h +138 -0
  7. package/framework/src/AppData/appdata_manager.cpp +126 -0
  8. package/framework/src/AppData/appdata_manager.h +3 -0
  9. package/framework/src/FileSystem/API/FileSystem.ts +389 -0
  10. package/framework/src/FileSystem/Linux/filesearch.cpp +148 -0
  11. package/framework/src/FileSystem/Linux/readfile.cpp +79 -0
  12. package/framework/src/FileSystem/Linux/savefile.cpp +333 -0
  13. package/framework/src/FileSystem/MacOS/filesearch.cpp +149 -0
  14. package/framework/src/FileSystem/MacOS/readfile.cpp +80 -0
  15. package/framework/src/FileSystem/MacOS/savefile.cpp +264 -0
  16. package/framework/src/FileSystem/Windows/filesearch.cpp +195 -0
  17. package/framework/src/FileSystem/Windows/readfile.cpp +122 -0
  18. package/framework/src/FileSystem/Windows/savefile.cpp +290 -0
  19. package/framework/src/FileSystem/file_index_service.cpp +262 -0
  20. package/framework/src/FileSystem/file_index_service.h +55 -0
  21. package/framework/src/FileSystem/filesystem_bridge.h +243 -0
  22. package/framework/src/FileSystem/filesystem_handler.h +93 -0
  23. package/framework/src/FileSystem/filesystem_json.h +241 -0
  24. package/framework/src/FileSystem/filesystem_search_service.cpp +414 -0
  25. package/framework/src/FileSystem/filesystem_search_service.h +94 -0
  26. package/framework/src/Input/API/Input.ts +161 -0
  27. package/framework/src/Input/Linux/linux_key_utils.h +135 -0
  28. package/framework/src/Input/MacOS/macos_key_utils.h +137 -0
  29. package/framework/src/Input/Windows/win32_key_utils.h +199 -0
  30. package/framework/src/Input/input_bridge.h +192 -0
  31. package/framework/src/Input/input_service.cpp +584 -0
  32. package/framework/src/Input/input_service.h +21 -0
  33. package/framework/src/application.cpp +29 -0
  34. package/framework/src/common/hit_test.cpp +40 -0
  35. package/framework/src/common/image_loader.cpp +24 -0
  36. package/framework/src/common/paths.cpp +75 -0
  37. package/framework/src/filedrop/filedrop.cpp +316 -0
  38. package/framework/src/filedrop/filedrop.css +421 -0
  39. package/framework/src/filedrop/filedrop.hpp +92 -0
  40. package/framework/src/filedrop/filedrop.ts +183 -0
  41. package/framework/src/platform/API/App.ts +156 -0
  42. package/framework/src/platform/API/Window.ts +249 -0
  43. package/framework/src/platform/linux/app_linux.cpp +256 -0
  44. package/framework/src/platform/linux/app_linux.h +64 -0
  45. package/framework/src/platform/linux/linux_helpers.cpp +26 -0
  46. package/framework/src/platform/linux/linux_helpers.h +19 -0
  47. package/framework/src/platform/linux/tray_linux.cpp +21 -0
  48. package/framework/src/platform/linux/tray_linux.h +26 -0
  49. package/framework/src/platform/linux/window_linux.cpp +256 -0
  50. package/framework/src/platform/linux/window_linux.h +70 -0
  51. package/framework/src/platform/macos/app_macos.h +59 -0
  52. package/framework/src/platform/macos/app_macos.mm +223 -0
  53. package/framework/src/platform/macos/macos_helpers.h +21 -0
  54. package/framework/src/platform/macos/tray_macos.h +22 -0
  55. package/framework/src/platform/macos/tray_macos.mm +53 -0
  56. package/framework/src/platform/macos/window_macos.h +74 -0
  57. package/framework/src/platform/macos/window_macos.mm +318 -0
  58. package/framework/src/platform/platform_bridge.h +514 -0
  59. package/framework/src/platform/platform_factory.cpp +33 -0
  60. package/framework/src/platform/platform_factory.h +19 -0
  61. package/framework/src/platform/win32/app_win32.cpp +572 -0
  62. package/framework/src/platform/win32/app_win32.h +83 -0
  63. package/framework/src/platform/win32/tray_win32.cpp +57 -0
  64. package/framework/src/platform/win32/tray_win32.h +30 -0
  65. package/framework/src/platform/win32/win32_helpers.h +61 -0
  66. package/framework/src/platform/win32/window_win32.cpp +267 -0
  67. package/framework/src/platform/win32/window_win32.h +79 -0
  68. package/framework/src/renderer/webgpu.h +128 -0
  69. package/framework/src/renderer/webview/include/WebView2.h +48014 -0
  70. package/framework/src/renderer/webview/include/WebView2EnvironmentOptions.h +342 -0
  71. package/framework/src/renderer/webview/webview.h +13 -0
  72. package/framework/src/renderer/webview/webview_linux.cpp +392 -0
  73. package/framework/src/renderer/webview/webview_macos.mm +388 -0
  74. package/framework/src/renderer/webview/webview_win32.cpp +688 -0
  75. package/framework/src/renderer/webview/x64/WebView2Loader.dll +0 -0
  76. package/framework/src/renderer/webview/x64/WebView2Loader.lib +0 -0
  77. package/framework/src/renderer/webview/x64/WebView2LoaderStatic.lib +0 -0
  78. package/lib/build.js +112 -0
  79. package/lib/create.js +283 -0
  80. package/lib/dev.js +155 -0
  81. package/package.json +24 -0
  82. package/scripts/publish.js +67 -0
  83. package/scripts/sync-framework.js +73 -0
  84. package/templates/solid/CMakeLists.txt +56 -0
  85. package/templates/solid/frontend/package.json +22 -0
  86. package/templates/solid/frontend/vite.config.ts +25 -0
  87. package/templates/solid/main.cpp +72 -0
  88. package/templates/solid/package.json +12 -0
@@ -0,0 +1,392 @@
1
+ // ============================================================================
2
+ // webview_linux.cpp — Linux WebKitGTK implementation
3
+ // ============================================================================
4
+
5
+ #if defined(__linux__)
6
+
7
+ #include "../webview.h"
8
+ #include <webkit2/webkit2.h>
9
+ #include <gtk/gtk.h>
10
+ #include <cstring>
11
+ #include <memory>
12
+ #include <string>
13
+
14
+ namespace wpp {
15
+
16
+ namespace {
17
+
18
+ std::string wpp_dropzone_toggle_script(bool enabled) {
19
+ return enabled
20
+ ? "window.__wpp_dropzone_enabled = true;"
21
+ : "window.__wpp_dropzone_enabled = false; document.querySelectorAll('.wpp-dropzone-active').forEach(function(el){ el.classList.remove('wpp-dropzone-active'); });";
22
+ }
23
+
24
+ const char* wpp_dropzone_script() {
25
+ return R"JS(
26
+ (function() {
27
+ if (window.__wpp_dropzone_init) return;
28
+ window.__wpp_dropzone_init = true;
29
+ window.__wpp_dropzone_enabled = true;
30
+
31
+ var activeZone = null;
32
+ var pendingZone = null;
33
+ var cachedZones = [];
34
+ var outerBounds = null;
35
+ var refreshPending = false;
36
+ var framePending = false;
37
+ var _lastHit = null;
38
+ var observedZones = [];
39
+ var resizeObserver = typeof ResizeObserver === 'function'
40
+ ? new ResizeObserver(function() { scheduleRefreshZones(); })
41
+ : null;
42
+
43
+ var disconnectObservedZones = function() {
44
+ if (!resizeObserver) return;
45
+ for (var i = 0; i < observedZones.length; i++) {
46
+ resizeObserver.unobserve(observedZones[i]);
47
+ }
48
+ observedZones = [];
49
+ };
50
+
51
+ var refreshZones = function() {
52
+ refreshPending = false;
53
+ _lastHit = null;
54
+ disconnectObservedZones();
55
+ cachedZones = [];
56
+ outerBounds = null;
57
+ var zones = document.querySelectorAll('[data-dropzone]');
58
+ for (var i = 0; i < zones.length; i++) {
59
+ var zone = zones[i];
60
+ var rect = zone.getBoundingClientRect();
61
+ var zoneData = {
62
+ element: zone,
63
+ left: rect.left,
64
+ top: rect.top,
65
+ right: rect.right,
66
+ bottom: rect.bottom
67
+ };
68
+ cachedZones.push(zoneData);
69
+ if (resizeObserver) {
70
+ resizeObserver.observe(zone);
71
+ observedZones.push(zone);
72
+ }
73
+ if (!outerBounds) {
74
+ outerBounds = {left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom};
75
+ } else {
76
+ outerBounds.left = Math.min(outerBounds.left, rect.left);
77
+ outerBounds.top = Math.min(outerBounds.top, rect.top);
78
+ outerBounds.right = Math.max(outerBounds.right, rect.right);
79
+ outerBounds.bottom = Math.max(outerBounds.bottom, rect.bottom);
80
+ }
81
+ }
82
+ };
83
+
84
+ var scheduleRefreshZones = function() {
85
+ if (refreshPending) return;
86
+ refreshPending = true;
87
+ window.requestAnimationFrame(refreshZones);
88
+ };
89
+
90
+ var findDropZoneAt = function(x, y) {
91
+ if (!outerBounds || x < outerBounds.left || x > outerBounds.right || y < outerBounds.top || y > outerBounds.bottom) {
92
+ return null;
93
+ }
94
+ if (_lastHit && x >= _lastHit.left && x <= _lastHit.right && y >= _lastHit.top && y <= _lastHit.bottom) {
95
+ return _lastHit.element;
96
+ }
97
+ for (var i = cachedZones.length - 1; i >= 0; i--) {
98
+ var zone = cachedZones[i];
99
+ if (x >= zone.left && x <= zone.right && y >= zone.top && y <= zone.bottom) {
100
+ _lastHit = zone;
101
+ return zone.element;
102
+ }
103
+ }
104
+ _lastHit = null;
105
+ return null;
106
+ };
107
+
108
+ var updateActiveZone = function(zone) {
109
+ if (activeZone === zone) return;
110
+ if (activeZone) {
111
+ activeZone.classList.remove('wpp-dropzone-active');
112
+ }
113
+ activeZone = zone;
114
+ if (activeZone) {
115
+ activeZone.classList.add('wpp-dropzone-active');
116
+ }
117
+ };
118
+
119
+ var flushActiveZone = function() {
120
+ framePending = false;
121
+ updateActiveZone(window.__wpp_dropzone_enabled ? pendingZone : null);
122
+ };
123
+
124
+ var scheduleZoneUpdate = function(zone) {
125
+ pendingZone = zone;
126
+ if (framePending) return;
127
+ framePending = true;
128
+ window.requestAnimationFrame(flushActiveZone);
129
+ };
130
+
131
+ var setDropEffect = function(e, zone) {
132
+ if (!e.dataTransfer) return;
133
+ try { e.dataTransfer.dropEffect = zone ? 'copy' : 'none'; } catch (_) {}
134
+ };
135
+
136
+ document.addEventListener('dragenter', function(e) {
137
+ if (!window.__wpp_dropzone_enabled) return;
138
+ e.preventDefault();
139
+ if (!cachedZones.length) refreshZones();
140
+ var zone = findDropZoneAt(e.clientX, e.clientY);
141
+ setDropEffect(e, zone);
142
+ scheduleZoneUpdate(zone);
143
+ }, true);
144
+
145
+ document.addEventListener('dragover', function(e) {
146
+ if (!window.__wpp_dropzone_enabled) return;
147
+ e.preventDefault();
148
+ var zone = findDropZoneAt(e.clientX, e.clientY);
149
+ setDropEffect(e, zone);
150
+ scheduleZoneUpdate(zone);
151
+ }, true);
152
+
153
+ document.addEventListener('dragleave', function(e) {
154
+ if (!window.__wpp_dropzone_enabled) return;
155
+ e.preventDefault();
156
+ var related = e.relatedTarget;
157
+ if (!related || related === document.documentElement || related === document.body) {
158
+ pendingZone = null;
159
+ framePending = false;
160
+ _lastHit = null;
161
+ updateActiveZone(null);
162
+ }
163
+ }, true);
164
+
165
+ document.addEventListener('drop', function(e) {
166
+ if (!window.__wpp_dropzone_enabled) return;
167
+ e.preventDefault();
168
+ pendingZone = null;
169
+ framePending = false;
170
+ var zone = findDropZoneAt(e.clientX, e.clientY);
171
+ var zoneName = zone ? zone.getAttribute('data-dropzone') : null;
172
+ _lastHit = null;
173
+ updateActiveZone(null);
174
+
175
+ if (zoneName && window.__wpp_fileDrop__) {
176
+ var files = [];
177
+ if (e.dataTransfer && e.dataTransfer.files) {
178
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
179
+ var file = e.dataTransfer.files[i];
180
+ files.push({
181
+ name: file.name,
182
+ size: file.size,
183
+ type: file.type || 'application/octet-stream'
184
+ });
185
+ }
186
+ }
187
+ window.__wpp_fileDrop__(zoneName, files);
188
+ }
189
+ }, true);
190
+ window.addEventListener('dragover', function(e) {
191
+ if (!window.__wpp_dropzone_enabled) return;
192
+ e.preventDefault();
193
+ setDropEffect(e, findDropZoneAt(e.clientX, e.clientY));
194
+ }, true);
195
+ window.addEventListener('drop', function(e) {
196
+ if (!window.__wpp_dropzone_enabled) return;
197
+ e.preventDefault();
198
+ }, true);
199
+ window.addEventListener('resize', scheduleRefreshZones, true);
200
+ window.addEventListener('scroll', scheduleRefreshZones, true);
201
+ document.addEventListener('DOMContentLoaded', scheduleRefreshZones, true);
202
+ window.addEventListener('load', scheduleRefreshZones, true);
203
+ var attachMutationObserver = function() {
204
+ if (typeof MutationObserver !== 'function') return;
205
+ var target = document.documentElement || document.body;
206
+ if (!target || typeof target.nodeType !== 'number') return;
207
+ new MutationObserver(scheduleRefreshZones).observe(
208
+ target,
209
+ { childList: true, subtree: true, attributes: true, attributeFilter: ['data-dropzone'] }
210
+ );
211
+ };
212
+ if (typeof MutationObserver === 'function') {
213
+ attachMutationObserver();
214
+ document.addEventListener('DOMContentLoaded', attachMutationObserver, { once: true });
215
+ window.addEventListener('load', attachMutationObserver, { once: true });
216
+ }
217
+ refreshZones();
218
+ })();
219
+ )JS";
220
+ }
221
+
222
+ } // namespace
223
+
224
+ class LinuxWebView : public WebView {
225
+ public:
226
+ LinuxWebView(const WebViewConfig& config, xcb_window_t window);
227
+ ~LinuxWebView() override;
228
+
229
+ void load_url(const std::string& url) override;
230
+ void load_html(const std::string& html) override;
231
+ void execute_script(const std::string& script) override;
232
+ void send_message(const std::string& message) override;
233
+ void go_back() override;
234
+ void go_forward() override;
235
+ void reload() override;
236
+ void close() override;
237
+ void resize(int width, int height) override {
238
+ if (socket_) {
239
+ gtk_widget_set_size_request(socket_, width, height);
240
+ }
241
+ }
242
+
243
+ void set_drag_drop_enabled(bool enabled) override {
244
+ if (!webview_) return;
245
+ std::string script = wpp_dropzone_toggle_script(enabled);
246
+ webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(webview_), script.c_str(), nullptr, nullptr, nullptr);
247
+ }
248
+
249
+ private:
250
+ WebViewConfig config_;
251
+ xcb_window_t window_;
252
+ GtkWidget* webview_ = nullptr;
253
+ GtkWidget* socket_ = nullptr;
254
+ static bool gtk_init_done_;
255
+ };
256
+
257
+ bool LinuxWebView::gtk_init_done_ = false;
258
+
259
+ LinuxWebView::LinuxWebView(const WebViewConfig& config, xcb_window_t window)
260
+ : config_(config), window_(window) {
261
+
262
+ if (!gtk_init_done_) {
263
+ gtk_init(nullptr, nullptr);
264
+ gtk_init_done_ = true;
265
+ }
266
+
267
+ socket_ = gtk_socket_new();
268
+ gtk_widget_set_size_request(socket_, 800, 600);
269
+ gtk_widget_show(socket_);
270
+
271
+ GdkDisplay* display = gdk_display_get_default();
272
+ GdkScreen* screen = gdk_display_get_default_screen(display);
273
+ GtkCssProvider* provider = gtk_css_provider_get_default();
274
+ gtk_css_provider_load_from_data(provider, "window { background: white; }", -1, nullptr);
275
+ gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
276
+
277
+ WebKitUserContentManager* content_manager = webkit_user_content_manager_new();
278
+ WebKitUserScript* dropzone_script = webkit_user_script_new(
279
+ wpp_dropzone_script(),
280
+ WEBKIT_USER_CONTENT_INJECT_TOP_FRAME,
281
+ WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
282
+ nullptr,
283
+ nullptr);
284
+ webkit_user_content_manager_add_script(content_manager, dropzone_script);
285
+ webkit_user_script_unref(dropzone_script);
286
+
287
+ webview_ = webkit_web_view_new_with_user_content_manager(content_manager);
288
+ g_object_unref(content_manager);
289
+ gtk_container_add(GTK_CONTAINER(socket_), webview_);
290
+ gtk_widget_show(webview_);
291
+
292
+ gtk_socket_steal(socket_, window_);
293
+
294
+ if (!config_.custom_scheme.empty() && config_.scheme_handler) {
295
+ struct SchemeCallbackData {
296
+ std::function<wpp::SchemeResponse(const std::string&)> handler;
297
+ };
298
+ auto* data = new SchemeCallbackData{config_.scheme_handler};
299
+
300
+ webkit_web_context_register_uri_scheme(
301
+ webkit_web_context_get_default(),
302
+ config_.custom_scheme.c_str(),
303
+ [](WebKitURISchemeRequest* request, gpointer user_data) {
304
+ auto* d = static_cast<SchemeCallbackData*>(user_data);
305
+ const char* raw = webkit_uri_scheme_request_get_path(request);
306
+ std::string path(raw ? raw : "/");
307
+ if (path.empty()) path = "/";
308
+
309
+ wpp::SchemeResponse resp = d->handler(path);
310
+
311
+ gpointer body_copy = g_malloc(resp.body.size());
312
+ std::memcpy(body_copy, resp.body.data(), resp.body.size());
313
+ GInputStream* stream = g_memory_input_stream_new_from_data(
314
+ body_copy,
315
+ static_cast<gssize>(resp.body.size()),
316
+ g_free);
317
+ webkit_uri_scheme_request_finish(
318
+ request,
319
+ stream,
320
+ static_cast<gint64>(resp.body.size()),
321
+ resp.content_type.c_str());
322
+ g_object_unref(stream);
323
+ },
324
+ data,
325
+ [](gpointer d) {
326
+ delete static_cast<SchemeCallbackData*>(d);
327
+ });
328
+ }
329
+
330
+ if (!config_.initial_url.empty()) {
331
+ load_url(config_.initial_url);
332
+ } else if (!config_.initial_html.empty()) {
333
+ load_html(config_.initial_html);
334
+ }
335
+ }
336
+
337
+ LinuxWebView::~LinuxWebView() {
338
+ if (webview_) {
339
+ gtk_widget_destroy(webview_);
340
+ }
341
+ if (socket_) {
342
+ gtk_widget_destroy(socket_);
343
+ }
344
+ }
345
+
346
+ void LinuxWebView::load_url(const std::string& url) {
347
+ if (!webview_) return;
348
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview_), url.c_str());
349
+ }
350
+
351
+ void LinuxWebView::load_html(const std::string& html) {
352
+ if (!webview_) return;
353
+ webkit_web_view_load_html(WEBKIT_WEB_VIEW(webview_), html.c_str(), nullptr);
354
+ }
355
+
356
+ void LinuxWebView::execute_script(const std::string& script) {
357
+ if (!webview_) return;
358
+ webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(webview_), script.c_str(), nullptr, nullptr, nullptr);
359
+ }
360
+
361
+ void LinuxWebView::send_message(const std::string& message) {
362
+ if (!webview_) return;
363
+ std::string js = "window.webkit.messageHandlers.wpp.postMessage('" + message + "');";
364
+ webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(webview_), js.c_str(), nullptr, nullptr, nullptr);
365
+ }
366
+
367
+ void LinuxWebView::go_back() {
368
+ if (webview_) webkit_web_view_go_back(WEBKIT_WEB_VIEW(webview_));
369
+ }
370
+
371
+ void LinuxWebView::go_forward() {
372
+ if (webview_) webkit_web_view_go_forward(WEBKIT_WEB_VIEW(webview_));
373
+ }
374
+
375
+ void LinuxWebView::reload() {
376
+ if (webview_) webkit_web_view_reload(WEBKIT_WEB_VIEW(webview_));
377
+ }
378
+
379
+ void LinuxWebView::close() {
380
+ if (webview_) {
381
+ gtk_widget_destroy(webview_);
382
+ webview_ = nullptr;
383
+ }
384
+ }
385
+
386
+ std::unique_ptr<WebView> create_webview(const WebViewConfig& config, void* native_handle) {
387
+ return std::make_unique<LinuxWebView>(config, static_cast<xcb_window_t>(reinterpret_cast<uintptr_t>(native_handle)));
388
+ }
389
+
390
+ } // namespace wpp
391
+
392
+ #endif // __linux__