Compare commits

...

537 Commits
2.4.1 ... main

Author SHA1 Message Date
Albert
9dd20b5c98 Update frameless example 2025-03-25 16:12:31 -04:00
Albert
65fd9a8800 Fix out of screen 2025-03-25 16:10:59 -04:00
Albert
3c03d4f45c Fix GCC Warning - ICoreWebView2Controller 2025-03-19 12:20:50 -04:00
Albert
1f80350564 Win32 - Safer WM_EXITSIZEMOVE 2025-03-19 10:54:03 -04:00
Albert
4c8fc25b2d Fix zig warning - Win32 LONG 2025-03-18 19:10:36 -04:00
Albert
b59ddf1c0c Fix zig warning - Win32 LPVOID 2025-03-18 19:02:25 -04:00
Albert
5fafc9b6b6 Improve webkit-app-region precision 2025-03-18 19:00:16 -04:00
Albert
995f1ab25f Frameless + Transparent Screenshot 2025-03-18 17:58:21 -04:00
Albert
d274723ec6 Updating frameless example 2025-03-18 17:46:56 -04:00
Albert
9430e57040 New API - webui_set_transparent 2025-03-18 17:45:34 -04:00
Albert
78b163c350 Win32 - Up WebView Controller Version 2025-03-18 13:52:42 -04:00
Albert
af455d38ee webui_set_center - Linux 2025-03-17 17:22:04 -04:00
Albert
5c52beebfb Fix macOS Build 2025-03-17 15:03:42 -04:00
Albert
ea5e9a57fc Adding webui_set_resizable (macOS) - Not Tested 2025-03-17 14:54:47 -04:00
Albert
c50fcdf5da Adding webui_set_resizable (Linux) 2025-03-17 14:38:13 -04:00
Albert
433dcc25e0 Internal flags rename 2025-03-17 14:07:15 -04:00
Albert
c66b71a98c Renaming webui_wv_set_frameless to webui_set_frameless 2025-03-17 14:01:51 -04:00
Albert
f21f4f14e1 Adding webui_set_resizable (Win32) 2025-03-17 13:59:10 -04:00
Albert
84758f6742 Adding webui_set_center 2025-03-17 13:14:24 -04:00
Hassan DRAGA
aec0f654ba Frameless Example (Not complete) 2025-03-16 00:59:47 -04:00
Hassan DRAGA
ed3aae5790 New webui_minimize and webui_maximize (Not complete) 2025-03-16 00:59:02 -04:00
Hassan DRAGA
d2b40ee7e6 Minor tab spaces cleaning 2025-03-15 23:49:06 -04:00
Hassan DRAGA
25c7e3f16c hwnd check before use 2025-03-15 23:11:21 -04:00
Hassan DRAGA
361237669b macOS frameless window 2025-03-15 18:55:31 -04:00
Hassan DRAGA
c6d5b58352 Custom webkit-app-region implementation 2025-03-15 18:29:28 -04:00
Hassan DRAGA
7e257de1b0 Linux GTK Frameless 2025-03-15 16:13:10 -04:00
Hassan DRAGA
16aec7e181 Renaming webui_wv_set_headless to webui_wv_set_frameless 2025-03-15 15:56:59 -04:00
Hassan DRAGA
5415b19b5f
Merge pull request #570 from eliemichel/patch-2
Fix `WEBUI_STR_CAT_STATIC` on Windows
2025-03-15 15:13:52 -04:00
Hassan DRAGA
c9baba76b7
Merge pull request #568 from eliemichel/patch-1
Remove "index" argument from get_count()
2025-03-15 14:19:37 -04:00
Elie Michel
f4b9043288
Fix WEBUI_STR_CAT_STATIC on Windows
`strcat_s` expects the total destination size as second argument, contrary to `strncat`.
2025-03-15 13:07:28 +01:00
Elie Michel
facd97c107
Remove "index" argument from get_count()
Argument is not used, I suspect it ended up here as part of an abusive copy-paste!
2025-03-15 12:30:42 +01:00
Albert
223608479b macOS - Fix Quick Close WebView 2025-03-14 13:41:53 -04:00
Albert
305070eeb1 macOS - Fix missing symbol build 2025-03-14 12:43:57 -04:00
Albert
7d310a7c1f Fix macOS Build 2025-03-14 12:36:45 -04:00
Albert
d58e04ff05 Safer webui_clean 2025-03-14 12:13:00 -04:00
Albert
1b2f7b637b Fix macOS CPU usage 2025-03-14 12:05:24 -04:00
Albert
dacbfcd257 macOS - Adding _webui_macos_wv_start 2025-03-14 12:00:56 -04:00
Albert
b1595c766c macOS WebView adding exit Timer 2025-03-14 11:37:59 -04:00
Albert
130a26cc21 Remove Linux Tests 2025-03-12 13:35:26 -04:00
Albert
8bf01b0d3e Removing Tests 2025-03-12 13:28:34 -04:00
Albert
3a959d0402 Fix new lib name in macOS 2025-03-12 13:12:50 -04:00
Albert
6cca39ecac Rename examples lib name (Linux and macOS) 2025-03-12 12:42:02 -04:00
Albert
e019f00fad Rename lib name 2025-03-12 11:55:17 -04:00
Albert
fcd903d424 Merge branch 'main' of https://github.com/webui-dev/webui 2025-03-12 10:41:50 -04:00
Showns
6b61f311c8
Merge pull request #306 from iacore/patch-1
fix: add linux dynamic library "lib" prefix
2025-03-12 10:40:03 -04:00
Albert
7dddb64d92 New API - webui_wv_set_headless 2025-03-11 15:09:13 -04:00
Albert
bf1c8ada92 Fix minor warnings 2025-03-11 15:06:20 -04:00
Albert
e558709118 _webui_custom_browser_exist - macOS 2025-03-11 11:51:46 -04:00
Albert
b6457c88bb _webui_custom_browser_exist - Linux 2025-03-11 11:48:01 -04:00
Albert
8d9c6b275b Fix missing Ini _webui_custom_browser_exist 2025-03-11 11:47:25 -04:00
Albert
5ac66da94b _webui_custom_browser_exist - Windows Implementation
We still need macOS and Linux Implementation.
2025-03-10 18:28:37 -04:00
Albert
92324edf6f Adding new API webui_set_browser_folder 2025-03-10 17:50:58 -04:00
Albert
9926908e4b Up to Beta 4 2025-03-10 10:14:39 -04:00
Albert
fd716ddcac C++ - Adding memcpy and win32_get_hwnd 2025-03-07 16:04:21 -05:00
Albert
ef5df7f28c Adding webui_win32_get_hwnd 2025-03-07 11:30:59 -05:00
Albert
5d497e3b83 Merge branch 'main' of https://github.com/webui-dev/webui 2025-03-05 15:49:45 -05:00
Albert
02328acc6d Readme (Organizing Commands) 2025-03-05 15:49:18 -05:00
Showns
b4ce0284ae
Merge pull request #560 from webui-dev/0_14_0
break change: support zig `0.14.0`
2025-03-05 14:31:30 -05:00
Albert
61444bfaa7 Fix Firefox UI
Fix https://github.com/webui-dev/webui/issues/550
2025-03-05 12:47:49 -05:00
jinzhongjia
70b6689106 break change: support zig 0.14.0
Since then, 0.13.0 and previous versions cannot be supported
2025-03-06 00:13:44 +08:00
Albert
7b661f142b Updating Civetweb 2025-03-04 16:19:16 -05:00
Albert
72039fa0ca WebView - Fix Linux CPU Usage 2025-03-04 13:04:14 -05:00
Albert
bd2611ba60 Updating Readme - Adding App Build CMDs 2025-02-28 10:48:33 -05:00
Albert
93ec28addb Fix long-wait when WebView not available 2025-02-27 18:27:36 -05:00
Albert
52c1777c77 Mutex WebView Loop (Linux and macOS) 2025-02-27 17:27:39 -05:00
Albert
3734f9fe9f Adding internal _webui_webview_update 2025-02-27 16:49:39 -05:00
Albert
fb29c6cac4 Switch from Global Mutex to Window Mutex 2025-02-27 16:11:13 -05:00
Albert
18b5d14f8e Rename Mutex Var 2025-02-27 15:21:44 -05:00
Albert
f4e327208f Rename Mutex Macros 2025-02-27 15:18:01 -05:00
Showns
8c58fcb973
Merge pull request #559 from redking00/main
Fix #543
2025-02-27 13:50:25 -05:00
redking00
8f5a306574 Fix https://github.com/webui-dev/webui/issues/543 2025-02-27 18:20:45 +00:00
Albert
e92f9b7824 Enable All Workflows 2025-02-25 17:18:10 -05:00
Albert
c386758414 Enable Arch Linux Workflow 2025-02-25 17:16:02 -05:00
Albert
0f8925e358 Fix Arch Linux Clang 2025-02-25 17:15:02 -05:00
Albert
44971f9bca Fix RedHat Clang 2025-02-25 17:07:17 -05:00
Albert
8fa1fdb89d Adding OpenSSL to RedHat 2025-02-25 16:41:13 -05:00
Albert
cdebbfee0a Enabling RedHat Workflow 2025-02-25 16:33:56 -05:00
Albert
bf94687089 Updating RedHat Workflow 2025-02-25 16:33:12 -05:00
Albert
36676f68ff Fix Arch Linux Workspace Permission 2025-02-25 16:25:19 -05:00
Albert
56f1e4eb2b Fix Arch Linux Git Workspace 2025-02-25 16:17:29 -05:00
Albert
553e65e218 Fix Arch Linux Artifact 2025-02-25 16:11:01 -05:00
Albert
d9af5b2c17 Adding Arch Linux Artifact 2025-02-25 15:25:06 -05:00
Albert
27c877f73f Remove Arch Linux Examples Test 2025-02-25 15:18:38 -05:00
Albert
c9c7562496 Fix Arch Linux Git 2025-02-25 15:18:20 -05:00
Albert
1594f9e40d Test Docker Host Files Access 2025-02-25 15:11:45 -05:00
Albert
133da5072b Test Arch Linux Docker 2025-02-25 15:06:16 -05:00
Showns
8eb49857c1
Merge pull request #555 from webui-dev/zig_master
fix: zig master change
2025-02-25 14:51:02 -05:00
Albert
6c299e49ed Temporary Disable Workflow 2025-02-25 14:49:47 -05:00
Albert
ad869075d2 Adding Arch Linux WorkFlow 2025-02-25 14:46:29 -05:00
Albert
0d8ed71a8a Temporary Disable Workflow 2025-02-25 14:45:08 -05:00
jinzhongjia
c512af1e6c fxi: zig master change 2025-02-23 16:47:35 +08:00
Albert
63284fe2a7 Removing Linux RedHat Build 2025-02-18 09:14:27 -05:00
Albert
f2961585e2 Adding Linux RedHat Build 2025-02-14 17:19:16 -05:00
Albert
fb5c2ab616 Adding webui_interface_get_context
* Note: Wrappers does not need to implement any `webui_interface_xx` APIs if not needed by the wrapper.
2025-02-14 16:45:58 -05:00
Albert
c52ac5fc4a Adding C++ set_context 2025-02-14 16:34:12 -05:00
Albert
3ff8742f3e Adding webui_memcpy
* This can help wrappers like Bun
2025-02-11 17:21:52 -05:00
Albert
27088bd5d2 Adding webui_set_context and webui_get_context
* webui_set_context
* webui_get_context

Inf: https://github.com/webui-dev/webui/issues/551
2025-02-11 11:26:13 -05:00
Albert
8a7ea878b5 webui_set_custom_parameters - Ignore default parameters 2025-02-10 14:35:02 -05:00
Albert
2d3a68ebea webui.js - Adding allowNavigation
More inf: https://github.com/webui-dev/webui/issues/541
2025-02-06 15:04:55 -05:00
Albert
1eb06bb0c7 Fix show_browser
https://github.com/webui-dev/zig-webui/issues/79
2025-02-06 12:22:19 -05:00
Albert
ddc94db8db New Example - ChatGPT HTTPS API in C 2025-01-31 17:00:59 -05:00
Albert
0268c3723b Update date from 2024 to 2025 2025-01-30 15:52:24 -05:00
Albert
7f60505709 Fix internal _webui_external_file_handler 2025-01-28 12:43:23 -05:00
Albert
f412473dca Downgrade Linux Workflows GCC from v14 to v11 (Prefix) 2025-01-27 12:57:29 -05:00
Albert
728cd8370d Downgrade Linux Workflows GCC from v14 to v11 2025-01-27 12:55:13 -05:00
Albert
0a088943d5 Linux Workflows - Disable Test (Temporary) 2025-01-27 12:54:38 -05:00
Albert
cdda40df5f Downgrade Linux Workflows from 24.01 to 22.04 2025-01-27 12:43:01 -05:00
Albert
2adfee2e04 Up Linux Workflows from 20.01 to 22.04 2025-01-27 12:28:35 -05:00
Albert
c05a18a2f4 Update Linux workflows 2025-01-27 12:16:27 -05:00
Albert
9e68b911ae Update Civetweb 2025-01-27 11:56:46 -05:00
Albert
5486cb4e9c Fix strcat warnings 2025-01-27 11:44:24 -05:00
Albert
2e9d65d2bc Fix strncat buffer size 2025-01-27 11:01:11 -05:00
Albert
c9087c35b1 Adding webui_interface_set_response_file_handler 2025-01-24 16:56:25 -05:00
Showns
4dcf4ce07c
Merge pull request #544 from guimaai/main
Fix csv_size size
2025-01-23 09:11:06 -05:00
guimaai
e0b09e3a49 Fix csv_size size 2025-01-19 01:33:33 +08:00
Showns
d7a87ed6f9
Merge pull request #542 from createc-uk/createc/c++_missing_return_values
Add missing returns to c++ interface
2025-01-16 11:45:23 -05:00
Shaun
737ee76cbc Upped CMakeLists.txt CXX version to c++17 for std::string_view 2025-01-16 15:53:56 +00:00
Shaun
b6f70527be Added missing returns and removed some whitespace in c++ interface 2025-01-16 15:52:05 +00:00
Showns
c9abbc9cdb
Merge pull request #538 from JackBoosY/jack/update-cmake
Update CMakeLists
2025-01-07 09:21:37 -05:00
jyu49
d695c5b8fc Remove duplicate define 2025-01-06 13:25:59 +08:00
jyu49
d757120977 Update CMakeLists 2025-01-06 13:23:56 +08:00
Albert
0ff3b1351b Adding Interfaces 2024-12-20 11:31:26 -05:00
Albert
41497e1a52 Fix double all-events in Bind interface 2024-12-20 10:50:39 -05:00
Albert
ef18fdc772 Fix Multi Window Script
Ref: https://github.com/webui-dev/deno-webui/issues/70
2024-12-19 12:41:56 -05:00
Albert
09128cefb0 Update macOS Obj-C Buffer Size 2024-12-04 16:43:58 -05:00
Albert
0f4cf1a4b8 Fix GNU Makefile - CreateProcess failed
process_begin: CreateProcess(NULL, uname, ...) failed.
GNUmakefile:30: pipe: No error
process_begin: CreateProcess(NULL, uname, ...) failed.
GNUmakefile:111: pipe: No error
process_begin: CreateProcess(NULL, uname, ...) failed.
GNUmakefile:144: pipe: No error
2024-11-29 14:41:46 -05:00
Albert
734f00aaac CI - Remove macOS x64 Examples Build 2024-11-22 18:07:05 -05:00
Albert
3c9137eef5 CI - Fix IF Syntax (macOS) 2024-11-22 18:02:58 -05:00
Albert
6511bc56d8 CI - Remove macOS OpenSSL Build 2024-11-22 17:52:02 -05:00
Albert
2a5a449900 CI - Fix IF Syntax (macOS) 2024-11-22 17:40:08 -05:00
Albert
a3ea3619ee CI - Fix IF Syntax (macOS) 2024-11-22 17:36:51 -05:00
Albert
a509155eaf CI - Fix OpenSSL Path (macOS) 2024-11-22 17:34:49 -05:00
Albert
9d2b80d3b3 Fix Clang Buffer Warning 2024-11-22 17:34:16 -05:00
Albert
e67788ad70 CI - Fix x64 OpenSSL (MacOS) 2024-11-22 17:27:14 -05:00
Albert
9814a18e0a Fix Strcat Warning 2024-11-22 17:26:45 -05:00
Albert
7189093a5d CI - Adding x64 OpenSSL for macOS 2024-11-22 17:17:08 -05:00
Albert
7156f6a1e2 CI - Adding ARCH_TARGET (macOS) 2024-11-22 16:43:51 -05:00
Albert
4a67f91554 Adding ARCH_TARGET x64 (macOS) 2024-11-22 16:36:30 -05:00
Albert
e01fb64666 Fix macOS WebView CPU Usage 2024-11-22 15:40:28 -05:00
Albert
984de15efa Fix Linux WebView CPU Usage 2024-11-22 15:38:58 -05:00
Albert
3084ff3e26 Fix Windows WebView CPU Usage 2024-11-22 15:33:05 -05:00
Albert
2a406f5276 Fix C++ GNU Makefiles 2024-11-22 11:51:00 -05:00
Albert
8fc3d1a39a Rename -lole32 (Lowercase) 2024-11-22 11:13:40 -05:00
Albert
89a54eb621 Fix C++ missing Returns 2024-11-22 10:15:59 -05:00
Albert
39628742aa Updating React Example Style 2024-11-22 10:05:20 -05:00
Albert
f59d0463e0 Making Show() waiting for connection + token 2024-11-21 13:15:02 -05:00
Albert
6e7b0dacb2 Adding React example 2024-11-20 16:59:51 -05:00
Albert
be972b50a4 Adding use_cookies comments 2024-11-20 16:19:31 -05:00
Albert
ed77621974 Bridge - Delay disconnection warning 2024-11-20 12:29:59 -05:00
Albert
e8863a06c1 Updating Civetweb 2024-11-19 14:27:56 -05:00
Albert
09cfb561d1 Allow set_custom_parameters to clean old params 2024-11-19 11:15:46 -05:00
Albert
5273ef3925 Fix internal mem alloc (Mem debug print improvement) 2024-11-19 10:34:27 -05:00
Albert
dc82dabf3b Merge branch 'main' of https://github.com/webui-dev/webui 2024-11-19 10:10:59 -05:00
Albert
39095cea86 Fix webui_set_custom_parameters 2024-11-19 09:43:23 -05:00
John
a44283b04d
scm: Print webui logs in debug mode (#527) 2024-11-19 23:30:30 +09:00
John
5a710c29ce
scm: Support dependency debug building (#526) 2024-11-19 23:28:45 +09:00
John
387bebe2c1
Drop Zig 0.11.0 support (#525)
* scm: Update to beta 3 in `build.zig.zon`

* scm: Drop Zig 0.11.0 support

* scm: Make shared library PIC
2024-11-19 22:57:11 +09:00
Albert
72ae4703aa Embedded HTML Div alert when connection is lost 2024-11-18 16:57:10 -05:00
Hassan DRAGA
12dee8bab7 Up to Beta 3 2024-11-15 21:02:26 -05:00
Hassan DRAGA
45257c7f8e Fix wrong ini alloc size 2024-11-15 20:56:20 -05:00
Hassan DRAGA
114ac657e7 Fix other dynamic allocs 2024-11-15 20:42:18 -05:00
Hassan DRAGA
c80f2fa1cd Fix Dynamic Allocation 2024-11-15 20:28:13 -05:00
Albert
8433878d3d Fix memory manager 2024-11-15 17:07:45 -05:00
Albert
5a1e097949 Adding Memory Mutex 2024-11-15 16:28:33 -05:00
Albert
2bef6d9f67 Fix Bridge - Duplicated Click Events 2024-11-15 16:04:47 -05:00
Hassan DRAGA
b122b59444
Merge pull request #519 from AlbertShown/patch-2
Update bridge build Batch
2024-11-11 20:46:21 -05:00
Hassan DRAGA
37cdbfde9d
Merge pull request #520 from AlbertShown/patch-3
Update bridge build Powershell
2024-11-11 20:46:03 -05:00
Showns
6a6385f515
Update bridge build Powershell 2024-11-11 15:13:47 -05:00
Showns
b261ec8c16
Update bridge build Batch 2024-11-11 15:12:20 -05:00
Hassan DRAGA
b803322edc Revert "make sure 4096 bytes not alloc 8192 bytes (#516)"
This reverts commit f161bcaced7fd699a5e6ca56144202227307d248.
2024-11-09 17:08:57 -05:00
Hassan DRAGA
57c0215069 Async Call
webui_set_config(asynchronous_response, true);
2024-11-09 16:29:44 -05:00
Hassan DRAGA
fb6ea0db5b
Merge pull request #505 from MiyamuraMiyako/main
Add user-defined command line parameter.
2024-11-09 13:54:28 -05:00
Hassan DRAGA
65b49d1d09 Fix - Add user-defined command line parameter 2024-11-09 13:50:01 -05:00
Hassan DRAGA
31c0264a04 Update - Add user-defined command line parameter 2024-11-09 13:44:22 -05:00
kbkpbot
f161bcaced
make sure 4096 bytes not alloc 8192 bytes (#516) 2024-11-09 17:30:57 +09:00
kbkpbot
48df019c84
fix linux tcc compile fail (#514) 2024-11-09 17:21:01 +09:00
jimying
d5b25ca1a8
Fix memory error (#508) 2024-10-25 00:05:56 +09:00
AsmX
5fd3f15ac7 Add user-defined command line parameter. 2024-10-19 09:48:34 +08:00
mochalins
15e2d684df scm: Fix Zig build examples from dependency 2024-10-12 13:09:56 +08:00
mochalins
2702d0427b scm: Fix Zig CI to use verbose enum 2024-10-12 12:58:32 +08:00
mochalins
9c7f07bd89 scm: Clean up build.zig, verbose logging levels 2024-10-12 12:58:32 +08:00
mochalins
5545881e4c scm: Limit paths in build.zig.zon
`build.zig.zon`'s paths are meant to specify what is needed when `webui`
is fetched as a dependency from another Zig build system. When being
used as a dependency, files such as tests/examples need not be included.
2024-10-12 12:58:32 +08:00
mochalins
3b0736fb89 fix: Release mode building with Zig 2024-10-11 20:04:46 +08:00
Hassan DRAGA
cf0c54e2bd
Merge pull request #487 from testdrive-profiling-master/main
add setting of minimum window size & default user icon patching. (currently windows only)
2024-10-06 17:00:43 -04:00
Hassan DRAGA
f8e0a20820
Merge pull request #488 from vieiro/feature/file-handler-window
File handlers could receive window number
2024-10-06 12:42:50 -04:00
HyungKi Jeong
7cb1493d0a add setting of minimum window size. (currently windows only)
add default user icon patching. (currently windows only)
actually window size and client size is not match in windows, so I fixed it.
2024-10-02 11:14:26 +09:00
Antonio
ca379f7ba6 Adding @example to the proper function now 2024-10-01 21:00:25 +02:00
Antonio
f8172bdbfa Updated @example for webui_set_file_handler_window 2024-10-01 18:30:10 +02:00
Antonio
3e66411779 File handlers could receive window number 2024-09-30 20:33:18 +02:00
niko
ead99700e9
Merge pull request #473 from ttytm/docs/remove-resolved-workarounds
Remove docs for workarounds for resolved thrid-party conflicts
2024-08-23 08:02:03 +01:00
niko
e8aaba6560
Merge pull request #477 from wansxlysys/main
add php webui wrapper
2024-08-23 08:00:46 +01:00
liming
069cb1f3a5 add php webui 2024-08-20 16:33:18 +08:00
Turiiya
924ea94f25
Update civetweb files to latest commit(3649a5f) (#474) 2024-08-18 14:21:42 +02:00
Turiiya
aec67a1e42 Remove docs for workarounds for resolved thrid-party conflicts
The conflicts were addressed in upstram.
2024-08-16 20:44:33 +02:00
Hassan DRAGA
2e94629304 Fix Bridge TypeScript Navigation Release Mode
* More inf: https://github.com/webui-dev/zig-webui/pull/58#issuecomment-2226417695
2024-07-12 20:38:08 -04:00
Hassan DRAGA
ecccc7e820 Add comment to webui.js 2024-07-12 20:10:25 -04:00
Hassan DRAGA
450197ffbf Removing Issue Template
* Templates stops some people from posting their questions.
2024-07-12 15:33:57 -04:00
Hassan DRAGA
a89a10120a Bridge - Fix unwanted logs 2024-07-12 15:11:37 -04:00
Hassan DRAGA
9c07d87041 Disable Linux WebView in Dynamic Version 2024-07-11 22:09:34 -04:00
Hassan DRAGA
0826a2c5f8 Fix macOS buffer overlap
* https://github.com/webui-dev/webui/issues/453
2024-07-11 20:29:24 -04:00
Hassan DRAGA
47c11dec33 Fix macOS Clang Warnings 2024-07-11 19:53:39 -04:00
Hassan DRAGA
64133f4c30 Fix Clang Warnings 2024-07-11 17:52:54 -04:00
Hassan DRAGA
ef8595ae1c Complete C++ Header 2024-07-11 17:06:37 -04:00
Hassan DRAGA
18f7ce3460 Update C++ Examples 2024-07-11 17:06:23 -04:00
Hassan DRAGA
78a30109de
Merge pull request #452 from webui-dev/WebKit-WebView-Conflict-Fix
Change WebView to Webview (macOS WebKit Conflict)
2024-07-11 15:57:35 -04:00
Hassan DRAGA
17a3a75959 Core - Change WebView to Webview (macOS WebKit Conflict) 2024-07-11 15:28:12 -04:00
Hassan DRAGA
0bfe23ceda Change WebView to Webview (macOS WebKit Conflict) 2024-07-11 13:40:57 -04:00
Hassan DRAGA
fb63521042 Fix serve_a_folder (Now should be Header + Body) 2024-07-11 13:32:31 -04:00
Hassan DRAGA
d213bf487a Debug Log External File Handler (Header + Body) 2024-07-11 13:31:41 -04:00
Hassan DRAGA
8008016de8 Fix HTTP Header Buffer 2024-07-11 13:07:40 -04:00
Hassan DRAGA
1dbce3938e Fix Minor Warnings (is_high_contrast) 2024-07-11 12:09:03 -04:00
Hassan DRAGA
13f1ebe1fe Increase Reload Timeout (500ms to 1500ms) 2024-07-11 10:32:36 -04:00
Hassan DRAGA
c158487417 Fix Invalid Packet Void Response 2024-07-11 10:31:48 -04:00
Hassan DRAGA
708d4a16a3 Unify Comments 2024-07-11 10:10:29 -04:00
Hassan DRAGA
bdd89e22ea Core - Send Bind List After Token 2024-07-10 23:59:31 -04:00
Hassan DRAGA
fc0c867f25 Bridge - Get Bind List After Token
* Get Bind List After Token
* Renaming bridge files
2024-07-10 23:59:08 -04:00
Hassan DRAGA
3f683ea036 Fix GCC Warning 2024-07-09 20:59:24 -04:00
Hassan DRAGA
633a96c54b New Example - virtual_file_system 2024-07-09 19:51:08 -04:00
Hassan DRAGA
1e8642bc6e Supporting header + body in webui_set_file_handler 2024-07-09 19:30:54 -04:00
Hassan DRAGA
b2f505a41c Update C Header - Adding et_mime_type 2024-07-09 19:19:26 -04:00
Hassan DRAGA
af46c34a02 Fix C++ Header 2024-07-09 19:11:51 -04:00
Hassan DRAGA
9350a6aa95
Merge pull request #449 from nater0000/main
Change to support serving files from a c-embed filesystem
2024-07-09 19:01:16 -04:00
Hassan DRAGA
d01c8a8352
Merge pull request #450 from nater0000/get_port
Added a function webui_get_port() to retrieve the server port for the session
2024-07-09 18:54:56 -04:00
Nathan R
9ed9279a98 Added a function webui_get_port() to retrieve the server port for the session 2024-07-09 14:39:38 -07:00
Nathan R
bbcdb9c5e0 Modify _webui_http_handler() to handle a file before a path 2024-07-09 14:29:48 -07:00
Hassan DRAGA
de9508653a
Merge pull request #448 from sensiblearts/main
exposing _webui_get_free_port
2024-07-09 16:02:57 -04:00
David Alm
51d82c82e9 tk 2024-07-09 13:54:59 -04:00
David Alm
0346f0ffdc exposing _webui_get_free_port 2024-07-09 12:06:31 -04:00
Hassan DRAGA
ff97452eb0 Fix Header SameSite and CORS 2024-07-08 23:35:41 -04:00
Hassan DRAGA
50e9e4c2c6 Update example (Bun - Deno - Nodejs) 2024-07-08 19:22:41 -04:00
Hassan DRAGA
0440eeaab1 Adding Bun Runtime 2024-07-08 19:21:51 -04:00
Hassan DRAGA
2a79c2b526 Bridge Minified Version 2024-07-08 17:01:16 -04:00
Hassan DRAGA
faa02ad708 Bridge - Auto-reconnect 2024-07-08 16:37:54 -04:00
jinzhongjia
f888f15dbd fix: zig cross compile from linux to windows error 2024-07-08 09:03:15 +08:00
Hassan DRAGA
4f6fbc58d0 Adding warnings for debug mode 2024-07-07 14:50:47 -04:00
Hassan DRAGA
923f48795f Fix warnings 2024-07-07 14:50:00 -04:00
Hassan DRAGA
e443e318f7 Update readme 2024-07-07 14:20:04 -04:00
Hassan DRAGA
bdf6bac511 Fix Makefile x86 and ARM conflict
Removing ` /MACHINE:X64`
2024-07-06 22:45:06 -04:00
Hassan DRAGA
600e8d36b1 Fix Win32 Folder Check 2024-07-06 21:48:27 -04:00
Hassan DRAGA
59f2d077a6 Supporting Firefox Snap 2024-07-06 21:25:13 -04:00
Hassan DRAGA
13c889a10e Update Text Editor Example 2024-07-06 20:42:33 -04:00
Hassan DRAGA
fb1607b3d3 Fix Linux Exit
* Fix Show update current window
* Fix Linux Exit SEGFAULT
2024-07-06 20:42:03 -04:00
Hassan DRAGA
cdc78e4609 Update default internal icon 2024-07-06 11:32:52 -04:00
Hassan DRAGA
89495f919d
Merge pull request #442 from ttytm/fix/gcc-14-compatibility
Resolve incompatible ptr warning to fix compatibility with gcc-14
2024-07-06 10:18:58 -04:00
Turiiya
3b3e4c4ab0 Resolve incompatible ptr warning to fix compatibility with gcc-14 2024-07-06 13:34:44 +02:00
Turiiya
57a5846746 Test gcc-14 builds in CI 2024-07-06 13:33:11 +02:00
Hassan DRAGA
836e1d115f Fix zig CI build 2024-07-05 18:59:08 -04:00
Hassan DRAGA
56f787cf73 New example - web_app_multi_client 2024-07-05 18:52:56 -04:00
Hassan DRAGA
6ca760163e Adding new API webui_open_url 2024-07-05 18:52:12 -04:00
Hassan DRAGA
f25dd98112 New Event Elements
* Updating webui_config: use_cookies
* Updating webui_event_t: connection_id, cookies
2024-07-05 16:48:32 -04:00
Hassan DRAGA
e8f6a8abdb Cookies System (Heavy Core Changes) 2024-07-05 16:46:51 -04:00
Hassan DRAGA
efe64ba0af Updating example - public_network_access
* Allowing public URL to be updated on refresh
2024-07-03 09:26:22 -04:00
Hassan DRAGA
5f33f70d64 Updating embedded icon 2024-07-02 23:13:34 -04:00
Hassan DRAGA
c4cc398778 Adding webui_interface_get_float_at 2024-07-02 11:31:32 -04:00
Hassan DRAGA
327067cb7d Fix build warnings 2024-07-02 11:30:34 -04:00
Hassan DRAGA
bb887d76f6 New API webui_start_server 2024-07-02 00:45:15 -04:00
Hassan DRAGA
cc103aa37f Header - New APIs
* WebView in browsers list
* multi_client in config
* client_id in webui_event_t
* webui_script_client
* webui_run_client
* webui_close_client
* webui_navigate_client
* webui_show_client
* webui_send_raw_client
2024-07-01 02:37:30 -04:00
Hassan DRAGA
92e98e84e2 New multi-client APIs
* webui_run_client
* webui_close_client
* webui_navigate_client
* webui_show_client
* webui_send_raw_client
2024-07-01 02:34:58 -04:00
Hassan DRAGA
4116ec7581 Bridge - Fix send raw size 2024-07-01 02:31:53 -04:00
Hassan DRAGA
d5a82f98bf Fix All Event Client ID 2024-07-01 00:32:48 -04:00
Hassan DRAGA
da7bb84ca3 MSVC Makefile - Keep .pdb (Debug Symbols) 2024-06-30 23:33:19 -04:00
Hassan DRAGA
4caeb82351 Update Bridge - One-time Token 2024-06-30 23:31:36 -04:00
Hassan DRAGA
88c9996ce6 Multi-Client Design (Heavy Core Change)
* Re-design the core to deal with multi-client requests
* Enhanced Security - Cookie Authorization
* Enhanced Security - One-time Token
* Enhanced Security - Isolated Window Binding IDs
2024-06-30 23:30:38 -04:00
Hassan DRAGA
5a39692fb8
Merge pull request #416 from ttytm/fix/swift
Fix compiling with swift due to incompatible civetweb structname
2024-06-29 11:50:08 -04:00
Hassan DRAGA
b65608dfec Fix monitor_thread (typo) 2024-06-25 22:53:40 -04:00
Hassan DRAGA
9b79e7329c Fix monitor_thread 2024-06-25 22:51:39 -04:00
Hassan DRAGA
b576b2f9de Adding folder_monitor (config)
* Automatically refresh the window when any file in the root folder gets changed.
2024-06-25 22:40:25 -04:00
Hassan DRAGA
88cd5f3774 Adding JS API - isHighContrast 2024-06-25 17:31:14 -04:00
Hassan DRAGA
d0b013ccda Adding webui_browser_exist
More inf: https://github.com/webui-dev/webui/issues/431
2024-06-25 16:20:25 -04:00
Hassan DRAGA
acc77ce5d2 Update high contrast 2024-06-25 14:01:09 -04:00
Hassan DRAGA
8e8abd2273 Up to Beta.2 2024-06-25 13:06:30 -04:00
Hassan DRAGA
b0dd088d56 Examples rename (webui.js) path to (/webui.js)
* All examples should use `/webui.js` instead of `webui.js`, this is because without the slash `/` it won't work if HTML file is located in a sub-folder.
2024-06-25 13:03:44 -04:00
Hassan DRAGA
a93083b2a2 Fix HTTP folder request
Before, a request to `/folder` will return a 404 error, now it will redirect to `/folder/index.html` if exist.
2024-06-25 12:58:37 -04:00
Hassan DRAGA
57f5fca41e Fix MSVC Makefile unrecognized NO_SSL
Fix :
```
cl : Command line warning D9024 : unrecognized source file type 'NO_SSL', object file assumed
cl : Command line warning D9027 : source file 'NO_SSL' ignored
webui.c
```
2024-06-25 11:22:23 -04:00
Hassan DRAGA
6b539c376a
Merge pull request #433 from malisipi/high-contrast-management
High Contrast Management
2024-06-24 21:01:01 -04:00
Mehmet Ali Şipi
900e6f8d61
Add linux support 2024-06-24 21:54:38 +03:00
Mehmet Ali Şipi
5399c1f2fe
Support high contrast detection on Windows. 2024-06-24 16:26:20 +03:00
Mehmet Ali Şipi
3bdacf4c12
Support to disable default high contrast of browser. 2024-06-24 15:27:28 +03:00
Hassan DRAGA
f40d35a60b Faster ARM runners 2024-06-22 20:51:32 -04:00
Hassan DRAGA
c2f410d700 Fix release tag workflow 2024-06-22 20:41:05 -04:00
Hassan DRAGA
81c778cc67 Update C++ Examples 2024-06-21 15:55:38 -04:00
Hassan DRAGA
aca21d905e Adding some C++ APIs 2024-06-21 15:47:08 -04:00
Hassan DRAGA
775455c809 Fix typos in the C header 2024-06-21 15:46:59 -04:00
Hassan DRAGA
d32f0932b4 Simpler Bug Report Template 2024-06-21 12:54:26 -04:00
Hassan DRAGA
e934fe6eee disable aarch64 build test 2024-06-19 16:09:18 -04:00
Hassan DRAGA
0af781390d Temporary disable aarch64 build test 2024-06-19 16:07:22 -04:00
Hassan DRAGA
a0595d992b Fix aarch64 examples test build 2024-06-19 15:50:04 -04:00
Hassan DRAGA
c17dc924fd Fix OpenSSL for aarch64 (ARM64)
* Build OpenSSL from source to use `gcc-aarch64-linux-gnu` to generate `ELF 64-bit ARM`
2024-06-19 15:33:58 -04:00
Hassan DRAGA
734511a1ee Fix compiled aarch64 objects 2024-06-19 15:18:53 -04:00
Hassan DRAGA
104fd4803a Upgrade OpenSSL to v3.3.1 2024-06-19 12:18:29 -04:00
Hassan DRAGA
270c4de9fb Adding Linux ARM.yml 2024-06-19 11:19:39 -04:00
Hassan DRAGA
a628e0780e Remove ARM from Linux.yml 2024-06-19 11:19:05 -04:00
Hassan DRAGA
6e7a7307cc Add Step Linux ARM 2024-06-19 11:18:42 -04:00
Hassan DRAGA
5aa49f6563 Rename Example IDs - call_c_from_js 2024-06-19 08:29:48 -04:00
Hassan DRAGA
56420d67b0 Rename Example IDs - call_js_from_c 2024-06-19 08:22:50 -04:00
Hassan DRAGA
a046af263c Rename Example IDs - custom_web_server 2024-06-18 18:55:54 -04:00
Hassan DRAGA
5657f3f481 Fix NoBrowser Mode
* public_network_access example was broken
2024-06-18 18:50:34 -04:00
Hassan DRAGA
90e774bb13 Rename Example IDs - serve_a_folder 2024-06-18 16:35:13 -04:00
Hassan DRAGA
c598ac996a Fix Deno FFI Warning 2024-06-18 16:33:49 -04:00
Hassan DRAGA
c3ce70c384 Rename Example IDs - text-editor 2024-06-18 12:28:34 -04:00
Hassan DRAGA
2730c9d8e9 Fix ignore all sublevel binaries
* `.exe` and other executables still not-ignored.
* Fix for 218093b958
2024-06-18 12:16:35 -04:00
Hassan DRAGA
1048ffaace
Merge pull request #422 from ttytm/build/tls
Update handling of build variables
2024-06-16 20:07:55 -04:00
Turiiya
8ab54084e4 Utilize CC not being overwritten 2024-06-16 15:50:36 +02:00
Turiiya
6732b84cc1 Only set CC if none is set (don't overwrite env CC)
Allow passing other CCs
2024-06-16 15:50:36 +02:00
Turiiya
56dc82758b Utilize simplified way to pass additional TLS flags 2024-06-16 15:48:04 +02:00
Turiiya
a86217ebf5 Simplify TLS handling 2024-06-16 15:44:24 +02:00
Turiiya
da61335597 Caputure and assert program output in CI 2024-06-16 14:16:32 +02:00
Turiiya
5ed5d688c2 Add cprint test to solidify confirmations in CI test runs 2024-06-16 14:16:32 +02:00
Turiiya
21118a5445 Update labels in issue templates 2024-06-16 14:16:32 +02:00
Turiiya
6cefcb1f3d
Merge pull request #421 from ttytm/ci/add-test 2024-06-16 04:43:51 +02:00
Turiiya
e70f64e2c6 Make labels in issue templates more consistent 2024-06-16 04:33:16 +02:00
Turiiya
b9c4530b42 Include failing test in CI run to make sure tests can fail 2024-06-16 04:21:39 +02:00
Turiiya
63b7cfde5f Add failing_test.c 2024-06-16 04:04:51 +02:00
Turiiya
6d1428ae61 Update test makefile to build test files 2024-06-16 04:04:51 +02:00
Turiiya
5a40b92cd2 Extend test to test passing js args to C 2024-06-16 04:04:51 +02:00
Turiiya
da7be60c78 Run test in CI 2024-06-16 04:04:51 +02:00
Turiiya
218093b958 Update .gitignore to ignore all sublevel build binaries 2024-06-16 01:22:01 +02:00
Turiiya
d4c1415fd8 Add test 2024-06-16 01:22:01 +02:00
Turiiya
9518b9e844
Merge pull request #415 from ttytm/ci/fix-release-cond
Fix condition for release steps when pushing tags
2024-06-15 22:06:05 +02:00
Hassan DRAGA
15d519c13d Fix get_new_window_id
* Details: https://github.com/webui-dev/webui/discussions/418
2024-06-15 14:12:25 -04:00
Turiiya
46b2228ddb Include change in civetweb readme 2024-06-15 04:35:38 +02:00
Turiiya
18f8a1ea23 Fix compiling with swift due to incompatible civetweb structname 2024-06-15 04:29:44 +02:00
Turiiya
23da99b3b7 Fix condition for release steps when pushing tags 2024-06-15 03:42:30 +02:00
Hassan DRAGA
ea5540c833
Merge pull request #413 from ttytm/ci/tls-linux-macos
Include TLS builds in artifact uploads on Linux and macOS
2024-06-13 10:46:49 -04:00
Turiiya
e8e4220b46 Include TLS builds in artifact uploads on Linux and macOS 2024-06-13 16:18:47 +02:00
Hassan DRAGA
0ae019b055
Merge pull request #412 from ttytm/ci/refine
Update workflows
2024-06-13 09:25:48 -04:00
Turiiya
486df2efbd Include tests with different compilers when building examples on Linux 2024-06-13 15:13:20 +02:00
Turiiya
92b7fc7ce1 Display nightly build date in title 2024-06-13 15:08:29 +02:00
Turiiya
2135b091fb Refine workflows, improve maintainability 2024-06-13 15:07:46 +02:00
Hassan DRAGA
02aeef647e
Merge pull request #410 from webui-dev/neroist-patch-1
Add ` --auto-accept-camera-and-microphone-capture` to chromium flags
2024-06-12 18:16:00 -04:00
Jazz
934727b346
Add --auto-accept-camera-and-microphone-capture to chromium flags 2024-06-12 18:07:44 -04:00
Hassan DRAGA
d394a2f92a * Rename webui_set_event_block to webui_set_event_blocking 2024-06-12 18:04:29 -04:00
Turiiya
a860746af7 Fix windows artifact name 2024-06-12 23:51:50 +02:00
Hassan DRAGA
109063e5a4
Merge pull request #409 from ttytm/ci/simplify-artifact-building
Simplify building artifacts in CI
2024-06-12 17:33:51 -04:00
Turiiya
a4f0490d99 Simplify building artifacts on windows 2024-06-12 23:26:13 +02:00
Turiiya
179039bf5a Simplify artifact building on linux and macos 2024-06-12 23:23:51 +02:00
Hassan DRAGA
545c4f5e42
Merge pull request #408 from ttytm/ci/limit-releases
Limit releases to webui origin repo
2024-06-12 17:12:33 -04:00
Turiiya
1416e001e3 Limit releases to webui origin repo 2024-06-12 23:01:04 +02:00
Hassan DRAGA
cc3df4f040 Moving TLS include step 2024-06-12 16:48:33 -04:00
Hassan DRAGA
d4e6d5f3d5 Fix TLS MSVC 2024-06-12 12:03:33 -04:00
Hassan DRAGA
a1e4ef51bb Assert 2024-06-12 11:48:17 -04:00
Hassan DRAGA
6e15893135 Update OpenSSL links 2024-06-12 10:19:29 -04:00
Hassan DRAGA
2257b94a9b Fix Windows TLS CI (OpenSSL Path) 2024-06-11 18:36:38 -04:00
Hassan DRAGA
cb76e0af53 Fix Windows TLS CI (OpenSSL Env) 2024-06-11 18:26:43 -04:00
Hassan DRAGA
bf1a443749 Fix Windows TLS CI (Env) 2024-06-11 18:14:07 -04:00
Hassan DRAGA
7d25559235 Fix Windows TLS CI 2024-06-11 18:07:24 -04:00
Hassan DRAGA
911fe332c6 Windows TLS CI 2024-06-11 18:04:05 -04:00
Hassan DRAGA
93d78bf7c8 Fix Bridge Navigation Event
* If there is no bind all, then keep navigation events as default
* More details (https://github.com/webui-dev/webui/issues/392)
2024-06-11 16:58:33 -04:00
Hassan DRAGA
20c350e3cd Fix Event Block 2024-06-11 15:33:38 -04:00
Hassan DRAGA
4fb247ef25 Adding Event Block APIs
* Adding `webui_set_event_block`
* Adding `ui_event_block` for `webui_set_config`
2024-06-11 15:27:12 -04:00
Hassan DRAGA
f182a12c8f
Merge pull request #404 from ttytm/main
Add CGO check
2024-06-09 18:33:37 -04:00
Turiiya
5be9d902db Add CGO check 2024-06-09 22:29:35 +02:00
Turiiya
4f2ccfb834
Merge pull request #403 from ttytm/fix/dirent-conflict
Fix conflict with including dirent
2024-06-09 20:54:50 +02:00
Turiiya
45c973a387 Fix conflict with including dirent 2024-06-09 20:47:17 +02:00
Hassan DRAGA
561c044924 Update readme about required modifications 2024-06-09 14:12:04 -04:00
Turiiya
c3e2e821c6
Merge pull request #402 from ttytm/civetweb-readme
Add readme about required modifications to civetweb
2024-06-09 16:02:46 +02:00
Turiiya
cdce8348bb Add readme about required modifications to civetweb 2024-06-09 15:34:52 +02:00
Hassan DRAGA
926dd936cb
Merge pull request #401 from webui-dev/zig-nightly
fix: zig nightly becomes `0.14.0`
2024-06-09 00:54:40 -04:00
jinzhongjia
c2bdc44371 update workflows zig version 2024-06-09 11:38:59 +08:00
jinzhongjia
27160810a8 fix: zig nightly becomes 0.14.0 2024-06-09 11:35:29 +08:00
Hassan DRAGA
ab827e0b50
Merge pull request #400 from dgllghr/fix-send-raw-parse
Fix index when parsing data from raw data command
2024-06-08 21:42:09 -04:00
Dan
ee90585a0a
fix index for command data 2024-06-09 01:29:30 +00:00
Dan
eacce2e00c
attempt to fix index in parse 2024-06-09 01:20:37 +00:00
Hassan DRAGA
9039c31e68 Adding isConnected to the JavaScript bridge
* More details https://github.com/webui-dev/webui/issues/392
2024-06-07 18:31:55 -04:00
Hassan DRAGA
ced5d9795e Fix wv crash after browser show
* Because GTK WebView and WKWebView are not thread safe
2024-06-06 22:06:25 -04:00
Jazz
b57a803d5a
Merge pull request #398 from malisipi/main
Remove platform-dependent CSS and use browser titlebar on Firefox
2024-06-06 15:23:05 -04:00
Mehmet Ali Şipi
6c41d8d9b3
Remove platform-dependent CSS and use browser titlebar 2024-06-06 15:28:31 +03:00
Hassan DRAGA
1e6196cb9c
Merge pull request #378 from ttytm/prevent-civetweb-warnings
Prevent warnings from reminder definitions defined in civetweb thridparty
2024-06-05 21:55:55 -04:00
Hassan DRAGA
8b715e61f3 Fix Single Port Redirection
* Fix broken redirection after using single port for HTTP/WS
2024-06-05 21:22:50 -04:00
Hassan DRAGA
a6aee12de0 Single Port for HTTP and WS
* Fix https://github.com/webui-dev/webui/issues/341
2024-06-05 21:16:45 -04:00
Hassan DRAGA
0462ca7fdb Fix WS close warning 2024-06-05 16:41:19 -04:00
Hassan DRAGA
67179f582b Suppress Warnings 2024-06-05 15:40:28 -04:00
Hassan DRAGA
97d7543289
Merge pull request #394 from ttytm/semver-version
Use semver compliant version specification
2024-06-05 14:12:24 -04:00
Hassan DRAGA
30889511ed
Merge pull request #396 from ttytm/fix/macos-dbg-print
Update format specification in macos debug print
2024-06-05 13:58:21 -04:00
Turiiya
3ab322a33f Update format specification in debug print 2024-06-05 19:36:00 +02:00
Turiiya
d8008e3d57 Update version after suggestions 2024-06-05 19:15:29 +02:00
Hassan DRAGA
386a26030c Apply safe std (dyn and static)
* Internal. Using `WEBUI_SPF_DYN` for dynamic buffers, so block size is rounded.
* Internal. Using `WEBUI_SPF_STATIC` for static (stack) buffers, so block size not rounded.
* Fix Clang crash in Linux (https://github.com/webui-dev/webui/issues/388)
2024-06-05 11:56:50 -04:00
Hassan DRAGA
743fe3d011 Add internal safe std (dyn and static) 2024-06-05 11:42:35 -04:00
Hassan DRAGA
6e775b277d Linux - C Adding -LDL lib
* Adding `-ldl`
* Fix https://github.com/webui-dev/webui/issues/380
2024-06-05 09:09:59 -04:00
Hassan DRAGA
62a3b79e4b Linux - C++ Adding -LDL lib
* Adding `-ldl`
2024-06-05 09:09:38 -04:00
Turiiya
cf9764a071 Use semver compliant version specification 2024-06-05 01:21:59 +02:00
Hassan DRAGA
4b8b4faa11 Linux - Faster browser load when GTK WebView is not available
* Fix the internal waiting timeout when GTK WebView is not available
2024-06-04 18:04:39 -04:00
Hassan DRAGA
d46f806038 Win32 - Faster browser load when WebView is not available
* Fix the internal waiting timeout when WebView2 loader DLL is not available
2024-06-04 17:31:53 -04:00
Hassan DRAGA
a29b0753d9 Unfinished - WebView Auto JS Inject 2024-06-04 17:14:56 -04:00
Jazz
ecea17cd3b
Merge pull request #393 from ttytm/issue-templates
Add issue templates
2024-06-04 15:03:05 -04:00
Turiiya
3de023e27e Add issue templates 2024-06-04 19:07:28 +02:00
Jazz
26c9126880
Merge pull request #390 from vindarel/main
README: add Common Lisp wrapper
2024-06-03 14:43:10 -04:00
vindarel
d982e5bd8a README: add Common Lisp wrapper
in alphabetical order after the webui-dev repositories.
2024-06-03 18:30:35 +02:00
Turiiya
33fd4a2f23
Make minor cleanups in build.zig (#389) 2024-06-03 06:38:56 +02:00
Turiiya
62431928d8
Merge pull request #387 from ttytm/update-enums
Use singular form for enum names
2024-06-03 02:10:44 +02:00
Turiiya
bf87e04a6b Rename webui_config to webui_set_config 2024-06-02 18:32:39 +02:00
Turiiya
37bdee47ec Use singular form for enum names 2024-06-02 18:29:15 +02:00
Hassan DRAGA
4466bcfc4e Update webui_get_best_browser description 2024-06-01 16:30:52 -04:00
Hassan DRAGA
c853979fb1 Fix webui_get_best_browser 2024-06-01 16:21:58 -04:00
Hassan DRAGA
bcf08875a7 Removing dup internal calls 2024-06-01 16:19:37 -04:00
Hassan DRAGA
4694a29389 Fix missing some HTTP files 2024-06-01 16:07:18 -04:00
Turiiya
0878256bf8
Merge pull request #382 from ttytm/update-description
Update tagline
2024-06-01 06:06:50 +02:00
Turiiya
ade685fd3f
Merge pull request #384 from ttytm/build/zig-nightly
Add build support with zig `0.13.0-dev`
2024-06-01 06:05:33 +02:00
Turiiya
7a1eb111bb Add build support with zig 0.13.0-dev 2024-06-01 05:40:17 +02:00
Turiiya
0ade1d9b0d Include nightly tests in zig workflow 2024-06-01 05:34:04 +02:00
Turiiya
41428a172c Update tagline 2024-06-01 02:26:16 +02:00
Hassan DRAGA
373c546702
Merge pull request #310 from NicolasBFR/main
Draft: Add CMake build system
2024-05-31 19:01:58 -04:00
Hassan DRAGA
817cc605be
Merge pull request #326 from SpikeHD/expose_browser
Expose `_webui_find_the_best_browser` as `webui_get_best_browser`
2024-05-31 18:24:29 -04:00
Hassan DRAGA
6fe3549684
Merge pull request #351 from GiuseppeCesarano/main
C++ events are now enum instead of const static int
2024-05-31 18:21:44 -04:00
Hassan DRAGA
c8c1b2b757
Merge pull request #361 from xland/patch-1
Add QuickJS Wrapper
2024-05-31 18:20:47 -04:00
Hassan DRAGA
218a129d25
Merge pull request #377 from ttytm/fix/sign-comp2
Update linux webview positon fallback values values to match type declarations
2024-05-31 18:16:49 -04:00
Hassan DRAGA
570a917a7d Fix runtime functionality - Linux 2024-05-31 17:51:30 -04:00
Hassan DRAGA
c537df5abe Fix runtime functionality 2024-05-31 17:46:03 -04:00
Hassan DRAGA
d86a795898 Fix runtime break 2024-05-31 15:37:41 -04:00
Hassan DRAGA
769b011a87 Print used compiler in logs 2024-05-31 10:28:52 -04:00
Turiiya
272b44a5e8 Prevent warnings from reminder definitions defined in civetweb thridparty 2024-05-30 23:52:20 +02:00
Hassan DRAGA
43225227fa Fix warnings - Linux 2024-05-30 16:22:47 -04:00
Hassan DRAGA
2e1717272c Fix warnings - casting 2024-05-30 16:17:15 -04:00
Hassan DRAGA
d3038f6a4a Fix all warnings (MSVC) 2024-05-30 16:02:16 -04:00
Hassan DRAGA
72737eabcf Fix WEBUI_SPF 2024-05-30 15:44:31 -04:00
Hassan DRAGA
36e268c634 Fix warnings - Safe fopen 2024-05-30 15:40:40 -04:00
Hassan DRAGA
d25ae317f4 Fix warnings - Safe strcat 2024-05-30 13:08:21 -04:00
Hassan DRAGA
6ae5046287 Fix warnings - Safe strcpy 2024-05-30 13:02:09 -04:00
Hassan DRAGA
a8709a71b5 Fix webui_set_position args 2024-05-30 12:53:56 -04:00
Hassan DRAGA
34e9b10c68 Fix warnings - Safe strtok 2024-05-30 12:28:58 -04:00
Hassan DRAGA
a1c6802a8a Fix warnings - Safe sprintf 2024-05-30 12:14:52 -04:00
Hassan DRAGA
ce3dce4991
Merge pull request #376 from ttytm/fix/sign-comp
Update variable type decl in internal function `_webui_round_to_memory_block` to resolve sing-comp warning
2024-05-30 09:36:33 -04:00
Turiiya
6d83d7e403 Update linux webview positon fallback values values to match type declaration 2024-05-30 15:09:44 +02:00
Turiiya
cdc1d29879 Update variable type in _webui_round_to_memory_block to resolve sing-comp warning 2024-05-30 06:25:09 +02:00
Hassan DRAGA
4517ba4982 Adding webui_return_float 2024-05-29 19:01:10 -04:00
Hassan DRAGA
065cd3f09c webui_show_wv default center 2024-05-29 18:35:21 -04:00
Turiiya
b4d428d09c
Merge pull request #373 from webui-dev/zig-12+ 2024-05-29 23:59:16 +02:00
Hassan DRAGA
b61b145bb9 Arguments count example 2024-05-29 17:47:13 -04:00
Hassan DRAGA
19b2e32394 Adding webui_get_count 2024-05-29 17:44:03 -04:00
Turiiya
21da984823 CI include Zig 0.12.0 compilation tests in workflow 2024-05-29 23:43:21 +02:00
Turiiya
a7475d16ee Support compiling with zig versions 0.12.0 and above 2024-05-29 23:43:21 +02:00
Hassan DRAGA
19234368ba Float example 2024-05-29 17:39:49 -04:00
Hassan DRAGA
9c9b3dc00a Adding webui_get_float 2024-05-29 17:23:19 -04:00
Hassan DRAGA
8d94cdcae8 Rename WebUI Nightly Development Build 2024-05-29 16:41:31 -04:00
Hassan DRAGA
225f818ce4 Faster window exit 2024-05-29 16:34:42 -04:00
Hassan DRAGA
cd0646274d
Merge pull request #369 from ttytm/build/update-zig-11-build
Refine and fix building with zig
2024-05-29 13:59:31 -04:00
Turiiya
58f764898e Sort params 2024-05-29 19:11:48 +02:00
Turiiya
9ca7c3c8d0 Run CI zig builds verbose 2024-05-29 18:45:58 +02:00
Turiiya
f94fa664b1 Add verbose, build silent by default 2024-05-29 18:45:58 +02:00
Turiiya
3b3ccdfb03 Add setup-xcode action to fix bug with current default XCode CI version 2024-05-29 16:58:10 +02:00
Turiiya
5baf13a068 Run different zig build options in CI 2024-05-29 16:58:10 +02:00
Turiiya
c4485be70e Fix assigning incompatible ptr in webview windows function 2024-05-29 16:58:10 +02:00
Turiiya
6ec0c7bd6c Update linked lib and frameworks 2024-05-29 16:58:10 +02:00
Turiiya
736cd41f9c Update zig example build command in workflow 2024-05-29 16:58:09 +02:00
Turiiya
4f9fc49cfd Add build info print 2024-05-29 16:58:09 +02:00
Turiiya
1f5d52048a Refine zig 0.11 build prep 0.12 build integration 2024-05-29 16:58:09 +02:00
Hassan DRAGA
a54d90607a Fix GC WebView2 2024-05-28 18:04:00 -04:00
Hassan DRAGA
f915af388e Prioritize the server thread 2024-05-28 15:20:28 -04:00
Hassan DRAGA
c31abc32ee Adding webui_config 2024-05-28 14:28:32 -04:00
Turiiya
587963ff6d
Merge pull request #371 from ttytm/ci/examples
Extend test coverage, add CI steps to build C examples with make
2024-05-28 18:43:02 +02:00
Turiiya
b07f5be076 Abstract make command in windows workflow to simplify and reduce redundancy 2024-05-28 18:35:45 +02:00
Turiiya
c82b21033f Extend test coverage, add CI steps to build C examples with make 2024-05-28 18:26:33 +02:00
Hassan DRAGA
ab175b489b Update readme 2024-05-27 16:19:00 -04:00
Hassan DRAGA
ac2230c4c0 Fix GNU Makefile examples 2024-05-27 16:18:53 -04:00
Hassan DRAGA
ba7d032377
Merge pull request #368 from ttytm/build/fix
Fix building v2.5.0-beta1
2024-05-27 10:08:56 -04:00
Turiiya
32d1917ff9 Apply changes to other examples 2024-05-27 14:11:53 +02:00
Turiiya
13e2ccf17d Fix dir in release target 2024-05-27 13:49:10 +02:00
Turiiya
4700c2c5ff Cleanup variables in makefile and move into correct scope 2024-05-27 13:49:06 +02:00
Turiiya
9a057e1b29 Move webkit linker flags to macos conditon 2024-05-27 13:37:44 +02:00
Turiiya
3500b053bb Remove return in function returning void 2024-05-27 13:33:18 +02:00
Hassan DRAGA
b3c8f78271 Fix screenshot 2024-05-26 20:24:26 -04:00
Hassan DRAGA
e921f0dde4 Update screenshot 2024-05-26 20:16:49 -04:00
Hassan DRAGA
7e99ecc7bf WebUI v2.5.0-Beta-1 2024-05-26 20:02:12 -04:00
Hassan DRAGA
ca65af8be6 Adding macOS WKWebView 2024-05-26 20:01:26 -04:00
Hassan DRAGA
c4769e9cc3 Adding WebView2 Third-party
* Headers are taken from Microsoft WebView2 package
2024-05-26 20:00:45 -04:00
Hassan DRAGA
e8d38e4620 Updating Civetweb Third-party 2024-05-26 19:58:48 -04:00
Hassan DRAGA
c832eced7b Updating MSVC Makefile
* Adding `-lOle32` for Windows, needed by WebView2
2024-05-26 19:57:37 -04:00
Hassan DRAGA
c5ddba49fd Update GNU Makefile
* Adding `-lOle32` for Windows, needed by WebView2
* Adding Cocoa and WebKit frameworks, needed by macOS WKWebView
2024-05-26 19:56:47 -04:00
Hassan DRAGA
33ff93f475 Update version to 2.5.0-Beta-1 2024-05-26 19:53:44 -04:00
Hassan DRAGA
d20df6483b Update the date to 2024 2024-05-26 19:52:59 -04:00
Turiiya
9f120e974f Update action versions 2024-05-26 12:06:16 +08:00
Turiiya
bf81ad1b8f Add CI concurency group setting to 2024-05-26 12:06:16 +08:00
Turiiya
cec7b8b756 Add zig workflow 2024-05-26 12:06:16 +08:00
Turiiya
9a1e116701 Make furhter minor cleanup 2024-05-26 11:39:56 +08:00
Turiiya
fb6618ca79 Simplify building examples with Zig 2024-05-26 11:39:56 +08:00
Turiiya
c448c52182 Don't return silently when zig build is not possible 2024-05-26 10:34:47 +08:00
liulun
8ebdb00b43
Add QuickJS Wrapper
Add QuickJS Wrapper
2024-05-24 14:59:23 +08:00
Jazz
a3f3174c73
Merge pull request #357 from halildgn/main
change ubuntu version in linux workflow to support legacy glib
2024-05-09 09:34:49 -04:00
Halil Dogan
7ca2382f99 change ubuntu version in linux workflow to support legacy linux glib 2024-05-09 12:14:38 +02:00
jinzhongjia
deae94bac8 little fix 2024-05-04 08:06:14 +08:00
jinzhongjia
02f05a2936 remove other build.zig 2024-05-04 07:08:54 +08:00
Giuseppe Cesarano
fc10b42318
C++ events are now enum instead of const static int 2024-04-22 09:48:26 +02:00
Jazz
24fefb865b
Merge pull request #349 from webui-dev/with_zig-0.13
[Update]: update to zig nightly 0.13 support
2024-04-21 09:15:01 -04:00
jinzhongjia
4a63099003 update to zig nightly 0.13 support 2024-04-21 13:53:33 +08:00
Jazz
32f876a0ae
Merge pull request #346 from webui-dev/build_api_change
fix api changes of nightly zig `installHeader`
2024-04-14 13:21:39 -04:00
jinzhongjia
faeb246a03 maybe useful to fix 2024-04-14 10:55:22 +08:00
MBK
f37844bd56 fix issue #344 compile error with webui_tls on win32 2024-04-13 17:19:41 +08:00
jinzhongjia
b2ea3861d6 fix api changes of nightly zig 2024-04-10 15:07:57 +08:00
jinzhongjia
a994629f90 fix nightly api change 2024-03-26 07:20:43 +08:00
jinzhongjia
7a690a514d Split build.zig
Split build.zig
 replace strdup with _strdup when compiling with msvc
2024-03-26 07:20:43 +08:00
jinzhongjia
ce4b2e0530 msvc_tmp 2024-03-26 07:20:43 +08:00
fibodevy
a0c42eec91
Merge pull request #342 from thechampagne/main
add missing void
2024-03-25 23:25:56 +01:00
fibodevy
a33a2a2717
Merge pull request #343 from sitd2813/patch-1
Add MIME type for `.mjs`
2024-03-25 23:25:40 +01:00
Gihun Nam | 남기훈
2503683a31
Add MIME type for .mjs 2024-03-24 16:57:05 +09:00
XXIV
6e5ba97b5b
add missing void 2024-03-23 16:05:59 +03:00
Jazz
b1adef299f
Merge pull request #339 from mitchcapper/strict_powershell_buildscript
Use strict mode for powershell bridge script
2024-03-22 17:07:06 -04:00
Mitch Capper
57e6083b7a Use strict mode for powershell bridge script 2024-03-20 16:02:41 -07:00
fibodevy
55e38e89ce
Merge pull request #332 from webui-dev/neroist-patch-1
fix issue #315 - typo in debug logs
2024-02-26 02:58:29 +01:00
Jazz
bb055f8fa8
fix #315 typo in debug logs 2024-02-25 20:36:31 -05:00
SpikeHD
a4168b9b19 feat: expose get_best_browser to C and C++ api 2024-02-13 00:07:53 -08:00
Nicolas Boganski
3fcf8cea97 Add CMake-generated files to gitignore 2024-01-22 16:11:21 +01:00
Nicolas Boganski
328705360a Add CMake build system
New CMakeLists.txt to let users build the libraries using CMake
Build CivetWeb and then use it to build WebUI
2024-01-22 16:08:48 +01:00
iacore
88bd588905
fix: add linux dynamic library "lib" prefix 2024-01-14 16:01:23 +00:00
jinzhongjia
2a5f0c98fb readme: set zig status is complete 2024-01-13 16:19:53 +08:00
Hassan DRAGA
841def61bf
Merge pull request #304 from AlbertShown/patch-1
Adding Delphi wrapper
2024-01-12 09:30:00 -05:00
Showns
1fb87145aa
Adding Delphi wrapper 2024-01-11 17:09:09 -05:00
Hassan DRAGA
350ec1d262
Merge pull request #301 from cwegener/main
fix: too few arguments to webui_set_profile
2024-01-09 10:12:55 -05:00
Christoph Wegener
6d99a29e69
fix: too few arguments to webui_set_profile
When following the C++ hello world tutorial, the first example
immediately fails to compile due to an error in hte C++ header file.

```
In file included from main.cpp:1:
webui.hpp: In member function ‘void webui:🪟:set_proxy(std::string_view) const’:
webui.hpp:202:26: error: too few arguments to function ‘void webui_set_profile(size_t, const char*, const char*)’
  202 |         webui_set_profile(webui_window, proxy_server.data());
      |         ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from webui.hpp:21:
webui.h:422:19: note: declared here
  422 | WEBUI_EXPORT void webui_set_profile(size_t window, const char* name, const char* path);
```
2024-01-09 14:50:45 +11:00
Hassan DRAGA
e73b3cfecd New Logo
https://github.com/webui-dev/webui/discussions/292
2024-01-05 12:53:31 -05:00
Hassan DRAGA
f936a8c9e1 Update webui_set_proxy (Incomplete)
* Firefox proxy is not implemented yet
2024-01-05 11:16:24 -05:00
Hassan DRAGA
c56260ff0d
Merge pull request #297 from osljw/main
webui chromium proxy support
2024-01-05 10:43:51 -05:00
Hassan DRAGA
146f40fa51
Merge pull request #298 from webui-dev/zig-build-update
update zig nightly api changes
2024-01-05 10:28:00 -05:00
jinzhongjia
01d025117d update zig nightly api changes 2024-01-05 12:52:32 +08:00
123
5755fead94 remove chromium_options --no-proxy-server, export webui_set_proxy api 2024-01-05 09:16:11 +08:00
Hassan DRAGA
70def025c8 Adding webui.setEventCallback
* Adding new feature to WebUI Bridge to listen for connect/disconnect events in the UI. More events will be added in the future.
*
2024-01-04 16:17:51 -05:00
Ikko Eltociear Ashimine
b3a2677809 Update build.zig
exmaple -> example
2024-01-04 00:44:43 +08:00
jinzhongjia
de98b03522 Simplify build files 2024-01-03 14:31:46 +08:00
jinzhongjia
7c1e2c7588 update 2024-01-02 15:18:52 +08:00
jinzhongjia
8e990d836d Optimizing the build process
Optimizing the build process, we can now use zig to build all C examples
2024-01-02 15:18:52 +08:00
Hassan DRAGA
be5e2940e1
Merge pull request #285 from jinzhongjia/main
[fix]: build error on windows with `build.zig`
2024-01-01 12:40:04 -05:00
jinzhongjia
8e097357e6 [fix]: build error on windows 2024-01-01 22:09:23 +08:00
Hassan DRAGA
c86fc0ce97
Merge pull request #283 from jinzhongjia/build.zig
add `build.zig` to support zig build system
2023-12-31 00:40:53 -05:00
jinzhongjia
d40ce7caeb simplify build.zig 2023-12-31 13:26:57 +08:00
jinzhongjia
c6dc314dbd build.zig 2023-12-31 00:14:30 +08:00
Hassan DRAGA
36b76afeb1
Merge pull request #282 from rtanabe999/fix_typo
Fix typos
2023-12-23 00:14:07 -05:00
rtanabe999
1a495cf2d5
Fix typos 2023-12-22 11:40:42 +09:00
Hassan DRAGA
69066b18f9
Merge pull request #280 from ttytm/ci/fix-macos-artifact-upload
Fix macos artifact upload
2023-12-07 09:29:14 -05:00
Turiiya
288f1e9d39 Fix macos artifact upload 2023-12-07 10:49:35 +01:00
Hassan DRAGA
ac4ea8cd7b Fix webui_set_public 2023-11-29 18:27:44 -05:00
Hassan DRAGA
152ef446c0 Up version to v2.4.2 2023-11-29 18:25:08 -05:00
Hassan DRAGA
29e69a970f Update readme - Features 2023-11-29 18:23:54 -05:00
Hassan DRAGA
663e066f5e New API - webui_set_public
* New API: `webui_set_public()` to let window URL accessible from any public network
2023-11-29 18:23:35 -05:00
Hassan DRAGA
c063f07dcd New example - Public network access 2023-11-29 18:22:35 -05:00
Hassan DRAGA
ff6fdb1361 Make bridge use current host
* To be able to use `webui_set_public()`, the bridge should use the current hostname instead of hardcoded `localhost`.
2023-11-29 18:21:51 -05:00
Hassan DRAGA
02361e0518 Fix wrapper missing all-events call
* Issue (https://github.com/webui-dev/python-webui/issues/12)
2023-11-29 12:08:54 -05:00
Hassan DRAGA
c9801ac2ad
Merge pull request #273 from ttytm/ci/simplify-macos-yml
Simplify macos.yml
2023-11-25 07:38:23 -05:00
Turiiya
4621be9f17 Simplify macos.yml 2023-11-25 11:34:04 +01:00
122 changed files with 88394 additions and 6596 deletions

View File

@ -1,8 +1,9 @@
# http://webui.me
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2023 Hassan Draga.
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# Special Thanks to Turiiya (https://github.com/ttytm)
@ -14,6 +15,10 @@ on:
branches: [main]
paths-ignore: ['**/*.md']
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name == 'main' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
windows:
uses: ./.github/workflows/windows.yml
@ -29,3 +34,21 @@ jobs:
uses: ./.github/workflows/linux.yml
permissions:
contents: write
linux_arm:
uses: ./.github/workflows/linux_arm.yml
permissions:
contents: write
linux_redhat:
uses: ./.github/workflows/linux_redhat.yml
permissions:
contents: write
linux_arch:
uses: ./.github/workflows/linux_arch.yml
permissions:
contents: write
zig:
uses: ./.github/workflows/zig.yml

View File

@ -1,8 +1,9 @@
# http://webui.me
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2023 Hassan Draga.
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# Special Thanks to Turiiya (https://github.com/ttytm)
@ -12,97 +13,102 @@ on:
jobs:
setup:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Bundle WebUI Bridge
run: |
npm i -g esbuild
chmod +x bridge/build.sh
bridge/build.sh
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
build:
needs: setup
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
contents: write
strategy:
matrix:
compiler: [GCC, Clang]
arch: [x64]
include:
- compiler: GCC
arch: arm64
- compiler: GCC
arch: arm
- cc: gcc
arch: x64
- cc: clang
arch: x64
fail-fast: false
env:
ARTIFACT: webui-linux-${{ matrix.cc }}-${{ matrix.arch }}
CC: ${{ matrix.cc }}
steps:
- uses: actions/checkout@v3
- uses: actions/cache/restore@v3
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
fail-on-cache-miss: true
- name: Setup Libraries
- name: Setup
run: |
if [ "${{ matrix.compiler }}" == "Clang" ]; then
if [ "$CC" == "clang" ]; then
sudo ln -s llvm-ar-14 /usr/bin/llvm-ar
sudo ln -s llvm-ranlib-14 /usr/bin/llvm-ranlib
elif [ "${{ matrix.arch }}" == "arm64" ]; then
sudo apt install gcc-aarch64-linux-gnu
elif [ "${{ matrix.arch }}" == "arm" ]; then
sudo apt install gcc-arm-linux-gnueabihf
sudo ln -s llvm-strip-14 /usr/bin/llvm-strip
fi
- name: Build Debug Target
run: |
if [ "${{ matrix.arch }}" == "arm64" ]; then
make CC=aarch64-linux-gnu-gcc debug
elif [ "${{ matrix.arch }}" == "arm" ]; then
make CC=arm-linux-gnueabihf-gcc debug
else
compiler=${{ matrix.compiler }}
make CC=${compiler,,} debug
fi
run: make debug
- name: Build Release Target
if: ${{ !cancelled() }}
run: make
- name: Build TLS Debug Target
run: make WEBUI_USE_TLS=1 debug
- name: Build TLS Release Target
run: make WEBUI_USE_TLS=1
- name: Build Examples
run: |
if [ "${{ matrix.arch }}" == "arm64" ]; then
make CC=aarch64-linux-gnu-gcc
elif [ "${{ matrix.arch }}" == "arm" ]; then
make CC=arm-linux-gnueabihf-gcc
else
compiler=${{ matrix.compiler }}
make CC=${compiler,,}
fi
examples_base_dir=$(pwd)/examples/C
for example in $(find $examples_base_dir/* -maxdepth 0 -type d); do
echo "> $example"
cd $example || (exit_code=1 && continue)
if ! make; then
echo "Failed to build '$example'"
exit_code=1
continue
fi
if [[ ! -e "main" || ! -e "main-dyn" ]] ; then
echo "Failed to find executable for '$example'" && find .
exit_code=1
continue
fi
done
exit $exit_code
- name: Setup Browser
uses: browser-actions/setup-chrome@v1
- name: Prepare Artifact
run: |
cp -r include dist
artifact=webui-${{ runner.os }}-${{ matrix.compiler }}-${{ matrix.arch }}
# Convert to lowercase (`,,` ^= lowercase shell param)
artifact=${artifact,,}
# Add the ARTIFACT name as GitHub environment variable.
echo "ARTIFACT=$artifact" >> $GITHUB_ENV
mv dist/ $artifact
mv dist/ "$ARTIFACT"
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT }}
path: ${{ env.ARTIFACT }}
- name: Prepare Release
if: github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push')
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
run: |
zip -r ${{ env.ARTIFACT }}.zip ${{ env.ARTIFACT }}
zip -r "$ARTIFACT.zip" "$ARTIFACT"
if [ $GITHUB_REF_TYPE == tag ]; then
echo "TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
else
echo "IS_PRERELEASE=true" >> $GITHUB_ENV
now=$(date -u +'%Y-%m-%d %H:%M:%S UTC')
echo "TAG=nightly" >> $GITHUB_ENV
echo "BODY=Generated on <samp>$now</samp> from commit ${{ github.sha }}." >> $GITHUB_ENV
echo "TITLE=WebUI Development Build" >> $GITHUB_ENV
{
echo "IS_PRERELEASE=true";
echo "TAG=nightly";
echo "TITLE=WebUI Nightly Build $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "BODY=Generated from commit $GITHUB_SHA."
} >> $GITHUB_ENV
fi
- name: Update Nightly Tag
if: env.IS_PRERELEASE
@ -112,7 +118,9 @@ jobs:
with:
tag_name: nightly
- name: Release
if: github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push')
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
uses: ncipollo/release-action@v1
with:
artifacts: ${{ env.ARTIFACT }}.zip
@ -121,3 +129,65 @@ jobs:
name: ${{ env.TITLE }}
prerelease: ${{ env.IS_PRERELEASE }}
allowUpdates: true
build-ubuntu-22:
needs: setup
runs-on: ubuntu-22.04
permissions:
contents: write
strategy:
matrix:
include:
- cc: gcc
arch: x64
- cc: clang
arch: x64
fail-fast: false
env:
ARTIFACT: webui-linux-${{ matrix.cc }}-${{ matrix.arch }}
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
fail-on-cache-miss: true
- name: Setup
run: |
CC="${{ matrix.cc }}"
if [ "$CC" == "clang" ]; then
sudo ln -s llvm-ar-14 /usr/bin/llvm-ar
sudo ln -s llvm-ranlib-14 /usr/bin/llvm-ranlib
sudo ln -s llvm-strip-14 /usr/bin/llvm-strip
else
sudo apt -qq install gcc-11
CC+="-11"
fi
echo "CC=$CC" >> $GITHUB_ENV
- name: Build Debug Target
run: make debug
- name: Build Release Target
if: ${{ !cancelled() }}
run: make
- name: Build TLS Debug Target
run: make WEBUI_USE_TLS=1 debug
- name: Build TLS Release Target
run: make WEBUI_USE_TLS=1
- name: Build Examples
run: |
examples_base_dir=$(pwd)/examples/C
for example in $(find $examples_base_dir/* -maxdepth 0 -type d); do
echo "> $example"
cd $example || (exit_code=1 && continue)
if ! make; then
echo "Failed to build '$example'"
exit_code=1
continue
fi
if [[ ! -e "main" || ! -e "main-dyn" ]] ; then
echo "Failed to find executable for '$example'" && find .
exit_code=1
continue
fi
done
exit $exit_code

111
.github/workflows/linux_arch.yml vendored Normal file
View File

@ -0,0 +1,111 @@
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
name: Linux-Arch
on:
workflow_call:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- cc: gcc
arch: x64
- cc: clang
arch: x64
fail-fast: false
env:
ARTIFACT: webui-linux-arch-${{ matrix.cc }}-${{ matrix.arch }}
CC: ${{ matrix.cc }}
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build Arch Linux Docker Image
run: |
docker build -t archlinux:latest - <<EOF
FROM archlinux:latest
RUN pacman -Syu --noconfirm git npm make gcc clang llvm lld
EOF
- name: Run build inside Arch Linux container
run: |
docker run --rm \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
--user root \
-e CC=${{ matrix.cc }} \
archlinux:latest \
bash -c "
git config --global --add safe.directory /workspace &&
npm i -g esbuild &&
chmod +x bridge/build.sh &&
if [ '${{ matrix.cc }}' == 'clang' ]; then
export AR=llvm-ar
export STRIP=llvm-strip
fi &&
./bridge/build.sh &&
make debug &&
make &&
make WEBUI_USE_TLS=1 debug &&
make WEBUI_USE_TLS=1 &&
chown -R $(id -u):$(id -g) /workspace
"
- name: Prepare Artifact
run: |
cp -r include dist
mv dist/ "$ARTIFACT"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT }}
path: ${{ env.ARTIFACT}}
- name: Prepare Release
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
run: |
zip -r "$ARTIFACT.zip" "$ARTIFACT"
if [ $GITHUB_REF_TYPE == tag ]; then
echo "TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
else
{
echo "IS_PRERELEASE=true";
echo "TAG=nightly";
echo "TITLE=WebUI Nightly Build $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "BODY=Generated from commit $GITHUB_SHA."
} >> $GITHUB_ENV
fi
- name: Update Nightly Tag
if: env.IS_PRERELEASE
uses: richardsimko/update-tag@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: nightly
- name: Release
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
uses: ncipollo/release-action@v1
with:
artifacts: ${{ env.ARTIFACT }}.zip
tag: ${{ env.TAG }}
body: ${{ env.BODY }}
name: ${{ env.TITLE }}
prerelease: ${{ env.IS_PRERELEASE }}
allowUpdates: true

165
.github/workflows/linux_arm.yml vendored Normal file
View File

@ -0,0 +1,165 @@
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# Special Thanks to Turiiya (https://github.com/ttytm)
name: Linux ARM
on:
workflow_call:
jobs:
setup:
runs-on: buildjet-32vcpu-ubuntu-2204-arm
steps:
- uses: actions/checkout@v4
- name: Check CPU Architecture
run: |
ARCH=$(uname -m)
if [[ "$ARCH" != "arm"* && "$ARCH" != "aarch64" ]]; then
echo "Expected ARM-based CPU architecture. Detected: $ARCH"
exit 1
else
echo "ARM CPU Detected: $ARCH"
fi
- name: Bundle WebUI Bridge
run: |
npm i -g esbuild
chmod +x bridge/build.sh
bridge/build.sh
- uses: actions/cache@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
build:
needs: setup
# Same as `buildjet-32vcpu-ubuntu-2204-arm`
runs-on: ubuntu-22.04
permissions:
contents: write
strategy:
matrix:
include:
- cc: gcc
arch: arm
- cc: gcc
arch: arm64
fail-fast: false
env:
ARTIFACT: webui-linux-${{ matrix.cc }}-${{ matrix.arch }}
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
fail-on-cache-miss: true
- name: Setup
run: |
CC=${{ matrix.cc }}
if [ "${{ matrix.arch }}" == "arm64" ]; then
sudo apt update
sudo apt install -y gcc-aarch64-linux-gnu
CC=aarch64-linux-gnu-gcc
wget https://github.com/openssl/openssl/releases/download/openssl-3.3.1/openssl-3.3.1.tar.gz
tar -xzf openssl-3.3.1.tar.gz
cd openssl-3.3.1
./Configure linux-generic64 --prefix=/usr/aarch64-linux-gnu --cross-compile-prefix=aarch64-linux-gnu- --release -latomic
make
sudo make install
elif [ "${{ matrix.arch }}" == "arm" ]; then
sudo apt update
sudo apt install -y gcc-arm-linux-gnueabi
CC=arm-linux-gnueabi-gcc
wget https://github.com/openssl/openssl/releases/download/openssl-3.3.1/openssl-3.3.1.tar.gz
tar -xzf openssl-3.3.1.tar.gz
cd openssl-3.3.1
./Configure linux-generic32 --prefix=/usr/arm-linux-gnueabi --cross-compile-prefix=arm-linux-gnueabi- --release -latomic
make
sudo make install
fi
echo "CC=$CC" >> $GITHUB_ENV
- name: Build Debug Target
run: make debug
- name: Build Release Target
if: ${{ !cancelled() }}
run: make
- name: Build TLS Debug ARM64 Target
if: matrix.arch == 'arm64'
run: make WEBUI_USE_TLS=1 debug WEBUI_TLS_INCLUDE="/usr/aarch64-linux-gnu/include" WEBUI_TLS_LIB="/usr/aarch64-linux-gnu/lib"
- name: Build TLS Debug ARM Target
if: matrix.arch == 'arm'
run: make WEBUI_USE_TLS=1 debug WEBUI_TLS_INCLUDE="/usr/arm-linux-gnueabi/include" WEBUI_TLS_LIB="/usr/arm-linux-gnueabi/lib"
- name: Build TLS Release ARM64 Target
if: matrix.arch == 'arm64'
run: make WEBUI_USE_TLS=1 WEBUI_TLS_INCLUDE="/usr/aarch64-linux-gnu/include" WEBUI_TLS_LIB="/usr/aarch64-linux-gnu/lib"
- name: Build TLS Release ARM Target
if: matrix.arch == 'arm'
run: make WEBUI_USE_TLS=1 WEBUI_TLS_INCLUDE="/usr/arm-linux-gnueabi/include" WEBUI_TLS_LIB="/usr/arm-linux-gnueabi/lib"
# - name: Build Examples
# if: matrix.arch == 'arm64'
# run: |
# examples_base_dir=$(pwd)/examples/C
# for example in $(find $examples_base_dir/* -maxdepth 0 -type d); do
# echo "> $example"
# cd $example || (exit_code=1 && continue)
# if ! make CC=aarch64-linux-gnu-gcc; then
# echo "Failed to build '$example'"
# exit_code=1
# continue
# fi
# if [[ ! -e "main" || ! -e "main-dyn" ]] ; then
# echo "Failed to find executable for '$example'" && find .
# exit_code=1
# continue
# fi
# done
# exit $exit_code
- name: Prepare Artifact
run: |
cp -r include dist
mv dist/ "$ARTIFACT"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT }}
path: ${{ env.ARTIFACT }}
- name: Prepare Release
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
run: |
zip -r "$ARTIFACT.zip" "$ARTIFACT"
if [ $GITHUB_REF_TYPE == tag ]; then
echo "TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
else
{
echo "IS_PRERELEASE=true";
echo "TAG=nightly";
echo "TITLE=WebUI Nightly Build $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "BODY=Generated from commit $GITHUB_SHA."
} >> $GITHUB_ENV
fi
- name: Update Nightly Tag
if: env.IS_PRERELEASE
uses: richardsimko/update-tag@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: nightly
- name: Release
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
uses: ncipollo/release-action@v1
with:
artifacts: ${{ env.ARTIFACT }}.zip
tag: ${{ env.TAG }}
body: ${{ env.BODY }}
name: ${{ env.TITLE }}
prerelease: ${{ env.IS_PRERELEASE }}
allowUpdates: true

113
.github/workflows/linux_redhat.yml vendored Normal file
View File

@ -0,0 +1,113 @@
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
name: Linux-RedHat
on:
workflow_call:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- cc: gcc
arch: x64
- cc: clang
arch: x64
fail-fast: false
env:
ARTIFACT: webui-linux-redhat-${{ matrix.cc }}-${{ matrix.arch }}
CC: ${{ matrix.cc }}
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build RedHat Docker Image
run: |
docker build -t redhat:latest - <<EOF
FROM almalinux:9
RUN dnf install -y epel-release
RUN dnf groupinstall -y "Development Tools"
RUN dnf install -y git nodejs npm clang llvm-toolset lld openssl-devel
EOF
- name: Run build inside RedHat container
run: |
docker run --rm \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
--user root \
-e CC=${{ matrix.cc }} \
redhat:latest \
bash -c "
git config --global --add safe.directory /workspace &&
npm i -g esbuild &&
chmod +x bridge/build.sh &&
if [ '${{ matrix.cc }}' == 'clang' ]; then
export AR=llvm-ar
export STRIP=llvm-strip
fi &&
./bridge/build.sh &&
make debug &&
make &&
make WEBUI_USE_TLS=1 debug &&
make WEBUI_USE_TLS=1 &&
chown -R $(id -u):$(id -g) /workspace
"
- name: Prepare Artifact
run: |
cp -r include dist
mv dist/ "$ARTIFACT"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT }}
path: ${{ env.ARTIFACT }}
- name: Prepare Release
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
run: |
zip -r "$ARTIFACT.zip" "$ARTIFACT"
if [ $GITHUB_REF_TYPE == tag ]; then
echo "TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
else
{
echo "IS_PRERELEASE=true";
echo "TAG=nightly";
echo "TITLE=WebUI Nightly Build $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "BODY=Generated from commit $GITHUB_SHA."
} >> $GITHUB_ENV
fi
- name: Update Nightly Tag
if: env.IS_PRERELEASE
uses: richardsimko/update-tag@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: nightly
- name: Release
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
uses: ncipollo/release-action@v1
with:
artifacts: ${{ env.ARTIFACT }}.zip
tag: ${{ env.TAG }}
body: ${{ env.BODY }}
name: ${{ env.TITLE }}
prerelease: ${{ env.IS_PRERELEASE }}
allowUpdates: true

View File

@ -1,8 +1,9 @@
# http://webui.me
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2023 Hassan Draga.
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# Special Thanks to Turiiya (https://github.com/ttytm)
@ -14,13 +15,13 @@ jobs:
setup:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Bundle WebUI Bridge
run: |
npm i -g esbuild
chmod +x bridge/build.sh
bridge/build.sh
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
@ -32,46 +33,76 @@ jobs:
contents: write
strategy:
matrix:
compiler: [Clang]
cc: [clang]
arch: [x64, arm64]
fail-fast: false
env:
ARTIFACT: webui-macos-${{ matrix.cc }}-${{ matrix.arch }}
steps:
- uses: actions/checkout@v3
- uses: actions/cache/restore@v3
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
fail-on-cache-miss: true
- name: Setup OpenSSL
run: |
echo "WEBUI_TLS_INCLUDE=$(brew --cellar)/openssl@1.1/1.1.1w/include/" >> $GITHUB_ENV
echo "WEBUI_TLS_LIB=$(brew --cellar)/openssl@1.1/1.1.1w/lib/" >> $GITHUB_ENV
- name: Build Debug Target
run: make ARCH_TARGET=${{ matrix.arch }} debug
- name: Build Release Target
if: ${{ !cancelled() }}
run: make ARCH_TARGET=${{ matrix.arch }}
- name: Build TLS Debug Target
if: ${{ matrix.arch != 'x64' }}
run: make ARCH_TARGET=${{ matrix.arch }} WEBUI_USE_TLS=1 debug
- name: Build TLS Release Target
if: ${{ matrix.arch != 'x64' }}
run: make ARCH_TARGET=${{ matrix.arch }} WEBUI_USE_TLS=1
- name: Build examples
if: ${{ matrix.arch != 'x64' }}
run: |
examples_base_dir=$(pwd)/examples/C
for example in $(find $examples_base_dir/* -maxdepth 0 -type d); do
echo "> $example"
cd $example || (exit_code=1 && continue)
if ! make ARCH_TARGET=${{ matrix.arch }}; then
echo "Failed to build '$example'"
exit_code=1
continue
fi
if [[ ! -e "main" || ! -e "main-dyn" ]] ; then
echo "Failed to find executable for '$example'" && find .
exit_code=1
continue
fi
done
exit $exit_code
- name: Prepare Artifacts
run: |
cp -r include dist
# Add the ARTIFACT name(lowercased) as GitHub environment variable.
artifact=webui-$(echo ${{ runner.os }}-${{ matrix.compiler }}-${{ matrix.arch }} | tr '[:upper:]' '[:lower:]')
chmod -x dist/webui-2.dylib
chmod -x dist/debug/webui-2.dylib
mv dist/ $artifact
zip -r $artifact.zip $artifact
# Add the artifact name as GitHub environment variable for usage in later steps.
echo "ARTIFACT=$artifact" >> $GITHUB_ENV
mv dist/ "$ARTIFACT"
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT }}
path: ${{ env.ARTIFACT }}.zip
path: ${{ env.ARTIFACT }}
- name: Prepare Release
if: github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push')
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
run: |
zip -r "$ARTIFACT.zip" "$ARTIFACT"
if [ $GITHUB_REF_TYPE == tag ]; then
echo "TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
else
echo "IS_PRERELEASE=true" >> $GITHUB_ENV
now=$(date -u +'%Y-%m-%d %H:%M:%S UTC')
echo "TAG=nightly" >> $GITHUB_ENV
echo "BODY=Generated on <samp>$now</samp> from commit ${{ github.sha }}." >> $GITHUB_ENV
echo "TITLE=WebUI Development Build" >> $GITHUB_ENV
{
echo "IS_PRERELEASE=true";
echo "TAG=nightly";
echo "TITLE=WebUI Nightly Build $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "BODY=Generated from commit $GITHUB_SHA."
} >> $GITHUB_ENV
fi
- name: Update Nightly Tag
if: env.IS_PRERELEASE
@ -81,7 +112,9 @@ jobs:
with:
tag_name: nightly
- name: Release
if: github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push')
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
uses: ncipollo/release-action@v1
with:
artifacts: ${{ env.ARTIFACT }}.zip

View File

@ -1,8 +1,9 @@
# http://webui.me
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2023 Hassan Draga.
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# Special Thanks to Turiiya (https://github.com/ttytm)
@ -14,10 +15,10 @@ jobs:
setup:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Bundle WebUI Bridge
run: bridge/build.ps1
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
@ -29,62 +30,87 @@ jobs:
contents: write
strategy:
matrix:
compiler: [GCC, MSVC]
cc: ['gcc', 'msvc']
include:
- cc: gcc
make: mingw32-make
- cc: msvc
make: nmake
fail-fast: false
env:
ARTIFACT: webui-windows-${{ matrix.cc }}-x64
WEBUI_TLS_INCLUDE: "C:\\Program Files\\OpenSSL\\include"
WEBUI_TLS_LIB: "C:\\Program Files\\OpenSSL\\lib"
steps:
- uses: actions/checkout@v3
- uses: actions/cache/restore@v3
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: bridge/webui_bridge.h
key: ${{ runner.os }}-${{ github.sha }}-bridge
fail-on-cache-miss: true
- uses: microsoft/setup-msbuild@v1.1
- if: matrix.compiler == 'MSVC'
uses: ilammy/msvc-dev-cmd@v1
- uses: microsoft/setup-msbuild@v2
- uses: ilammy/msvc-dev-cmd@v1
if: matrix.cc == 'msvc'
- name: Build Debug Target
run: |
if ('${{ matrix.compiler }}' -eq 'MSVC') {
nmake debug
} else {
mingw32-make debug
}
run: ${{ matrix.make }} debug
- name: Build Release Target
if: ${{ !cancelled() }}
run: ${{ matrix.make }}
- name: Build TLS Debug Target
run: ${{ matrix.make }} WEBUI_USE_TLS=1 debug
- name: Build TLS Release Target
run: ${{ matrix.make }} WEBUI_USE_TLS=1
- name: Build examples
run: |
if ('${{ matrix.compiler }}' -eq 'MSVC') {
nmake
} else {
mingw32-make
$examples_base_dir = "$(Get-Location)/examples/C/"
foreach ($example in Get-ChildItem -Path $examples_base_dir -Directory) {
Write-Host "> $example"
Set-Location -Path $example.FullName
if (!$?) {
$exit_code = 1
continue
}
$make_output = Invoke-Expression ${{ matrix.make }}
if (!$?) {
Write-Host "Failed to build '$example': $make_output"
$exit_code = 1
continue
}
Write-Output $make_output
if (!(Test-Path "main.exe") -or !(Test-Path "main-dyn.exe")) {
Write-Host "Failed to find executable for '$example'"
Get-ChildItem
$exit_code = 1
continue
}
}
exit $exit_code
- name: Prepare Artifact
shell: bash
run: |
cp -r include dist
artifact=webui-${{ runner.os }}-${{ matrix.compiler }}-x64
# Convert to lowercase (`,,` ^= lowercase shell param)
artifact=${artifact,,}
# Create the directory for the artifact
mkdir $artifact
# Add the ARTIFACT name as GitHub environment variable.
echo "ARTIFACT=$artifact" >> $GITHUB_ENV
mv dist/* $artifact/
mv dist/ "$ARTIFACT"
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.ARTIFACT }}
path: ${{ env.ARTIFACT }}
- name: Prepare Release
if: github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push')
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
shell: bash
run: |
7z a -tzip ${{ env.ARTIFACT }}.zip ${{ env.ARTIFACT }}/*
7z a -tzip "$ARTIFACT.zip" "$ARTIFACT/*"
if [ $GITHUB_REF_TYPE == tag ]; then
echo "TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
else
echo "IS_PRERELEASE=true" >> $GITHUB_ENV
now=$(date -u +'%Y-%m-%d %H:%M:%S UTC')
echo "TAG=nightly" >> $GITHUB_ENV
echo "BODY=Generated on <samp>$now</samp> from commit ${{ github.sha }}." >> $GITHUB_ENV
echo "TITLE=WebUI Development Build" >> $GITHUB_ENV
{
echo "IS_PRERELEASE=true";
echo "TAG=nightly";
echo "TITLE=WebUI Nightly Build $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
echo "BODY=Generated from commit $GITHUB_SHA."
} >> $GITHUB_ENV
fi
- name: Update Nightly Tag
if: env.IS_PRERELEASE
@ -94,7 +120,9 @@ jobs:
with:
tag_name: nightly
- name: Release
if: github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push')
if: >
github.repository_owner == 'webui-dev'
&& (github.ref_type == 'tag' || (github.ref_name == 'main' && github.event_name == 'push'))
uses: ncipollo/release-action@v1
with:
artifacts: ${{ env.ARTIFACT }}.zip

36
.github/workflows/zig.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: Zig Build
on:
workflow_call:
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
version: [0.14.0, '']
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: maxim-lobanov/setup-xcode@v1
if: runner.os == 'macOS'
with:
xcode-version: latest-stable
- uses: actions/checkout@v4
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: ${{ matrix.version }}
- name: Build static library
run: zig build -Dverbose=debug
- name: Build dynamic library
if: ${{ !cancelled() }}
run: zig build -Ddynamic -Dverbose=debug
- name: Build static library with TLS support
if: runner.os == 'Linux'
run: zig build -Denable-tls -Dverbose=debug
- name: Build dynamic library with TLS support
if: runner.os == 'Linux'
run: zig build -Ddynamic -Denable-tls -Dverbose=debug
- name: Build examples
run: zig build examples

20
.gitignore vendored
View File

@ -8,6 +8,14 @@ build/
*.out
*.def
# All sub-level build binaries
*/**/*
!*/**/*/
!*/**/*.*
!*makefile
!Makefile
*/**/*.exe
# Compiled Object files
*.slo
*.lo
@ -40,6 +48,7 @@ build/
*.recipe
*.idb
*.iobj
*.pdb
# Visual Studio for Mac
.idea/
@ -108,11 +117,12 @@ Thumbs.db
# User-specific private settings
*.DotSettings.user
# Example binaries
examples/**/main
examples/**/main-dyn
examples/**/text-editor/text-editor
# Compressed
*.zip
*.gz
# CMake
**/cmake_install.cmake
**/CMakeCache.txt
**/CMakeFiles/
.zig-cache

59
CMakeLists.txt Normal file
View File

@ -0,0 +1,59 @@
cmake_minimum_required(VERSION 3.10)
# Project name
project(WebUILibrary)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Variables for library names, source files, etc.
set(WEBUI_OUT_LIB_NAME "webui-2")
# Conditional compilation for TLS
option(WEBUI_USE_TLS "Enable TLS support" OFF)
if(WEBUI_USE_TLS)
find_package(OpenSSL REQUIRED)
set(WEBUI_OUT_LIB_NAME "webui-2-secure")
endif()
# Source files (already filled)
set(SOURCE_FILES
src/civetweb/civetweb.c
src/webui.c
)
# Library targets
add_library(webui ${SOURCE_FILES})
target_include_directories(webui PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
target_compile_definitions(webui PUBLIC NDEBUG NO_CACHING NO_CGI USE_WEBSOCKET)
if(BUILD_SHARED_LIBS AND WIN32)
target_compile_definitions(webui PRIVATE CIVETWEB_DLL_EXPORTS PUBLIC CIVETWEB_DLL_IMPORTS)
endif()
if(WEBUI_USE_TLS)
target_compile_definitions(webui PUBLIC WEBUI_TLS NO_SSL_DL OPENSSL_API_1_1)
target_link_libraries(webui PRIVATE OpenSSL::SSL OpenSSL::Crypto)
else()
target_compile_definitions(webui PUBLIC NO_SSL)
endif()
set_target_properties(webui PROPERTIES
OUTPUT_NAME ${WEBUI_OUT_LIB_NAME}
PREFIX "")
# Install headers
install(FILES include/webui.h include/webui.hpp DESTINATION include)
# Install targets
install(TARGETS webui
EXPORT webui
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
install(EXPORT webui
FILE webui-config.cmake
NAMESPACE webui::
DESTINATION share/webui
)

View File

@ -4,16 +4,23 @@
WEBUI_OUT_LIB_NAME = webui-2
# Detect the OS once
ifeq ($(OS),Windows_NT)
DETECTED_OS := Windows
else
DETECTED_OS := $(shell uname -s)
endif
# TLS
WEBUI_USE_TLS =
WEBUI_TLS_INCLUDE = .
WEBUI_TLS_LIB = .
WEBUI_TLS_INCLUDE ?= .
WEBUI_TLS_LIB ?= .
TLS_CFLAG = -DNO_SSL
TLS_LDFLAG_DYNAMIC =
ifeq ($(WEBUI_USE_TLS), 1)
WEBUI_OUT_LIB_NAME = webui-2-secure
TLS_CFLAG = -DWEBUI_TLS -DNO_SSL_DL -DOPENSSL_API_1_1
ifeq ($(OS),Windows_NT)
ifeq ($(DETECTED_OS),Windows)
TLS_LDFLAG_DYNAMIC = -lssl -lcrypto -lbcrypt
else
TLS_LDFLAG_DYNAMIC = -lssl -lcrypto
@ -25,10 +32,13 @@ MAKEFILE_DIR := $(dir $(MAKEFILE_PATH))
BUILD_DIR := $(MAKEFILE_DIR)/dist
# ARGS
# Set a compiler when running on Linux via `make CC=gcc` / `make CC=clang`
CC = gcc
ifneq ($(filter $(CC),gcc clang aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc musl-gcc),$(CC))
$(error Invalid compiler specified: `$(CC)`)
CC ?= gcc
ifeq ($(CC), cc)
ifeq ($(DETECTED_OS),Darwin)
CC = clang
else
CC = gcc
endif
endif
# Allow to add arch-target for macOS CI cross compilation
@ -37,7 +47,9 @@ ARCH_TARGET ?=
# BUILD FLAGS
CIVETWEB_BUILD_FLAGS := -o civetweb.o -I"$(MAKEFILE_DIR)/include/" -c "$(MAKEFILE_DIR)/src/civetweb/civetweb.c" -I"$(WEBUI_TLS_INCLUDE)" $(TLS_CFLAG) -w
CIVETWEB_DEFINE_FLAGS = -DNDEBUG -DNO_CACHING -DNO_CGI -DUSE_WEBSOCKET $(TLS_CFLAG)
WEBUI_BUILD_FLAGS := -o webui.o -I"$(MAKEFILE_DIR)/include/" -c "$(MAKEFILE_DIR)/src/webui.c" -I"$(WEBUI_TLS_INCLUDE)" $(TLS_CFLAG) -w
WEBUI_BUILD_FLAGS := -o webui.o -I"$(MAKEFILE_DIR)/include/" -c "$(MAKEFILE_DIR)/src/webui.c" -I"$(WEBUI_TLS_INCLUDE)" $(TLS_CFLAG)
WARNING_RELEASE := -w
WARNING_LOG := -Wall -Wno-unused
# OUTPUT FILES
# The static output is the same for all platforms
@ -45,32 +57,41 @@ WEBUI_BUILD_FLAGS := -o webui.o -I"$(MAKEFILE_DIR)/include/" -c "$(MAKEFILE_DIR)
LIB_STATIC_OUT := lib$(WEBUI_OUT_LIB_NAME)-static.a
# Platform defaults and dynamic library outputs
ifeq ($(OS),Windows_NT)
ifeq ($(DETECTED_OS),Windows)
# Windows
SHELL := CMD
PLATFORM := windows
LIB_DYN_OUT := $(WEBUI_OUT_LIB_NAME).dll
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
CIVETWEB_DEFINE_FLAGS += -DMUST_IMPLEMENT_CLOCK_GETTIME
else ifeq ($(shell uname),Darwin)
else ifeq ($(DETECTED_OS),Darwin)
# MacOS
PLATFORM := macos
CC = clang
LIB_DYN_OUT := $(WEBUI_OUT_LIB_NAME).dylib
LIB_DYN_OUT := lib$(WEBUI_OUT_LIB_NAME).dylib
WEBKIT_OBJ := wkwebview.o
WKWEBKIT_BUILD_FLAGS := -o wkwebview.o -c "$(MAKEFILE_DIR)/src/webview/wkwebview.m"
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
LIB_DYN_OUT := $(WEBUI_OUT_LIB_NAME).so
LIB_DYN_OUT := lib$(WEBUI_OUT_LIB_NAME).so
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
# macOS can set `ARCH_TARGET=arm64` - intented for CI cross-compilation.
# macOS can set `ARCH_TARGET=arm64` for cross-compilation.
ifneq ($(ARCH_TARGET),)
ifneq ($(PLATFORM),macos)
$(error ARCH_TARGET is only available on macOS)
else ifeq ($(ARCH_TARGET),arm64)
TARGET := -target arm64-apple-darwin
endif
ifeq ($(ARCH_TARGET),arm64)
TARGET := -target arm64-apple-darwin -arch arm64
else ifeq ($(ARCH_TARGET),x64)
TARGET := -target x86_64-apple-darwin -arch x86_64
else
$(error Unsupported ARCH_TARGET: $(ARCH_TARGET). Use 'arm64' or 'x64'.)
endif
endif
@ -93,19 +114,25 @@ ifeq ($(PLATFORM),windows)
else
@mkdir -p "$(BUILD_DIR)/debug"
endif
# Build macOS WKWebView
ifeq ($(DETECTED_OS),Darwin)
@cd "$(BUILD_DIR)/debug" \
&& echo "Build WebUI Objective-C WKWebKit ($(CC) $(TARGET) debug)..." \
&& $(CC) $(TARGET) $(WKWEBKIT_BUILD_FLAGS) -g -DWEBUI_LOG
endif
# Static with Debug info
@cd "$(BUILD_DIR)/debug" \
&& echo "Build WebUI library ($(CC) $(TARGET)debug static)..." \
&& echo "Build WebUI library ($(CC) $(TARGET) debug static)..." \
&& $(CC) $(TARGET) $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS) -g \
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) -g -DWEBUI_LOG \
&& $(LLVM_OPT)ar rc $(LIB_STATIC_OUT) webui.o civetweb.o \
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) $(WARNING_LOG) -g -DWEBUI_LOG \
&& $(LLVM_OPT)ar rc $(LIB_STATIC_OUT) webui.o civetweb.o $(WEBKIT_OBJ) \
&& $(LLVM_OPT)ranlib $(LIB_STATIC_OUT)
# Dynamic with Debug info
@cd "$(BUILD_DIR)/debug" \
&& echo "Build WebUI library ($(CC) $(TARGET)debug dynamic)..." \
&& echo "Build WebUI library ($(CC) $(TARGET) debug dynamic)..." \
&& $(CC) $(TARGET) $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS) -g -fPIC \
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) -g -fPIC -DWEBUI_LOG \
&& $(CC) $(TARGET) -shared -o $(LIB_DYN_OUT) webui.o civetweb.o -g -L"$(WEBUI_TLS_LIB)" $(TLS_LDFLAG_DYNAMIC) $(LWS2_OPT)
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) $(WARNING_LOG) -g -fPIC -DWEBUI_LOG -DWEBUI_DYNAMIC \
&& $(CC) $(TARGET) -shared -o $(LIB_DYN_OUT) webui.o civetweb.o $(WEBKIT_OBJ) -g -L"$(WEBUI_TLS_LIB)" $(TLS_LDFLAG_DYNAMIC) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS)
ifeq ($(PLATFORM),windows)
@cd "$(BUILD_DIR)/debug" && del *.o >nul 2>&1
else
@ -120,19 +147,25 @@ ifeq ($(PLATFORM),windows)
else
@mkdir -p "$(BUILD_DIR)"
endif
# Build macOS WKWebView
ifeq ($(DETECTED_OS),Darwin)
@cd "$(BUILD_DIR)" \
&& echo "Build WebUI Objective-C WKWebKit ($(CC) $(TARGET) release)..." \
&& $(CC) $(TARGET) $(WKWEBKIT_BUILD_FLAGS) -Os
endif
# Static Release
@cd "$(BUILD_DIR)" \
&& echo "Build WebUI library ($(CC) $(TARGET)release static)..." \
&& echo "Build WebUI library ($(CC) $(TARGET) release static)..." \
&& $(CC) $(TARGET) $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS) -Os \
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) -Os \
&& $(LLVM_OPT)ar rc $(LIB_STATIC_OUT) webui.o civetweb.o \
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) $(WARNING_RELEASE) -Os \
&& $(LLVM_OPT)ar rc $(LIB_STATIC_OUT) webui.o civetweb.o $(WEBKIT_OBJ) \
&& $(LLVM_OPT)ranlib $(LIB_STATIC_OUT)
# Dynamic Release
@cd "$(BUILD_DIR)" \
&& echo "Build WebUI library ($(CC) $(TARGET)release dynamic)..." \
&& echo "Build WebUI library ($(CC) $(TARGET) release dynamic)..." \
&& $(CC) $(TARGET) $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS) -Os -fPIC \
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) -O3 -fPIC \
&& $(CC) $(TARGET) -shared -o $(LIB_DYN_OUT) webui.o civetweb.o -L"$(WEBUI_TLS_LIB)" $(TLS_LDFLAG_DYNAMIC) $(LWS2_OPT)
&& $(CC) $(TARGET) $(WEBUI_BUILD_FLAGS) $(WARNING_RELEASE) -O3 -fPIC -DWEBUI_DYNAMIC \
&& $(CC) $(TARGET) -shared -o $(LIB_DYN_OUT) webui.o civetweb.o $(WEBKIT_OBJ) -L"$(WEBUI_TLS_LIB)" $(TLS_LDFLAG_DYNAMIC) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS)
# Clean
ifeq ($(PLATFORM),windows)
@strip --strip-unneeded $(BUILD_DIR)/$(LIB_DYN_OUT)

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Hassan Draga
Copyright (c) 2025 Hassan Draga
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -4,27 +4,39 @@
# == 1. VARIABLES =============================================================
WEBUI_OUT_LIB_NAME = webui-2
TLS_CFLAG = /DNO_SSL
# TLS
WEBUI_USE_TLS =
WEBUI_TLS_INCLUDE = .
WEBUI_TLS_LIB = .
TLS_CFLAG = /D NO_SSL
TLS_LDFLAG_DYNAMIC =
# TLS Enabled
!IF "$(WEBUI_USE_TLS)" == "1"
WEBUI_OUT_LIB_NAME = webui-2-secure
TLS_CFLAG = /D WEBUI_TLS /D NO_SSL_DL /D OPENSSL_API_1_1
TLS_CFLAG = /DWEBUI_TLS /DNO_SSL_DL /DOPENSSL_API_1_1
TLS_LDFLAG_DYNAMIC = libssl.lib libcrypto.lib
!IF "$(WEBUI_TLS_INCLUDE)" != ""
TLS_CFLAG = $(TLS_CFLAG) /I"$(WEBUI_TLS_INCLUDE)"
!ELSE
TLS_CFLAG = $(TLS_CFLAG) /I"."
!ENDIF
!IF "$(WEBUI_TLS_LIB)" != ""
TLS_LDFLAG_DYNAMIC = $(TLS_LDFLAG_DYNAMIC) /LIBPATH:"$(WEBUI_TLS_LIB)"
!ELSE
TLS_LDFLAG_DYNAMIC += $(TLS_LDFLAG_DYNAMIC) /LIBPATH:"."
!ENDIF
!ENDIF
# Build Flags
CIVETWEB_BUILD_FLAGS = /Fo"civetweb.obj" /c /EHsc "$(MAKEDIR)/src/civetweb/civetweb.c" /I"$(MAKEDIR)/src/civetweb/" /I"$(WEBUI_TLS_INCLUDE)"
CIVETWEB_DEFINE_FLAGS = /D NDEBUG /D NO_CACHING /D NO_CGI /D USE_WEBSOCKET $(TLS_CFLAG)
CIVETWEB_BUILD_FLAGS = /Fo"civetweb.obj" /c /EHsc "$(MAKEDIR)/src/civetweb/civetweb.c" /I"$(MAKEDIR)/src/civetweb/" $(TLS_CFLAG)
CIVETWEB_DEFINE_FLAGS = /D NDEBUG /D NO_CACHING /D NO_CGI /D USE_WEBSOCKET
WEBUI_BUILD_FLAGS = /Fo"webui.obj" /c /EHsc "$(MAKEDIR)/src/webui.c" /I"$(MAKEDIR)/include" /I"$(WEBUI_TLS_INCLUDE)" $(TLS_CFLAG)
WARNING_RELEASE = /w
WARNING_LOG = /W4
# Output Commands
LIB_STATIC_OUT = /OUT:"$(WEBUI_OUT_LIB_NAME)-static.lib" "webui.obj" "civetweb.obj"
LIB_DYN_OUT = /DLL /OUT:"$(WEBUI_OUT_LIB_NAME).dll" "webui.obj" "civetweb.obj" user32.lib Advapi32.lib Shell32.lib /LIBPATH:"$(WEBUI_TLS_LIB)" $(TLS_LDFLAG_DYNAMIC)
LIB_DYN_OUT = /DLL /OUT:"$(WEBUI_OUT_LIB_NAME).dll" "webui.obj" "civetweb.obj" user32.lib Advapi32.lib Shell32.lib Ole32.lib $(TLS_LDFLAG_DYNAMIC)
# == 2.TARGETS ================================================================
@ -36,18 +48,16 @@ debug:
@- cd $(MAKEDIR)/dist/debug
@echo Build WebUI Library (MSVC Debug Static)...
@cl /Zl /Zi $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS)
@cl /Zl /Zi $(WEBUI_BUILD_FLAGS) /D WEBUI_LOG
@cl /Zl /Zi $(WEBUI_BUILD_FLAGS) $(WARNING_LOG) /D WEBUI_LOG
@lib $(LIB_STATIC_OUT)
# Dynamic with Debug info
@echo Build WebUI Library (MSVC Debug Dynamic)...
@cl /Zi $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS)
@cl /Zi $(WEBUI_BUILD_FLAGS) /D WEBUI_LOG
@cl /Zi $(WEBUI_BUILD_FLAGS) $(WARNING_LOG) /D WEBUI_LOG /D WEBUI_DYNAMIC
@link $(LIB_DYN_OUT)
# Clean
@- del *.pdb >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.pdb >nul 2>&1
@- del *.exp >nul 2>&1
@echo Done.
@ -57,18 +67,17 @@ release:
# Static Release
@echo Build WebUI Library (MSVC Release Static)...
@cl /Zl $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS)
@cl /Zl $(WEBUI_BUILD_FLAGS)
@cl /Zl $(WEBUI_BUILD_FLAGS) $(WARNING_RELEASE)
@lib $(LIB_STATIC_OUT)
# Dynamic Release
@echo Build WebUI Library (MSVC Release Dynamic)...
@cl $(CIVETWEB_BUILD_FLAGS) $(CIVETWEB_DEFINE_FLAGS)
@cl $(WEBUI_BUILD_FLAGS)
@cl $(WEBUI_BUILD_FLAGS) $(WARNING_RELEASE) /D WEBUI_DYNAMIC
@link $(LIB_DYN_OUT)
# Clean
@- del *.pdb >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.pdb >nul 2>&1
@- del *.exp >nul 2>&1
@- echo Done.
@ -77,7 +86,6 @@ clean:
@- del *.pdb >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.pdb >nul 2>&1
@- del *.exp >nul 2>&1
@- del *.dll >nul 2>&1
@- del *.lib >nul 2>&1

230
README.md
View File

@ -1,8 +1,8 @@
<div align="center">
![Logo](https://github.com/webui-dev/webui/assets/34311583/c92e712f-0698-486a-a460-d4acea28a4f8)
![Logo](https://raw.githubusercontent.com/webui-dev/webui-logo/14fd595844f57ce751dfc751297b1468b10de77a/webui_120.svg)
# WebUI v2.4.1
# WebUI v2.5.0-beta.4
[build-status]: https://img.shields.io/github/actions/workflow/status/webui-dev/webui/ci.yml?branch=main&style=for-the-badge&logo=githubactions&labelColor=414868&logoColor=C0CAF5
[last-commit]: https://img.shields.io/github/last-commit/webui-dev/webui?style=for-the-badge&logo=github&logoColor=C0CAF5&labelColor=414868
@ -14,9 +14,9 @@
[![][release-version]](https://github.com/webui-dev/webui/releases/latest)
[![][license]](https://github.com/webui-dev/webui/blob/main/LICENSE)
> WebUI is not a web-server solution or a framework, but it allows you to use any web browser as a GUI, with your preferred language in the backend and HTML5 in the frontend. All in a lightweight portable lib.
> Use any web browser or WebView as GUI, with your preferred language in the backend and modern web technologies in the frontend, all in a lightweight portable library.
![Screenshot](https://github.com/webui-dev/webui/assets/34311583/57992ef1-4f7f-4d60-8045-7b07df4088c6)
![Screenshot](https://raw.githubusercontent.com/webui-dev/webui-logo/main/screenshot.png)
</div>
@ -39,32 +39,18 @@
## Features
- Written in Pure C
- Fully Independent (_No need for any third-party runtimes_)
- Lightweight ~200 Kb & Small memory footprint
- Fast binary communication protocol between WebUI and the browser (_Instead of JSON_)
- Portable (*Needs only a web browser or a WebView at runtime*)
- One header file
- Lightweight (*Few Kb library*) & Small memory footprint
- Fast binary communication protocol
- Multi-platform & Multi-Browser
- Using private profile for safety
## Showcase
This [text editor](https://github.com/webui-dev/webui/tree/main/examples/C/text-editor) is a lightweight and portable example written in C using WebUI as the GUI library.
<div align="center">
![Example](https://github.com/webui-dev/webui/assets/34311583/c1ccf29c-806a-4742-bfd7-a3dc30cab70b)
</div>
- Cross-platform WebView
## UI & The Web Technologies
[Borislav Stanimirov](https://ibob.bg/) discusses using HTML5 in the web browser as GUI at the [C++ Conference 2019 (_YouTube_)](https://www.youtube.com/watch?v=bbbcZd4cuxg).
<!-- <div align="center">
<a href="https://www.youtube.com/watch?v=bbbcZd4cuxg"><img src="https://img.youtube.com/vi/bbbcZd4cuxg/0.jpg" alt="Embrace Modern Technology: Using HTML 5 for GUI in C++ - Borislav Stanimirov - CppCon 2019"></a>
</div> -->
<div align="center">
![CPPCon](https://github.com/webui-dev/webui/assets/34311583/4e830caa-4ca0-44ff-825f-7cd6d94083c8)
@ -89,7 +75,7 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
### Runtime Dependencies Comparison
| | WebView | Qt | WebUI |
| | Tauri / WebView | Qt | WebUI |
| ------------------------------- | ----------------- | -------------------------- | ------------------- |
| Runtime Dependencies on Windows | _WebView2_ | _QtCore, QtGui, QtWidgets_ | **_A Web Browser_** |
| Runtime Dependencies on Linux | _GTK3, WebKitGTK_ | _QtCore, QtGui, QtWidgets_ | **_A Web Browser_** |
@ -100,27 +86,24 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
> **Note**
> We are currently writing documentation.
- [Online Documentation - C](https://webui.me/docs/#/c_api)
- [Online Documentation - C++](https://webui.me/docs/#/cpp_api)
- [Online Documentation](https://webui.me/docs/)
## Build
## Build WebUI Library
- **Windows**
### Windows
```powershell
# GCC
mingw32-make
# MSVC
nmake
```
**Windows SSL/TLS (_Optional_)**
| Compiler | Command |
|----------|---------|
| GCC | `mingw32-make` |
| MSVC | `nmake` |
<details>
<summary><strong>Windows SSL/TLS (Optional)</strong></summary>
Download and install the OpenSSL pre-compiled binaries for Windows:
- MSVC: [x64 OpenSSL v3.1.3](https://slproweb.com/download/Win64OpenSSL-3_1_3.msi) or [_32Bit_](https://slproweb.com/download/Win32OpenSSL-3_1_3.msi). Please check this [Wiki list](https://wiki.openssl.org/index.php/Binaries) for more info.
- MinGW: [Curl for Windows win OpenSSL](https://curl.se/windows/)
- **MSVC**: [x64 OpenSSL v3.3.1](https://slproweb.com/download/Win64OpenSSL-3_3_1.msi) or [_32Bit_](https://slproweb.com/download/Win32OpenSSL-3_3_1.msi). See the [Wiki list](https://wiki.openssl.org/index.php/Binaries) for more info.
- **MinGW**: [Curl for Windows with OpenSSL](https://curl.se/windows/)
```powershell
# GCC
@ -129,19 +112,18 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
# MSVC
nmake WEBUI_USE_TLS=1 WEBUI_TLS_INCLUDE="C:\Program Files\OpenSSL-xxx\include" WEBUI_TLS_LIB="C:\Program Files\OpenSSL-xxx\lib"
```
</details>
- **Linux**
### Linux
```sh
# GCC
make
# Clang
make CC=clang
```
**Linux SSL/TLS (_Optional_)**
| Compiler | Command |
|----------|---------|
| GCC | `make` |
| Clang | `make CC=clang` |
<details>
<summary><strong>Linux SSL/TLS (Optional)</strong></summary>
```sh
sudo apt update
sudo apt install libssl-dev
@ -152,38 +134,142 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
# Clang
make WEBUI_USE_TLS=1 CC=clang
```
</details>
- **macOS**
### macOS
```sh
make
```
**macOS SSL/TLS (_Optional_)**
| Compiler | Command |
|----------|---------|
| Default | `make` |
<details>
<summary><strong>macOS SSL/TLS (Optional)</strong></summary>
```sh
brew install openssl
make WEBUI_USE_TLS=1
```
</details>
## Examples
## Minimal WebUI Application
- [C](https://github.com/webui-dev/webui/tree/main/examples/C)
- [C++](https://github.com/webui-dev/webui/tree/main/examples/C++)
- **C**
```c
#include "webui.h"
int main() {
size_t my_window = webui_new_window();
webui_show(my_window, "<html><head><script src=\"webui.js\"></script></head> Hello World ! </html>");
webui_wait();
return 0;
}
```
- **C++**
```cpp
#include "webui.hpp"
#include <iostream>
int main() {
webui::window my_window;
my_window.show("<html><head><script src=\"webui.js\"></script></head> C++ Hello World ! </html>");
webui::wait();
return 0;
}
```
- **More C/C++ Examples**
- [C](https://github.com/webui-dev/webui/tree/main/examples/C)
- [C++](https://github.com/webui-dev/webui/tree/main/examples/C++)
- **Other Languages**
- [Wrappers List](#Wrappers)
## Build WebUI Application
### Windows
| Compiler | Type | Command |
|----------|--------|---------|
| GCC | Static | `gcc -Os -Wl,-subsystem=windows my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-static -lws2_32 -Wall -luser32 -static -lole32 -o my_application.exe` |
| GCC | Dynamic | `gcc -Wl,-subsystem=windows my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" "webui-2.dll" -lws2_32 -Wall -luser32 -lole32 -o my_application.exe` |
| MSVC | Static | `cl my_application.c /I"_PATH_TO_WEBUI_INCLUDE_" /link /LIBPATH:"_PATH_TO_WEBUI_LIB_" /SUBSYSTEM:WINDOWS webui-2-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:my_application.exe` |
| MSVC | Dynamic | `cl my_application.c /I"_PATH_TO_WEBUI_INCLUDE_" /link /LIBPATH:"_PATH_TO_WEBUI_LIB_" /SUBSYSTEM:WINDOWS webui-2.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:my_application.exe` |
<details>
<summary><strong>Windows With SSL/TLS (Optional)</strong></summary>
| Compiler | Type | Command |
|----------|--------|---------|
| GCC | Static | `gcc -Os -Wl,-subsystem=windows my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-secure-static -lws2_32 -Wall -luser32 -static -lole32 -o my_application.exe` |
| GCC | Dynamic | `gcc -Wl,-subsystem=windows my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" "webui-2-secure.dll" -lws2_32 -Wall -luser32 -lole32 -o my_application.exe` |
| MSVC | Static | `cl my_application.c /I"_PATH_TO_WEBUI_INCLUDE_" /link /LIBPATH:"_PATH_TO_WEBUI_LIB_" /SUBSYSTEM:WINDOWS webui-2-secure-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:my_application.exe` |
| MSVC | Dynamic | `cl my_application.c /I"_PATH_TO_WEBUI_INCLUDE_" /link /LIBPATH:"_PATH_TO_WEBUI_LIB_" /SUBSYSTEM:WINDOWS webui-2-secure.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:my_application.exe` |
</details>
### Linux
| Compiler | Type | Command |
|----------|--------|---------|
| GCC | Static | `gcc -Os my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-static -lpthread -lm -ldl -o my_application` |
| GCC | Dynamic | `gcc my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2 -lpthread -lm -ldl -o my_application` |
| Clang | Static | `clang -Os my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-static -lpthread -lm -ldl -o my_application` |
| Clang | Dynamic | `clang my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2 -lpthread -lm -ldl -o my_application` |
<details>
<summary><strong>Linux With SSL/TLS (Optional)</strong></summary>
| Compiler | Type | Command |
|----------|--------|---------|
| GCC | Static | `gcc -Os my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-secure-static -lpthread -lm -ldl -o my_application` |
| GCC | Dynamic | `gcc my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-secure -lpthread -lm -ldl -o my_application` |
| Clang | Static | `clang -Os my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-secure-static -lpthread -lm -ldl -o my_application` |
| Clang | Dynamic | `clang my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-secure -lpthread -lm -ldl -o my_application` |
</details>
### macOS
| Compiler | Type | Command |
|----------|--------|---------|
| Clang | Static | `clang -Os my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-static -lpthread -lm -framework Cocoa -framework WebKit -o my_application` |
| Clang | Dynamic | `clang my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2 -lpthread -lm -framework Cocoa -framework WebKit -o my_application` |
<details>
<summary><strong>macOS With SSL/TLS (Optional)</strong></summary>
| Compiler | Type | Command |
|----------|--------|---------|
| Clang | Static | `clang -Os my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-secure-static -lpthread -lm -framework Cocoa -framework WebKit -o my_application` |
| Clang | Dynamic | `clang my_application.c -I"_PATH_TO_WEBUI_INCLUDE_" -L"_PATH_TO_WEBUI_LIB_" -lwebui-2-secure -lpthread -lm -framework Cocoa -framework WebKit -o my_application` |
</details>
## Wrappers
| Language | Status | Link |
| ----------------------- | -------------- | --------------------------------------------------------- |
| Go | ✔️ | [Go-WebUI](https://github.com/webui-dev/go-webui) |
| Nim | ✔️ | [Nim-WebUI](https://github.com/webui-dev/nim-webui) |
| Pascal | ✔️ | [Pascal-WebUI](https://github.com/webui-dev/pascal-webui) |
| Python | ✔️ | [Python-WebUI](https://github.com/webui-dev/python-webui) |
| Rust | _not complete_ | [Rust-WebUI](https://github.com/webui-dev/rust-webui) |
| TypeScript / JavaScript | ✔️ | [Deno-WebUI](https://github.com/webui-dev/deno-webui) |
| V | ✔️ | [V-WebUI](https://github.com/webui-dev/v-webui) |
| Zig | _not complete_ | [Zig-WebUI](https://github.com/webui-dev/zig-webui) |
| Odin | _not complete_ | [Odin-WebUI](https://github.com/webui-dev/odin-webui) |
| Language | v2.4.0 API | v2.5.0 API | Link |
| --------------- | --- | -------------- | --------------------------------------------------------- |
| Python | ✔️ | _not complete_ | [Python-WebUI](https://github.com/webui-dev/python-webui) |
| Go | ✔️ | _not complete_ | [Go-WebUI](https://github.com/webui-dev/go-webui) |
| Zig | ✔️ | _not complete_ | [Zig-WebUI](https://github.com/webui-dev/zig-webui) |
| Nim | ✔️ | _not complete_ | [Nim-WebUI](https://github.com/webui-dev/nim-webui) |
| V | ✔️ | _not complete_ | [V-WebUI](https://github.com/webui-dev/v-webui) |
| Rust | _not complete_ | _not complete_ | [Rust-WebUI](https://github.com/webui-dev/rust-webui) |
| TS / JS (Deno) | ✔️ | _not complete_ | [Deno-WebUI](https://github.com/webui-dev/deno-webui) |
| TS / JS (Bun) | _not complete_ | _not complete_ | [Bun-WebUI](https://github.com/webui-dev/bun-webui) |
| Swift | _not complete_ | _not complete_ | [Swift-WebUI](https://github.com/webui-dev/swift-webui) |
| Odin | _not complete_ | _not complete_ | [Odin-WebUI](https://github.com/webui-dev/odin-webui) |
| Pascal | _not complete_ | _not complete_ | [Pascal-WebUI](https://github.com/webui-dev/pascal-webui) |
| Purebasic | _not complete_ | _not complete_ | [Purebasic-WebUI](https://github.com/webui-dev/purebasic-webui)|
| - | | |
| Common Lisp | _not complete_ | _not complete_ | [cl-webui](https://github.com/garlic0x1/cl-webui) |
| Delphi | _not complete_ | _not complete_ | [WebUI4Delphi](https://github.com/salvadordf/WebUI4Delphi) |
| C# | _not complete_ | _not complete_ | [WebUI4CSharp](https://github.com/salvadordf/WebUI4CSharp) |
| WebUI.NET | _not complete_ | _not complete_ | [WebUI.NET](https://github.com/Juff-Ma/WebUI.NET) |
| QuickJS | _not complete_ | _not complete_ | [QuickUI](https://github.com/xland/QuickUI) |
| PHP | _not complete_ | _not complete_ | [PHPWebUiComposer](https://github.com/KingBes/php-webui-composer) |
## Supported Web Browsers
@ -200,6 +286,14 @@ Think of WebUI like a WebView controller, but instead of embedding the WebView c
| Apple Safari | _not available_ | _coming soon_ | _not available_ |
| Opera | _coming soon_ | _coming soon_ | _coming soon_ |
## Supported WebView
| WebView | Status |
| --------------- | --------------- |
| Windows WebView2 | ✔️ |
| Linux GTK WebView | ✔️ |
| macOS WKWebView | ✔️ |
### License
> Licensed under MIT License.

View File

@ -1,6 +1,6 @@
# WebUI Bridge
The WebUI Bridge connects the UI (_Web Browser_) with the backend application through WebSocket. This bridge is written in TypeScript, and it needs to be transpiled to JavaScript using [ESBuild](https://esbuild.github.io/) to produce `webui_bridge.js`, then converted to C header using the Python script `js2c.py` to generate `webui_bridge.h`.
The WebUI Bridge connects the UI (_Web Browser_) with the backend application through WebSocket. This bridge is written in TypeScript, and it needs to be transpiled to JavaScript using [ESBuild](https://esbuild.github.io/) to produce `webui.js`, then converted to C header using the Python script `js2c.py` to generate `webui_bridge.h`.
### Windows
@ -8,7 +8,7 @@ The WebUI Bridge connects the UI (_Web Browser_) with the backend application th
- Install [Node.js](https://nodejs.org/en/download)
- cd `webui\bridge`
- `npm install esbuild`
- `.\node_modules\.bin\esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=.\ .\webui_bridge.ts`
- `.\node_modules\.bin\esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=.\ .\webui.ts`
- `python js2c.py`
### Windows PowerShell
@ -24,7 +24,7 @@ The WebUI Bridge connects the UI (_Web Browser_) with the backend application th
- Install [Node.js](https://nodejs.org/en/download)
- cd `webui/bridge`
- `npm install esbuild`
- `./node_modules/.bin/esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=./ ./webui_bridge.ts`
- `./node_modules/.bin/esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=./ ./webui.ts`
- `python js2c.py`
### Linux Bash
@ -38,7 +38,7 @@ The WebUI Bridge connects the UI (_Web Browser_) with the backend application th
- Install [Node.js](https://nodejs.org/en/download)
- cd `webui/bridge`
- `npm install esbuild`
- `./node_modules/.bin/esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=./ ./webui_bridge.ts`
- `./node_modules/.bin/esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=./ ./webui.ts`
- `python js2c.py`
### macOS Bash

View File

@ -27,7 +27,7 @@ IF NOT EXIST "%project_root%\bridge\node_modules\esbuild\" (
where npm > NUL 2>&1
IF %errorlevel%==0 (
echo Installing esbuild...
npm install esbuild
npm install --prefix ./ esbuild
) ELSE (
echo Error: Please install NPM.
cd %cd%
@ -37,7 +37,7 @@ IF NOT EXIST "%project_root%\bridge\node_modules\esbuild\" (
REM Transpile WebUI-Bridge (TS to JS) & Convert WebUI-Bridge (JS to C)
echo Transpile and bundle WebUI-Bridge from TypeScript to JavaScript...
.\node_modules\.bin\esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=. ./webui_bridge.ts & %python_cmd% js2c.py
.\node_modules\.bin\esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --minify-syntax --minify-whitespace --outdir=. ./webui.ts & %python_cmd% js2c.py
echo Done.
cd %cd%

View File

@ -1,14 +1,20 @@
# http://webui.me
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2023 Hassan Draga.
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# Special Thanks to Turiiya (https://github.com/ttytm)
Set-StrictMode -version latest
$ErrorActionPreference="Stop"
$current_location = Get-Location
$project_root = git rev-parse --show-toplevel
Set-Location $project_root/bridge
$silent=$false
$log_level=$null
# Arguments
foreach ($opt in $args) {
@ -22,6 +28,7 @@ foreach ($opt in $args) {
}
if ($silent) { $log_level = "--log-level=warning" }
$ErrorActionPreference="SilentlyContinue"
# Check which python command is available
$commandResult = python3 --version 2>&1 > $null
if (!$?) {
@ -37,12 +44,13 @@ if (!$?) {
} else {
$python_cmd = "python3"
}
$ErrorActionPreference="Stop"
# Check if node_modules\esbuild exists, if not, install using npm
if (-not (Test-Path "$project_root\bridge\node_modules\esbuild")) {
if (Get-Command npm -ErrorAction SilentlyContinue) {
if (!$silent) { Write-Host "Installing esbuild..." }
npm install esbuild
npm install --prefix ./ esbuild
} else {
Write-Host "Error: Please install NPM."
Set-Location $current_location
@ -52,7 +60,7 @@ if (-not (Test-Path "$project_root\bridge\node_modules\esbuild")) {
# Transpile WebUI-Bridge (TS to JS)
if (!$silent) { Write-Host "Transpile and bundle WebUI-Bridge from TypeScript to JavaScript..." }
.\node_modules\.bin\esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=. ./webui_bridge.ts $log_level
.\node_modules\.bin\esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --minify-syntax --minify-whitespace --outdir=. ./webui.ts $log_level
# Convert WebUI-Bridge (JS to C)
if (!$silent) { Write-Host "Convert WebUI-Bridge JavaScript to C Header..." }

View File

@ -1,10 +1,11 @@
#!/bin/bash
# http://webui.me
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2023 Hassan Draga.
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# Special Thanks to Turiiya (https://github.com/ttytm)
@ -28,7 +29,7 @@ done
if [ "$silent" = true ]; then log_level=--log-level=warning; fi
if [ "$silent" != true ]; then echo "Transpile and bundle TS sources to webui.js"; fi
esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --outdir=. ./webui_bridge.ts $log_level
esbuild --bundle --target="chrome90,firefox90,safari15" --format=esm --tree-shaking=false --minify-syntax --minify-whitespace --outdir=. ./webui.ts $log_level
if [ "$silent" != true ]; then echo "Convert JS source to C header"; fi
python3 js2c.py

View File

@ -1,24 +1,44 @@
# http://webui.me
# https://webui.me
# https://github.com/webui-dev/webui
# Copyright (c) 2020-2023 Hassan Draga.
# Copyright (c) 2020-2025 Hassan Draga.
# Licensed under MIT License.
# All rights reserved.
# Canada.
#
# WebUI JavaScript to C Header
def js_to_c_header(input_filename, output_filename):
try:
# Read JS file content
with open(input_filename, 'r', encoding='utf-8') as f:
content = f.read()
print(f"Converting '{input_filename}' to '{output_filename}'...")
# comment
comment = (
"// WebUI v2.5.0-beta.4\n"
"// https://webui.me\n"
"// https://github.com/webui-dev/webui\n"
"// Copyright (c) 2020-2025 Hassan Draga.\n"
"// Licensed under MIT License.\n"
"// All rights reserved.\n"
"// Canada.\n\n"
)
# Read JS file content
with open(input_filename, 'r', encoding='utf-8') as file_js:
content = file_js.read()
file_js.close()
# Add comment to js
new_content = comment + content
with open(input_filename, 'w') as file_js:
file_js.write(new_content)
file_js.close()
# Convert each character in JS content to its hexadecimal value
hex_values = ["0x{:02x}".format(ord(char)) for char in content]
hex_values = ["0x{:02x}".format(ord(char)) for char in new_content]
# Prepare the content for the C header file
header_content = (
comment +
"// --- PLEASE DO NOT EDIT THIS FILE -------\n"
"// --- THIS FILE IS GENERATED BY JS2C.PY --\n\n"
"#ifndef WEBUI_BRIDGE_H\n"
@ -29,16 +49,16 @@ def js_to_c_header(input_filename, output_filename):
# Split the hexadecimal values to make the output more readable, adding a new line every 10 values
for i in range(0, len(hex_values), 10):
header_content += "\n " + ', '.join(hex_values[i:i+10]) + ','
header_content += "\n 0x00\n};\n\n#endif // WEBUI_BRIDGE_H"
# Write the header content to the output file
with open(output_filename, 'w', encoding='utf-8') as f:
f.write(header_content)
with open(output_filename, 'w', encoding='utf-8') as file_h:
file_h.write(header_content)
file_h.close()
except FileNotFoundError:
print(f"Error: File '{input_filename}' not found.")
return
# Main
js_to_c_header('webui_bridge.js', 'webui_bridge.h')
js_to_c_header('webui.js', 'webui_bridge.h')

View File

@ -1,9 +1,13 @@
/*
WebUI Bridge Utils
Copyright (c) 2023 Oculi Julien.
https://webui.me
https://github.com/webui-dev/webui
Copyright (c) 2020-2025 Hassan Draga.
Licensed under MIT License.
All rights reserved.
Canada.
File: WebUI Bridge Utils
Copyright (c) 2024 Oculi Julien.
*/
/**

974
bridge/webui.ts Normal file
View File

@ -0,0 +1,974 @@
'use-strict'; // Force strict mode for transpiled
/*
WebUI Bridge
https://webui.me
https://github.com/webui-dev/webui
Copyright (c) 2020-2025 Hassan Draga.
Licensed under MIT License.
All rights reserved.
Canada.
Converted from JavaScript to TypeScript
By Oculi Julien. Copyright (c) 2023.
*/
//@ts-ignore use *.ts import real extension
import { AsyncFunction, addRefreshableEventListener } from './utils.ts';
type DataTypes = string | number | boolean | Uint8Array;
class WebuiBridge {
// WebUI Settings
#secure: boolean;
#token: number;
#port: number;
#log: boolean;
#winX: number;
#winY: number;
#winW: number;
#winH: number;
// Frameless Dragging
#isDragging: boolean = false;
#initialMouseX: number = 0;
#initialMouseY: number = 0;
#initialWindowX: number = window.screenX || window.screenLeft;
#initialWindowY: number = window.screenY || window.screenTop;
#currentWindowX: number = window.screenX || window.screenLeft;
#currentWindowY: number = window.screenY || window.screenTop;
// Internals
#ws: WebSocket;
#wsStayAlive: boolean = true;
#wsStayAliveTimeout: number = 500;
#wsWasConnected: boolean = false;
#TokenAccepted: boolean = false;
#closeReason: number = 0;
#closeValue: string;
#AllEvents: boolean = false;
#callPromiseID: Uint16Array = new Uint16Array(1);
#callPromiseResolve: (((data: string) => unknown) | undefined)[] = [];
#allowNavigation: boolean = true;
#sendQueue: Uint8Array[] = [];
#isSending: boolean = false;
#bindsList: string[];
// WebUI Const
#WEBUI_SIGNATURE: number = 221;
#CMD_JS: number = 254;
#CMD_JS_QUICK: number = 253;
#CMD_CLICK: number = 252;
#CMD_NAVIGATION: number = 251;
#CMD_CLOSE: number = 250;
#CMD_CALL_FUNC: number = 249;
#CMD_SEND_RAW: number = 248;
#CMD_NEW_ID: number = 247;
#CMD_MULTI: number = 246;
#CMD_CHECK_TK: number = 245;
#CMD_WINDOW_DRAG: number = 244;
#CMD_WINDOW_RESIZED: number = 243;
#MULTI_CHUNK_SIZE: number = 65500;
#PROTOCOL_SIZE: number = 8; // Protocol header size in bytes
#PROTOCOL_SIGN: number = 0; // Protocol byte position: Signature (1 Byte)
#PROTOCOL_TOKEN: number = 1; // Protocol byte position: Token (4 Bytes)
#PROTOCOL_ID: number = 5; // Protocol byte position: ID (2 Bytes)
#PROTOCOL_CMD: number = 7; // Protocol byte position: Command (1 Byte)
#PROTOCOL_DATA: number = 8; // Protocol byte position: Data (n Byte)
#Token: Uint32Array = new Uint32Array(1);
#Ping: Boolean = true;
// Events
#eventsCallback: ((event: number) => void) | null = null;
event = {
// TODO: Make `event` static and solve the ESBUILD `_WebuiBridge` issue.
CONNECTED: 0,
DISCONNECTED: 1,
};
// Constructor
constructor({
secure = false,
token = 0,
port = 0,
log = false,
winX = 0,
winY = 0,
winW = 0,
winH = 0,
}: {
secure: boolean;
token: number;
port: number;
log?: boolean;
winX: number;
winY: number;
winW: number;
winH: number;
}) {
// Constructor arguments are injected by webui.c
this.#secure = secure;
this.#token = token;
this.#port = port;
this.#log = log;
this.#winX = winX;
this.#winY = winY;
this.#winW = winW;
this.#winH = winH;
// Token
this.#Token[0] = this.#token;
// Instance
if ('webui' in globalThis) {
throw new Error('Sorry. WebUI is already defined, only one instance is allowed.');
}
// Positioning the current window
if (this.#winX !== undefined && this.#winY !== undefined) {
// window.moveTo(this.#winX, this.#winY);
}
// Resize the current window
if (this.#winW !== undefined && this.#winH !== undefined) {
// window.resizeTo(this.#winW, this.#winH);
}
// WebSocket
if (!('WebSocket' in window)) {
alert('Sorry. WebSocket is not supported by your web browser.');
if (!this.#log) globalThis.close();
}
// Connect to the backend application
this.#start();
// Navigation event listener
if ('navigation' in globalThis) {
globalThis.navigation.addEventListener('navigate', (event) => {
if (!this.#allowNavigation) {
if (this.#AllEvents && (this.#wsIsConnected())) {
event.preventDefault();
const url = new URL(event.destination.url);
if (this.#log) console.log(`WebUI -> DOM -> Navigation Event [${url.href}]`);
this.#sendEventNavigation(url.href);
}
}
});
} else {
// Click navigation event listener
addRefreshableEventListener(document.body, 'a', 'click', (event) => {
if (!this.#allowNavigation) {
if (this.#AllEvents && (this.#wsIsConnected())) {
event.preventDefault();
const { href } = event.target as HTMLAnchorElement;
if (this.#log) console.log(`WebUI -> DOM -> Navigation Click Event [${href}]`);
this.#sendEventNavigation(href);
}
}
});
}
// Prevent F5 refresh
document.addEventListener('keydown', (event) => {
if (this.#log) return; // Allowed in debug mode
if (event.key === 'F5') event.preventDefault();
});
// Frameless Dragging
document.addEventListener("mousemove", (e) => {
// WebUI `-webkit-app-region: drag;` custom implementation
if (e.buttons !== 1) {
this.#isDragging = false;
return;
}
if (!this.#isDragging) {
let target = e.target;
while (target) {
if (window.getComputedStyle(target).getPropertyValue("-webkit-app-region") === "drag") {
this.#initialMouseX = e.screenX;
this.#initialMouseY = e.screenY;
this.#initialWindowX = this.#currentWindowX;
this.#initialWindowY = this.#currentWindowY;
this.#isDragging = true;
break;
}
target = target.parentElement;
}
return;
}
// Calculate window position relative to cursor movement
const deltaX = e.screenX - this.#initialMouseX;
const deltaY = e.screenY - this.#initialMouseY;
let newX = this.#initialWindowX + deltaX;
let newY = this.#initialWindowY + deltaY;
// Fix out of screen
if (newX < 0) newX = 0;
if (newY < 0) newY = 0;
// Move the window
this.#sendDrag(newX, newY);
// Update the last window position
this.#currentWindowX = newX;
this.#currentWindowY = newY;
});
// Stop frameless dragging on mouse release
document.addEventListener("mouseup", () => {
this.#isDragging = false;
});
onbeforeunload = () => {
this.#close();
};
setTimeout(() => {
if (!this.#wsWasConnected) {
alert('Sorry. WebUI failed to connect to the backend application. Please try again.');
}
}, 1500);
}
// Methods
#close(reason = 0, value = '') {
this.#closeReason = reason;
this.#closeValue = value;
if (this.#wsIsConnected()) {
this.#ws.close();
}
}
#freezeUi() {
setTimeout(() => {
if (!this.#wsIsConnected()) {
if (document.getElementById('webui-error-connection-lost')) return;
const div = document.createElement('div');
div.id = 'webui-error-connection-lost';
Object.assign(div.style, {
position: 'relative',
top: '0',
left: '0',
width: '100%',
backgroundColor: '#ff4d4d',
color: '#fff',
textAlign: 'center',
padding: '2px 0',
fontFamily: 'Arial, sans-serif',
fontSize: '14px',
zIndex: '1000',
lineHeight: '1'
});
div.innerText = 'WebUI Error: Connection with the backend is lost.';
document.body.insertBefore(div, document.body.firstChild);
}
}, 1000);
}
#unfreezeUI() {
const div = document.getElementById('webui-error-connection-lost');
if (div) {
div.remove();
}
}
#isTextBasedCommand(cmd: number): Boolean {
if (cmd !== this.#CMD_SEND_RAW) return true;
return false;
}
#parseDimensions(input: string): {x: number; y: number; width: number; height: number} {
try {
const parts = input.split(',');
if (parts.length !== 4) return {x: 0, y: 0, width: 0, height: 0};
const x = parseFloat(parts[0]),
y = parseFloat(parts[1]),
width = parseFloat(parts[2]),
height = parseFloat(parts[3]);
return [x, y, width, height].some(isNaN) ? {x: 0, y: 0, width: 0, height: 0} : {x, y, width, height};
} catch {
return {x: 0, y: 0, width: 0, height: 0};
}
}
#getDataStrFromPacket(buffer: Uint8Array, startIndex: number): string {
let stringBytes: number[] = [];
for (let i = startIndex; i < buffer.length; i++) {
if (buffer[i] === 0) {
// Check for null byte
break;
}
stringBytes.push(buffer[i]);
}
// Convert the array of bytes to a string
const stringText = new TextDecoder().decode(new Uint8Array(stringBytes));
return stringText;
}
#getID(buffer: Uint8Array, index: number): number {
if (index < 0 || index >= buffer.length - 1) {
throw new Error('Index out of bounds or insufficient data.');
}
const firstByte = buffer[index];
const secondByte = buffer[index + 1];
const combined = (secondByte << 8) | firstByte; // Works only for little-endian
return combined;
}
#addToken(buffer: Uint8Array, value: number, index: number): void {
if (value < 0 || value > 0xffffffff) {
throw new Error('Number is out of the range for 4 bytes representation.');
}
if (index < 0 || index > buffer.length - 4) {
throw new Error('Index out of bounds or insufficient space in buffer.');
}
// WebUI expect Little-endian (Work for Little/Big endian platforms)
buffer[index] = value & 0xff; // Least significant byte
buffer[index + 1] = (value >>> 8) & 0xff;
buffer[index + 2] = (value >>> 16) & 0xff;
buffer[index + 3] = (value >>> 24) & 0xff; // Most significant byte
}
#addID(buffer: Uint8Array, value: number, index: number): void {
if (value < 0 || value > 0xffff) {
throw new Error('Number is out of the range for 2 bytes representation.');
}
if (index < 0 || index > buffer.length - 2) {
throw new Error('Index out of bounds or insufficient space in buffer.');
}
// WebUI expect Little-endian (Work for Little/Big endian platforms)
buffer[index] = value & 0xff; // Least significant byte
buffer[index + 1] = (value >>> 8) & 0xff; // Most significant byte
}
#start() {
this.#keepAlive();
this.#callPromiseID[0] = 0;
// Connect to the backend application
this.#wsConnect();
}
#keepAlive = async () => {
while (true) {
if (this.#Ping) {
// Some web browsers may close the connection
// let's send a void message to keep WS open
this.#sendData(new TextEncoder().encode('ping'));
} else {
// There is an active communication
this.#Ping = true;
}
await new Promise((resolve) => setTimeout(resolve, 20000));
}
};
#clicksListener() {
document.querySelectorAll<HTMLElement>("[id]").forEach(e => {
if (this.#AllEvents || ((e.id !== '') && (this.#bindsList.includes(e.id)))) {
if (e.id && !e.dataset.webui_click_is_set) {
e.dataset.webui_click_is_set = "true";
e.addEventListener("click", () => this.#sendClick(e.id));
}
}
});
}
async #sendData(packet: Uint8Array) {
this.#Ping = false;
if ((!this.#wsIsConnected()) || packet === undefined) return;
// Enqueue the packet
this.#sendQueue.push(packet);
if (this.#isSending) return;
this.#isSending = true;
while (this.#sendQueue.length > 0) {
const currentPacket = this.#sendQueue.shift()!;
if (currentPacket.length < this.#MULTI_CHUNK_SIZE) {
this.#ws.send(currentPacket.buffer);
} else {
// Pre-packet to let WebUI be ready for multi packet
const pre_packet = Uint8Array.of(
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_MULTI,
...new TextEncoder().encode(currentPacket.length.toString()),
0,
);
this.#ws.send(pre_packet.buffer);
// Send chunks
let offset = 0;
const sendChunk = async () => {
if (offset < currentPacket.length) {
const chunkSize = Math.min(this.#MULTI_CHUNK_SIZE, currentPacket.length - offset);
const chunk = currentPacket.subarray(offset, offset + chunkSize);
this.#ws.send(chunk);
offset += chunkSize;
await sendChunk();
}
};
await sendChunk();
}
}
this.#isSending = false;
}
#sendClick(elem: string) {
if (this.#wsIsConnected()) {
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Element]
const packet =
elem !== ''
? Uint8Array.of(
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_CLICK,
...new TextEncoder().encode(elem),
0,
)
: Uint8Array.of(
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_CLICK,
0,
);
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
// this.#addID(packet, 0, this.#PROTOCOL_ID)
this.#sendData(packet);
if (this.#log) console.log(`WebUI -> Send Click [${elem}]`);
}
}
#checkToken() {
if (this.#wsIsConnected()) {
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
const packet =
Uint8Array.of(
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_CHECK_TK,
0,
);
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
// this.#addID(packet, 0, this.#PROTOCOL_ID)
this.#sendData(packet);
if (this.#log) console.log(`WebUI -> Send Token [0x${this.#token.toString(16).padStart(8, '0')}]`);
}
}
#sendEventNavigation(url: string) {
if (url !== '') {
if (this.#wsIsConnected()) {
if (this.#log) console.log(`WebUI -> Send Navigation Event [${url}]`);
const packet = Uint8Array.of(
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [URL]
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_NAVIGATION,
...new TextEncoder().encode(url),
);
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
// this.#addID(packet, 0, this.#PROTOCOL_ID)
this.#sendData(packet);
}
}
}
#sendDrag(x: number, y: number) {
if (this.#wsIsConnected()) {
if (this.#log) console.log(`WebUI -> Send Drag Event [${x}, ${y}]`);
const packet = Uint8Array.of(
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [X]
// 4: [Y]
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_WINDOW_DRAG,
...new Uint8Array(new Int32Array([x]).buffer), // X (4 Bytes)
...new Uint8Array(new Int32Array([y]).buffer), // Y (4 Bytes)
);
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
// this.#addID(packet, 0, this.#PROTOCOL_ID)
this.#sendData(packet);
}
}
#closeWindowTimer() {
setTimeout(function () {
globalThis.close();
}, 1000);
}
#updateBindsList() {
if (this.#bindsList.includes('')) {
this.#AllEvents = true;
this.#allowNavigation = false;
}
this.#generateCallObjects();
this.#clicksListener();
}
#toUint16(value: number): number {
return value & 0xffff;
}
#generateCallObjects() {
for (const bind of this.#bindsList) {
if (bind.trim()) {
const fn = bind;
if (fn.trim()) {
if (fn !== '__webui_core_api__') {
if (typeof (window as any)[fn] === 'undefined') {
this[fn] = (...args: DataTypes[]) => this.call(fn, ...args);
(window as any)[fn] = (...args: string[]) => this.call(fn, ...args);
if (this.#log) console.log(`WebUI -> Binding backend function [${fn}]`);
}
}
}
}
}
}
#callPromise(fn: string, ...args: DataTypes[]) {
--this.#callPromiseID[0];
const callId = this.#toUint16(this.#callPromiseID[0]);
// Combine lengths
let argsLengths = args
.map((arg) => {
if (typeof arg === 'object') {
// Uint8Array
return arg.length;
} else {
// string, number, boolean
return new TextEncoder().encode(arg.toString()).length;
}
})
.join(';');
// Combine values
let argsValues: Uint8Array = new Uint8Array();
for (const arg of args) {
let buffer: Uint8Array;
if (typeof arg === 'object') {
buffer = arg; // Uint8Array
} else {
// string, number, boolean
buffer = new TextEncoder().encode(arg.toString());
}
const temp = new Uint8Array(argsValues.length + buffer.length + 1);
temp.set(argsValues, 0);
temp.set(buffer, argsValues.length);
temp[argsValues.length + buffer.length] = 0x00;
argsValues = temp;
}
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Fn, Null, {LenLen...}, Null, {Data,Null,Data,Null...}]
let packet = new Uint8Array(0);
const packetPush = (data: Uint8Array) => {
const newPacket = new Uint8Array(packet.length + data.length);
newPacket.set(packet);
newPacket.set(data, packet.length);
packet = newPacket;
};
packetPush(new Uint8Array([this.#WEBUI_SIGNATURE]));
packetPush(new Uint8Array([0, 0, 0, 0])); // Token (4 Bytes)
packetPush(new Uint8Array([0, 0])); // ID (2 Bytes)
packetPush(new Uint8Array([this.#CMD_CALL_FUNC]));
packetPush(new TextEncoder().encode(fn));
packetPush(new Uint8Array([0]));
packetPush(new TextEncoder().encode(argsLengths));
packetPush(new Uint8Array([0]));
packetPush(new Uint8Array(argsValues));
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
this.#addID(packet, callId, this.#PROTOCOL_ID);
return new Promise((resolve) => {
this.#callPromiseResolve[callId] = resolve;
this.#sendData(packet);
});
}
async callCore(fn: string, ...args: DataTypes[]): Promise<DataTypes> {
return this.call('__webui_core_api__', fn, ...args);
}
// -- WebSocket ----------------------------
#wsIsConnected(): boolean {
return ((this.#ws) && (this.#ws.readyState === WebSocket.OPEN));
}
#wsConnect(): void {
if (this.#wsIsConnected()) {
this.#ws.close();
}
this.#TokenAccepted = false;
const host = window.location.hostname;
const url = this.#secure ? ('wss://' + host) : ('ws://' + host);
this.#ws = new WebSocket(`${url}:${this.#port}/_webui_ws_connect`);
this.#ws.binaryType = 'arraybuffer';
this.#ws.onopen = this.#wsOnOpen.bind(this);
this.#ws.onmessage = this.#wsOnMessage.bind(this);
this.#ws.onclose = this.#wsOnClose.bind(this);
this.#ws.onerror = this.#wsOnError.bind(this);
}
#wsOnOpen = (event: Event) => {
this.#wsWasConnected = true;
this.#unfreezeUI();
if (this.#log) console.log('WebUI -> Connected');
this.#checkToken();
};
#wsOnError = (event: Event) => {
if (this.#log) console.log(`WebUI -> Connection failed.`);
};
#wsOnClose = (event: CloseEvent) => {
if (this.#closeReason === this.#CMD_NAVIGATION) {
this.#closeReason = 0;
if (this.#log) console.log(`WebUI -> Connection lost. Navigation to [${this.#closeValue}]`);
this.#allowNavigation = true;
globalThis.location.replace(this.#closeValue);
} else {
if (this.#wsStayAlive) {
// Re-connect
if (this.#log) console.log(`WebUI -> Connection lost (${event.code}). Reconnecting...`);
this.#freezeUi();
setTimeout(() => this.#wsConnect(), this.#wsStayAliveTimeout);
}
else if (this.#log) {
// Debug close
console.log(`WebUI -> Connection lost (${event.code})`);
this.#freezeUi();
} else {
// Release close
this.#closeWindowTimer();
}
}
// Event Callback
if (this.#eventsCallback) {
this.#eventsCallback(this.event.DISCONNECTED);
}
};
#wsOnMessage = async (event: MessageEvent) => {
const buffer8 = new Uint8Array(event.data);
if (buffer8.length < this.#PROTOCOL_SIZE) return;
if (buffer8[this.#PROTOCOL_SIGN] !== this.#WEBUI_SIGNATURE) return;
if (this.#isTextBasedCommand(buffer8[this.#PROTOCOL_CMD])) {
// UTF8 Text based commands
const callId = this.#getID(buffer8, this.#PROTOCOL_ID);
// Process Command
switch (buffer8[this.#PROTOCOL_CMD]) {
case this.#CMD_JS_QUICK:
case this.#CMD_JS:
{
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Script]
const script: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
const scriptSanitize = script.replace(/(?:\r\n|\r|\n)/g, '\n');
if (this.#log) console.log(`WebUI -> CMD -> JS [${scriptSanitize}]`);
// Get callback result
let FunReturn = 'undefined';
let FunError = false;
try {
FunReturn = await AsyncFunction(scriptSanitize)();
} catch (e) {
FunError = true;
FunReturn = e.message;
}
// Stop if this is a quick call
if (buffer8[this.#PROTOCOL_CMD] === this.#CMD_JS_QUICK) return;
// Get the call return
if (FunReturn === undefined) {
FunReturn = 'undefined';
}
// Logging
if (this.#log && !FunError) console.log(`WebUI -> CMD -> JS -> Return Success [${FunReturn}]`);
if (this.#log && FunError) console.log(`WebUI -> CMD -> JS -> Return Error [${FunReturn}]`);
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Error, Script Response]
let packet = new Uint8Array(0);
const packetPush = (data: Uint8Array) => {
const newPacket = new Uint8Array(packet.length + data.length);
newPacket.set(packet);
newPacket.set(data, packet.length);
packet = newPacket;
};
const packetPushStr = (data: string) => {
const chunkSize = 1024 * 8;
if (data.length > chunkSize) {
const encoder = new TextEncoder();
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.substring(i, Math.min(i + chunkSize, data.length));
const encodedChunk = encoder.encode(chunk);
packetPush(encodedChunk);
}
} else {
packetPush(new TextEncoder().encode(data));
}
};
packetPush(new Uint8Array([this.#WEBUI_SIGNATURE]));
packetPush(new Uint8Array([0, 0, 0, 0])); // Token (4 Bytes)
packetPush(new Uint8Array([0, 0])); // ID (2 Bytes)
packetPush(new Uint8Array([this.#CMD_JS]));
packetPush(new Uint8Array(FunError ? [1] : [0]));
packetPushStr(FunReturn);
packetPush(new Uint8Array([0]));
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
this.#addID(packet, callId, this.#PROTOCOL_ID);
this.#sendData(packet);
}
break;
case this.#CMD_CALL_FUNC:
{
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Call Response]
const callResponse: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
if (this.#log) {
console.log(`WebUI -> CMD -> Call Response [${callResponse}]`);
}
if (this.#callPromiseResolve[callId]) {
if (this.#log) {
console.log(`WebUI -> CMD -> Resolving Response #${callId}...`);
}
this.#callPromiseResolve[callId]?.(callResponse);
this.#callPromiseResolve[callId] = undefined;
}
}
break;
case this.#CMD_NAVIGATION:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [URL]
const url: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
if (this.#log) console.log(`WebUI -> CMD -> Navigation [${url}]`);
this.#close(this.#CMD_NAVIGATION, url);
break;
case this.#CMD_WINDOW_RESIZED:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [x,y,width,height]
const widthAndHeight: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
const { x, y, width, height } = this.#parseDimensions(widthAndHeight);
// Update drag positions
this.#currentWindowX = x;
this.#currentWindowY = y;
if (this.#log) console.log(`WebUI -> CMD -> Window Resized [x: ${x}, y: ${y}, width: ${width}, height: ${height}]`);
break;
case this.#CMD_NEW_ID:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [New Element]
const newElement: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
if (this.#log) console.log(`WebUI -> CMD -> New Bind ID [${newElement}]`);
if (!this.#bindsList.includes(newElement)) this.#bindsList.push(newElement);
// Generate objects
this.#updateBindsList();
break;
case this.#CMD_CLOSE:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
if (this.#log) {
// Debug Close
console.log(`WebUI -> CMD -> Close`);
if (this.#wsIsConnected()) {
this.#wsStayAlive = false;
this.#ws.close();
}
}
else {
// Release Close
globalThis.close();
}
break;
case this.#CMD_CHECK_TK:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Status]
// 5: [BindsList]
const status = (buffer8[this.#PROTOCOL_DATA] == 0 ? false : true);
const tokenHex = `0x${this.#token.toString(16).padStart(8, '0')}`;
if (status) {
if (this.#log) console.log(`WebUI -> CMD -> Token [${tokenHex}] Accepted`);
this.#TokenAccepted = true;
// Get binds list (CSV)
let csv: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA + 1);
csv = csv.endsWith(',') ? csv.slice(0, -1) : csv;
this.#bindsList = csv.split(',');
// Generate objects
this.#updateBindsList();
// User event callback
if (this.#eventsCallback) {
this.#eventsCallback(this.event.CONNECTED);
}
}
else {
if (this.#log) console.log(`WebUI -> CMD -> Token [${tokenHex}] Not Accepted. Reload page...`);
// Refresh the page to get a new token
this.#allowNavigation = true;
this.#wsStayAlive = false;
globalThis.location.reload();
}
break;
}
} else {
// Raw-binary based commands
switch (buffer8[this.#PROTOCOL_CMD]) {
case this.#CMD_SEND_RAW:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Function,Null,Raw Data]
// Get function name
const functionName: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
// Get the raw data
const rawDataIndex: number = this.#PROTOCOL_DATA + functionName.length + 1;
const rawDataSize: number = (buffer8.length - rawDataIndex) - 1;
const userRawData = buffer8.subarray(rawDataIndex, (rawDataIndex + rawDataSize));
if (this.#log) console.log(`WebUI -> CMD -> Received Raw ${rawDataSize} bytes for [${functionName}()]`);
// Call the user function, and pass the raw data
if (typeof window[functionName] === 'function') window[functionName](userRawData);
else await AsyncFunction(functionName + '(userRawData)')();
break;
}
}
};
// -- Public APIs --------------------------
/**
* Call a backend function
*
* @param fn - binding name
* @param data - data to be send to the backend function
* @return - Response of the backend callback string
* @example - const res = await webui.call("myID", 123, true, "Hi", new Uint8Array([0x42, 0x43, 0x44]))
*/
async call(fn: string, ...args: DataTypes[]): Promise<DataTypes> {
if (!fn) return Promise.reject(new SyntaxError('No binding name is provided'));
if (!this.#wsIsConnected()) return Promise.reject(new Error('WebSocket is not connected'));
// Check binding list
if (fn !== '__webui_core_api__') {
if (!this.#AllEvents && !this.#bindsList.includes(`${fn}`))
return Promise.reject(new ReferenceError(`No binding was found for "${fn}"`));
}
// Call backend and wait for response
if (this.#log) console.log(`WebUI -> Calling [${fn}(...)]`);
const response = (await this.#callPromise(fn, ...args)) as string;
// WebUI lib accept `DataTypes` but return only string
if (typeof response !== 'string') return '';
return response;
}
/**
* Active or deactivate webui debug logging
*
* @param status - log status to set
*/
setLogging(status: boolean) {
if (status) {
console.log('WebUI -> Log Enabled.');
this.#log = true;
} else {
console.log('WebUI -> Log Disabled.');
this.#log = false;
}
}
/**
* Encode text into base64 string
*
* @param data - text string
*/
encode(data: string): string {
return btoa(data);
}
/**
* Decode base64 string into text
*
* @param data - base64 string
*/
decode(data: string): string {
return atob(data);
}
/**
* Set a callback to receive events like connect/disconnect
*
* @param callback - callback function `myCallback(e)`
* @example - webui.setEventCallback((e) => {if(e == webui.event.CONNECTED){ ... }});
*/
setEventCallback(callback: (e: number) => void): void {
this.#eventsCallback = callback;
}
/**
* Check if UI is connected to the back-end. The connection
* is done by including `webui.js` virtual file in the HTML.
*
* @return - Boolean `true` if connected
*/
isConnected(): boolean {
return ((this.#wsIsConnected()) && (this.#TokenAccepted));
}
/**
* Get OS high contrast preference.
*
* @return - Boolean `True` if OS is using high contrast theme
*/
async isHighContrast(): Promise<boolean> {
// Call a core function and wait for response
const response = await this.callCore("high_contrast") as boolean;
if (this.#log) console.log(`Core Response: [${response}]`);
return response;
}
/**
* When binding all events on the backend, WebUI blocks all navigation events
* and sends them to the backend. This API allows you to control that behavior.
*
* @param status - Boolean `True` means WebUI will allow navigations
* @example - webui.allowNavigation(true); // Allow navigation
* window.location.replace('www.test.com'); // This will now proceed as usual
*/
allowNavigation(status: boolean): void {
this.#allowNavigation = status;
}
}
// Export
type webui = WebuiBridge;
export default webui;
export type { WebuiBridge };
// Wait for the html to be parsed
addEventListener('load', () => {
document.body.addEventListener('contextmenu', (event) => event.preventDefault());
addRefreshableEventListener(document.body, 'input', 'contextmenu', (event) => event.stopPropagation());
});

File diff suppressed because it is too large Load Diff

View File

@ -1,719 +0,0 @@
'use-strict'; // Force strict mode for transpiled
/*
WebUI Bridge
http://webui.me
https://github.com/webui-dev/webui
Copyright (c) 2020-2023 Hassan Draga.
Licensed under MIT License.
All rights reserved.
Canada.
Converted from JavaScript to TypeScript
By Oculi Julien. Copyright (c) 2023.
*/
//@ts-ignore use *.ts import real extension
import { AsyncFunction, addRefreshableEventListener } from './utils.ts';
type DataTypes = string | number | boolean | Uint8Array;
class WebuiBridge {
// WebUI settings
#secure: boolean;
#token: number;
#port: number;
#winNum: number;
#bindList: string[] = [];
#log: boolean;
#winX: number;
#winY: number;
#winW: number;
#winH: number;
// Internals
#ws: WebSocket;
#wsStatus = false;
#wsStatusOnce = false;
#closeReason = 0;
#closeValue: string;
#hasEvents = false;
#callPromiseID = new Uint16Array(1);
#callPromiseResolve: (((data: string) => unknown) | undefined)[] = [];
#allowNavigation = false;
#sendQueue: Uint8Array[] = [];
#isSending = false;
// WebUI const
#WEBUI_SIGNATURE = 221;
#CMD_JS = 254;
#CMD_JS_QUICK = 253;
#CMD_CLICK = 252;
#CMD_NAVIGATION = 251;
#CMD_CLOSE = 250;
#CMD_CALL_FUNC = 249;
#CMD_SEND_RAW = 248;
#CMD_NEW_ID = 247;
#CMD_MULTI = 246;
#MULTI_CHUNK_SIZE = 65500;
#PROTOCOL_SIZE = 8; // Protocol header size in bytes
#PROTOCOL_SIGN = 0; // Protocol byte position: Signature (1 Byte)
#PROTOCOL_TOKEN = 1; // Protocol byte position: Token (4 Bytes)
#PROTOCOL_ID = 5; // Protocol byte position: ID (2 Bytes)
#PROTOCOL_CMD = 7; // Protocol byte position: Command (1 Byte)
#PROTOCOL_DATA = 8; // Protocol byte position: Data (n Byte)
#Token = new Uint32Array(1);
#Ping: Boolean = true;
constructor({
secure,
token,
port,
winNum,
bindList,
log = false,
winX,
winY,
winW,
winH,
}: {
secure: boolean;
token: number;
port: number;
winNum: number;
bindList: string[];
log?: boolean;
winX: number;
winY: number;
winW: number;
winH: number;
}) {
// Constructor arguments are injected by webui.c
this.#secure = secure;
this.#token = token;
this.#port = port;
this.#winNum = winNum;
this.#bindList = bindList;
this.#log = log;
this.#winX = winX;
this.#winY = winY;
this.#winW = winW;
this.#winH = winH;
// Token
this.#Token[0] = this.#token;
// Instance
if ('webui' in globalThis) {
throw new Error('Sorry. WebUI is already defined, only one instance is allowed.');
}
// Positioning the current window
if (this.#winX !== undefined && this.#winY !== undefined) {
window.moveTo(this.#winX, this.#winY);
}
// Resize the current window
if (this.#winW !== undefined && this.#winH !== undefined) {
window.resizeTo(this.#winW, this.#winH);
}
// WebSocket
if (!('WebSocket' in window)) {
alert('Sorry. WebSocket is not supported by your web browser.');
if (!this.#log) globalThis.close();
}
// Connect to the backend application
this.#start();
// Handle navigation server side
if ('navigation' in globalThis) {
globalThis.navigation.addEventListener('navigate', (event) => {
if (!this.#allowNavigation) {
event.preventDefault();
const url = new URL(event.destination.url);
if (this.#hasEvents) {
if (this.#log) console.log(`WebUI -> DOM -> Navigation Event [${url.href}]`);
this.#sendEventNavigation(url.href);
} else {
this.#close(this.#CMD_NAVIGATION, url.href);
}
}
});
} else {
// Handle all link click to prevent natural navigation
// Rebind listener if user inject new html
addRefreshableEventListener(document.body, 'a', 'click', (event) => {
if (!this.#allowNavigation) {
event.preventDefault();
const { href } = event.target as HTMLAnchorElement;
if (this.#hasEvents) {
if (this.#log) console.log(`WebUI -> DOM -> Navigation Click Event [${href}]`);
this.#sendEventNavigation(href);
} else {
this.#close(this.#CMD_NAVIGATION, href);
}
}
});
}
// Prevent F5 refresh
document.addEventListener('keydown', (event) => {
if (this.#log) return; // Allowed in debug mode
if (event.key === 'F5') event.preventDefault();
});
onbeforeunload = () => {
this.#close();
};
setTimeout(() => {
if (!this.#wsStatusOnce) {
this.#freezeUi();
alert('Sorry. WebUI failed to connect to the backend application. Please try again.');
if (!this.#log) globalThis.close();
}
}, 1500);
}
#close(reason = 0, value = '') {
this.#wsStatus = false;
this.#closeReason = reason;
this.#closeValue = value;
this.#ws.close();
if (reason === this.#CMD_NAVIGATION) {
if (this.#log) {
console.log(`WebUI -> Close -> Navigation to [${value}]`);
}
this.#allowNavigation = true;
globalThis.location.replace(this.#closeValue);
} else {
if (this.#log) {
console.log(`WebUI -> Close.`);
}
}
}
#freezeUi() {
document.body.style.filter = 'contrast(1%)';
}
#isTextBasedCommand(cmd: number): Boolean {
if (cmd !== this.#CMD_SEND_RAW) return true;
return false;
}
#getDataStrFromPacket(buffer: Uint8Array, startIndex: number): string {
let stringBytes: number[] = [];
for (let i = startIndex; i < buffer.length; i++) {
if (buffer[i] === 0) {
// Check for null byte
break;
}
stringBytes.push(buffer[i]);
}
// Convert the array of bytes to a string
const stringText = new TextDecoder().decode(new Uint8Array(stringBytes));
return stringText;
}
#getID(buffer: Uint8Array, index: number): number {
if (index < 0 || index >= buffer.length - 1) {
throw new Error('Index out of bounds or insufficient data.');
}
const firstByte = buffer[index];
const secondByte = buffer[index + 1];
const combined = (secondByte << 8) | firstByte; // Works only for little-endian
return combined;
}
#addToken(buffer: Uint8Array, value: number, index: number): void {
if (value < 0 || value > 0xffffffff) {
throw new Error('Number is out of the range for 4 bytes representation.');
}
if (index < 0 || index > buffer.length - 4) {
throw new Error('Index out of bounds or insufficient space in buffer.');
}
// WebUI expect Little-endian (Work for Little/Big endian platforms)
buffer[index] = value & 0xff; // Least significant byte
buffer[index + 1] = (value >>> 8) & 0xff;
buffer[index + 2] = (value >>> 16) & 0xff;
buffer[index + 3] = (value >>> 24) & 0xff; // Most significant byte
}
#addID(buffer: Uint8Array, value: number, index: number): void {
if (value < 0 || value > 0xffff) {
throw new Error('Number is out of the range for 2 bytes representation.');
}
if (index < 0 || index > buffer.length - 2) {
throw new Error('Index out of bounds or insufficient space in buffer.');
}
// WebUI expect Little-endian (Work for Little/Big endian platforms)
buffer[index] = value & 0xff; // Least significant byte
buffer[index + 1] = (value >>> 8) & 0xff; // Most significant byte
}
#start() {
this.#generateCallObjects();
this.#keepAlive();
this.#callPromiseID[0] = 0;
if (this.#bindList.includes(this.#winNum + '/')) {
this.#hasEvents = true;
}
const url = this.#secure ? 'wss://localhost' : 'ws://localhost';
this.#ws = new WebSocket(`${url}:${this.#port}/_webui_ws_connect`);
this.#ws.binaryType = 'arraybuffer';
this.#ws.onopen = () => {
this.#wsStatus = true;
this.#wsStatusOnce = true;
if (this.#log) console.log('WebUI -> Connected');
this.#clicksListener();
};
this.#ws.onerror = () => {
if (this.#log) console.log('WebUI -> Connection Failed');
this.#freezeUi();
};
this.#ws.onclose = (event) => {
this.#wsStatus = false;
if (this.#closeReason === this.#CMD_NAVIGATION) {
if (this.#log) {
console.log(`WebUI -> Connection closed du to Navigation to [${this.#closeValue}]`);
}
} else {
if (this.#log) {
console.log(`WebUI -> Connection lost (${event.code})`);
this.#freezeUi();
} else {
this.#closeWindowTimer();
}
}
};
this.#ws.onmessage = async (event) => {
const buffer8 = new Uint8Array(event.data);
if (buffer8.length < this.#PROTOCOL_SIZE) return;
if (buffer8[this.#PROTOCOL_SIGN] !== this.#WEBUI_SIGNATURE) return;
if (this.#isTextBasedCommand(buffer8[this.#PROTOCOL_CMD])) {
// UTF8 Text based commands
const callId = this.#getID(buffer8, this.#PROTOCOL_ID);
// Process Command
switch (buffer8[this.#PROTOCOL_CMD]) {
case this.#CMD_JS_QUICK:
case this.#CMD_JS:
{
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Script]
const script = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
const scriptSanitize = script.replace(/(?:\r\n|\r|\n)/g, '\n');
if (this.#log) console.log(`WebUI -> CMD -> JS [${scriptSanitize}]`);
// Get callback result
let FunReturn = 'undefined';
let FunError = false;
try {
FunReturn = await AsyncFunction(scriptSanitize)();
} catch (e) {
FunError = true;
FunReturn = e.message;
}
// Stop if this is a quick call
if (buffer8[this.#PROTOCOL_CMD] === this.#CMD_JS_QUICK) return;
// Get the call return
if (FunReturn === undefined) {
FunReturn = 'undefined';
}
// Logging
if (this.#log && !FunError) console.log(`WebUI -> CMD -> JS -> Return Success [${FunReturn}]`);
if (this.#log && FunError) console.log(`WebUI -> CMD -> JS -> Return Error [${FunReturn}]`);
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Error, Script Response]
let packet = new Uint8Array(0);
const packetPush = (data: Uint8Array) => {
const newPacket = new Uint8Array(packet.length + data.length);
newPacket.set(packet);
newPacket.set(data, packet.length);
packet = newPacket;
};
const packetPushStr = (data: string) => {
const chunkSize = 1024 * 8;
if (data.length > chunkSize) {
const encoder = new TextEncoder();
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.substring(i, Math.min(i + chunkSize, data.length));
const encodedChunk = encoder.encode(chunk);
packetPush(encodedChunk);
}
} else {
packetPush(new TextEncoder().encode(data));
}
};
packetPush(new Uint8Array([this.#WEBUI_SIGNATURE]));
packetPush(new Uint8Array([0, 0, 0, 0])); // Token (4 Bytes)
packetPush(new Uint8Array([0, 0])); // ID (2 Bytes)
packetPush(new Uint8Array([this.#CMD_JS]));
packetPush(new Uint8Array(FunError ? [1] : [0]));
packetPushStr(FunReturn);
packetPush(new Uint8Array([0]));
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
this.#addID(packet, callId, this.#PROTOCOL_ID);
this.#sendData(packet);
}
break;
case this.#CMD_CALL_FUNC:
{
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Call Response]
const callResponse = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
if (this.#log) {
console.log(`WebUI -> CMD -> Call Response [${callResponse}]`);
}
if (this.#callPromiseResolve[callId]) {
if (this.#log) {
console.log(`WebUI -> CMD -> Resolving Response #${callId}...`);
}
this.#callPromiseResolve[callId]?.(callResponse);
this.#callPromiseResolve[callId] = undefined;
}
}
break;
case this.#CMD_NAVIGATION:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [URL]
const url = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
console.log(`WebUI -> CMD -> Navigation [${url}]`);
this.#close(this.#CMD_NAVIGATION, url);
break;
case this.#CMD_NEW_ID:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [New Element]
const newElement = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
console.log(`WebUI -> CMD -> New Bind ID [${newElement}]`);
if (!this.#bindList.includes(newElement)) this.#bindList.push(newElement);
break;
case this.#CMD_CLOSE:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
if (!this.#log) globalThis.close();
else {
console.log(`WebUI -> CMD -> Close`);
this.#ws.close();
}
break;
}
} else {
// Raw-binary based commands
switch (buffer8[this.#PROTOCOL_CMD]) {
case this.#CMD_SEND_RAW:
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Function,Null,Raw Data]
// Get function name
const functionName: string = this.#getDataStrFromPacket(buffer8, this.#PROTOCOL_DATA);
// Get the raw data
const rawDataIndex: number = 2 + functionName.length + 1;
const userRawData = buffer8.subarray(rawDataIndex);
if (this.#log) console.log(`WebUI -> CMD -> Send Raw ${buffer8.length} bytes to [${functionName}()]`);
// Call the user function, and pass the raw data
if (typeof window[functionName] === 'function') window[functionName](userRawData);
else await AsyncFunction(functionName + '(userRawData)')();
break;
}
}
};
}
#keepAlive = async () => {
while (true) {
if (this.#Ping) {
// Some web browsers may close the connection
// let's send a void message to keep WS open
this.#sendData(new TextEncoder().encode('ping'));
} else {
// There is an active communication
this.#Ping = true;
}
await new Promise((resolve) => setTimeout(resolve, 20000));
}
};
#clicksListener() {
Object.keys(window).forEach((key) => {
if (/^on(click)/.test(key)) {
globalThis.addEventListener(key.slice(2), (event) => {
if (!(event.target instanceof HTMLElement)) return;
if (
this.#hasEvents ||
(event.target.id !== '' && this.#bindList.includes(this.#winNum + '/' + event.target?.id))
) {
this.#sendClick(event.target.id);
}
});
}
});
}
async #sendData(packet: Uint8Array) {
this.#Ping = false;
if (!this.#wsStatus || packet === undefined) return;
// Enqueue the packet
this.#sendQueue.push(packet);
if (this.#isSending) return;
this.#isSending = true;
while (this.#sendQueue.length > 0) {
const currentPacket = this.#sendQueue.shift()!;
if (currentPacket.length < this.#MULTI_CHUNK_SIZE) {
this.#ws.send(currentPacket.buffer);
} else {
// Pre-packet to let WebUI be ready for multi packet
const pre_packet = Uint8Array.of(
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_MULTI,
...new TextEncoder().encode(currentPacket.length.toString()),
0,
);
this.#ws.send(pre_packet.buffer);
// Send chunks
let offset = 0;
const sendChunk = async () => {
if (offset < currentPacket.length) {
const chunkSize = Math.min(this.#MULTI_CHUNK_SIZE, currentPacket.length - offset);
const chunk = currentPacket.subarray(offset, offset + chunkSize);
this.#ws.send(chunk);
offset += chunkSize;
await sendChunk();
}
};
await sendChunk();
}
}
this.#isSending = false;
}
#sendClick(elem: string) {
if (this.#wsStatus) {
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Element]
const packet =
elem !== ''
? Uint8Array.of(
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_CLICK,
...new TextEncoder().encode(elem),
0,
)
: Uint8Array.of(
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_CLICK,
0,
);
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
// this.#addID(packet, 0, this.#PROTOCOL_ID)
this.#sendData(packet);
if (this.#log) console.log(`WebUI -> Send Click [${elem}]`);
}
}
#sendEventNavigation(url: string) {
if (url !== '') {
if (this.#hasEvents) {
if (this.#log) console.log(`WebUI -> Send Navigation Event [${url}]`);
if (this.#wsStatus && this.#hasEvents) {
const packet = Uint8Array.of(
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [URL]
this.#WEBUI_SIGNATURE,
0,
0,
0,
0, // Token (4 Bytes)
0,
0, // ID (2 Bytes)
this.#CMD_NAVIGATION,
...new TextEncoder().encode(url),
);
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
// this.#addID(packet, 0, this.#PROTOCOL_ID)
this.#sendData(packet);
}
} else {
if (this.#log) console.log(`WebUI -> Navigation To [${url}]`);
this.#allowNavigation = true;
globalThis.location.replace(url);
}
}
}
#closeWindowTimer() {
setTimeout(function () {
globalThis.close();
}, 1000);
}
#toUint16(value: number): number {
return value & 0xffff;
}
#generateCallObjects() {
for (const bind of this.#bindList) {
if (bind.trim()) {
const fn = bind.replace(`${this.#winNum}/`, '');
if (fn.trim()) {
this[fn] = (...args: DataTypes[]) => this.call(fn, ...args);
if (typeof (window as any)[fn] === 'undefined') {
(window as any)[fn] = (...args: string[]) => this.call(fn, ...args);
}
}
}
}
}
#callPromise(fn: string, ...args: DataTypes[]) {
--this.#callPromiseID[0];
const callId = this.#toUint16(this.#callPromiseID[0]);
// Combine lengths
let argsLengths = args
.map((arg) => {
if (typeof arg === 'object') {
// Uint8Array
return arg.length;
} else {
// string, number, boolean
return new TextEncoder().encode(arg.toString()).length;
}
})
.join(';');
// Combine values
let argsValues: Uint8Array = new Uint8Array();
for (const arg of args) {
let buffer: Uint8Array;
if (typeof arg === 'object') {
buffer = arg; // Uint8Array
} else {
// string, number, boolean
buffer = new TextEncoder().encode(arg.toString());
}
const temp = new Uint8Array(argsValues.length + buffer.length + 1);
temp.set(argsValues, 0);
temp.set(buffer, argsValues.length);
temp[argsValues.length + buffer.length] = 0x00;
argsValues = temp;
}
// Protocol
// 0: [SIGNATURE]
// 1: [TOKEN]
// 2: [ID]
// 3: [CMD]
// 4: [Fn, Null, {LenLen...}, Null, {Data,Null,Data,Null...}]
let packet = new Uint8Array(0);
const packetPush = (data: Uint8Array) => {
const newPacket = new Uint8Array(packet.length + data.length);
newPacket.set(packet);
newPacket.set(data, packet.length);
packet = newPacket;
};
packetPush(new Uint8Array([this.#WEBUI_SIGNATURE]));
packetPush(new Uint8Array([0, 0, 0, 0])); // Token (4 Bytes)
packetPush(new Uint8Array([0, 0])); // ID (2 Bytes)
packetPush(new Uint8Array([this.#CMD_CALL_FUNC]));
packetPush(new TextEncoder().encode(fn));
packetPush(new Uint8Array([0]));
packetPush(new TextEncoder().encode(argsLengths));
packetPush(new Uint8Array([0]));
packetPush(new Uint8Array(argsValues));
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
this.#addID(packet, callId, this.#PROTOCOL_ID);
return new Promise((resolve) => {
this.#callPromiseResolve[callId] = resolve;
this.#sendData(packet);
});
}
// -- APIs --------------------------
/**
* Call a backend function
*
* @param fn - binding name
* @param data - data to be send to the backend function
* @return - Response of the backend callback string
* @example - const res = await webui.call("myID", 123, true, "Hi", new Uint8Array([0x42, 0x43, 0x44]))
*/
async call(fn: string, ...args: DataTypes[]): Promise<DataTypes> {
if (!fn) return Promise.reject(new SyntaxError('No binding name is provided'));
if (!this.#wsStatus) return Promise.reject(new Error('WebSocket is not connected'));
// Check binding list
if (!this.#hasEvents && !this.#bindList.includes(`${this.#winNum}/${fn}`))
return Promise.reject(new ReferenceError(`No binding was found for "${fn}"`));
// Call backend and wait for response
if (this.#log) console.log(`WebUI -> Calling [${fn}(...)]`);
const response = (await this.#callPromise(fn, ...args)) as string;
// WebUI lib accept `DataTypes` but return only string
if (typeof response !== 'string') return '';
return response;
}
/**
* Active or deactivate webui debug logging
*
* @param status - log status to set
*/
setLogging(status: boolean) {
if (status) {
console.log('WebUI -> Log Enabled.');
this.#log = true;
} else {
console.log('WebUI -> Log Disabled.');
this.#log = false;
}
}
/**
* Encode text into base64 string
*
* @param data - text string
*/
encode(data: string): string {
return btoa(data);
}
/**
* Decode base64 string into text
*
* @param data - base64 string
*/
decode(data: string): string {
return atob(data);
}
}
// Export
type webui = WebuiBridge;
export default webui;
export type { WebuiBridge };
// Wait for the html to be parsed
addEventListener('load', () => {
document.body.addEventListener('contextmenu', (event) => event.preventDefault());
addRefreshableEventListener(document.body, 'input', 'contextmenu', (event) => event.stopPropagation());
});

210
build.zig Normal file
View File

@ -0,0 +1,210 @@
const std = @import("std");
const builtin = @import("builtin");
const Build = std.Build;
const OptimizeMode = std.builtin.OptimizeMode;
const Compile = Build.Step.Compile;
const Module = Build.Module;
const lib_name = "webui";
var global_log_level: std.log.Level = .warn;
/// Vendored dependencies of webui.
pub const Dependency = enum {
civetweb,
// TODO: Check and add all vendored dependencies, e.g. "webview"
};
const DebugDependencies = std.EnumSet(Dependency);
pub fn build(b: *Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const is_dynamic = b.option(bool, "dynamic", "build the dynamic library") orelse false;
const enable_tls = b.option(bool, "enable-tls", "enable TLS support") orelse false;
const verbose = b.option(std.log.Level, "verbose", "set verbose output") orelse .warn;
global_log_level = verbose;
// TODO: Support list of dependencies once support is limited to >0.13.0
const debug = b.option(Dependency, "debug", "enable dependency debug output");
const debug_dependencies = DebugDependencies.initMany(if (debug) |d| &.{d} else &.{});
if (enable_tls and !target.query.isNative()) {
log(.err, .WebUI, "cross compilation is not supported with TLS enabled", .{});
return error.InvalidBuildConfiguration;
}
log(.info, .WebUI, "Building {s} WebUI library{s}...", .{
if (is_dynamic) "dynamic" else "static",
if (enable_tls) " with TLS support" else "",
});
defer {
log(.info, .WebUI, "Done.", .{});
}
const webui = if (is_dynamic) b.addSharedLibrary(.{
.name = lib_name,
.target = target,
.optimize = optimize,
.pic = true,
}) else b.addStaticLibrary(.{
.name = lib_name,
.target = target,
.optimize = optimize,
});
try addLinkerFlags(b, webui, enable_tls, debug_dependencies);
b.installArtifact(webui);
try build_examples(b, webui);
}
fn addLinkerFlags(
b: *Build,
webui: *Compile,
enable_tls: bool,
debug_dependencies: DebugDependencies,
) !void {
const webui_target = webui.rootModuleTarget();
const is_windows = webui_target.os.tag == .windows;
const is_darwin = webui_target.os.tag == .macos;
const debug = webui.root_module.optimize.? == .Debug;
// Prepare compiler flags.
const no_tls_flags: []const []const u8 = &.{"-DNO_SSL"};
const tls_flags: []const []const u8 = &.{ "-DWEBUI_TLS", "-DNO_SSL_DL", "-DOPENSSL_API_1_1" };
const civetweb_flags: []const []const u8 = &.{
"-DNO_CACHING",
"-DNO_CGI",
"-DUSE_WEBSOCKET",
"-Wno-error=date-time",
};
if (debug) {
webui.root_module.addCMacro("WEBUI_LOG", "");
}
webui.addCSourceFile(.{
.file = b.path("src/webui.c"),
.flags = if (enable_tls) tls_flags else no_tls_flags,
});
const civetweb_debug = debug and debug_dependencies.contains(.civetweb);
webui.addCSourceFile(.{
.file = b.path("src/civetweb/civetweb.c"),
.flags = if (enable_tls and !civetweb_debug)
civetweb_flags ++ tls_flags ++ .{"-DNDEBUG"}
else if (enable_tls and civetweb_debug)
civetweb_flags ++ tls_flags
else if (!enable_tls and !civetweb_debug)
civetweb_flags ++ .{"-DUSE_WEBSOCKET"} ++ no_tls_flags ++ .{"-DNDEBUG"}
else
civetweb_flags ++ .{"-DUSE_WEBSOCKET"} ++ no_tls_flags,
});
webui.linkLibC();
webui.addIncludePath(b.path("include"));
webui.installHeader(b.path("include/webui.h"), "webui.h");
if (is_darwin) {
webui.addCSourceFile(.{
.file = b.path("src/webview/wkwebview.m"),
.flags = &.{},
});
webui.linkFramework("Cocoa");
webui.linkFramework("WebKit");
} else if (is_windows) {
webui.linkSystemLibrary("ws2_32");
webui.linkSystemLibrary("ole32");
if (webui_target.abi == .msvc) {
webui.linkSystemLibrary("Advapi32");
webui.linkSystemLibrary("Shell32");
webui.linkSystemLibrary("user32");
}
if (enable_tls) {
webui.linkSystemLibrary("bcrypt");
}
}
if (enable_tls) {
webui.linkSystemLibrary("ssl");
webui.linkSystemLibrary("crypto");
}
for (webui.root_module.link_objects.items) |lo| {
switch (lo) {
.c_source_file => |csf| {
log(.debug, .WebUI, "{s} linker flags: {s}", .{
csf.file.src_path.sub_path,
csf.flags,
});
},
else => {},
}
}
}
fn build_examples(b: *Build, webui: *Compile) !void {
const build_examples_step = b.step("examples", "builds the library and its examples");
const target = webui.root_module.resolved_target.?;
const optimize = webui.root_module.optimize.?;
const examples_path = b.path("examples/C").getPath(b);
var examples_dir = std.fs.cwd().openDir(
examples_path,
.{ .iterate = true },
) catch |e| switch (e) {
// Do not attempt building examples if directory does not exist.
error.FileNotFound => return,
else => return e,
};
defer examples_dir.close();
var paths = examples_dir.iterate();
while (try paths.next()) |val| {
if (val.kind != .directory) {
continue;
}
const example_name = val.name;
const exe = b.addExecutable(.{
.name = example_name,
.target = target,
.optimize = optimize,
});
const path = try std.fmt.allocPrint(b.allocator, "examples/C/{s}/main.c", .{example_name});
defer b.allocator.free(path);
exe.addCSourceFile(.{ .file = b.path(path), .flags = &.{} });
exe.linkLibrary(webui);
const exe_install = b.addInstallArtifact(exe, .{});
const exe_run = b.addRunArtifact(exe);
const step_name = try std.fmt.allocPrint(b.allocator, "run_{s}", .{example_name});
defer b.allocator.free(step_name);
const step_desc = try std.fmt.allocPrint(b.allocator, "run example {s}", .{example_name});
defer b.allocator.free(step_desc);
const cwd = try std.fmt.allocPrint(b.allocator, "src/examples/{s}", .{example_name});
defer b.allocator.free(cwd);
exe_run.setCwd(b.path(cwd));
exe_run.step.dependOn(&exe_install.step);
build_examples_step.dependOn(&exe_install.step);
b.step(step_name, step_desc).dependOn(&exe_run.step);
}
}
/// Function to runtime-scope log levels based on build flag, for all scopes.
fn log(
comptime level: std.log.Level,
comptime scope: @TypeOf(.EnumLiteral),
comptime format: []const u8,
args: anytype,
) void {
const should_print: bool = @intFromEnum(global_log_level) >= @intFromEnum(level);
if (should_print) {
switch (comptime level) {
.err => std.log.scoped(scope).err(format, args),
.warn => std.log.scoped(scope).warn(format, args),
.info => std.log.scoped(scope).info(format, args),
.debug => std.log.scoped(scope).debug(format, args),
}
}
}

14
build.zig.zon Normal file
View File

@ -0,0 +1,14 @@
.{
.name = .webui,
.version = "2.5.0-beta.4",
.fingerprint = 0xac5d87f2e5831aa7,
.paths = .{
"src",
"include",
"bridge",
"build.zig",
"build.zig.zon",
"LICENSE",
"README.md",
},
}

View File

@ -4,7 +4,11 @@
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
@ -13,25 +17,28 @@ endif
# ARGS
# Set a compiler when running on Linux via `make CC=g++` / `make CC=clang`
CXX = g++
CC = g++
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
STATIC_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -Wl,-subsystem=console -luser32 -static
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -Wl,-subsystem=console -luser32
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
@ -40,14 +47,18 @@ else
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib"
CXX = clang
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CXX),clang)
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
@ -57,19 +68,19 @@ endif
all: release
debug: LIB_DIR := $(LIB_DIR)/debug
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) debug static)..."
@$(CXX) -g $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CXX) debug dynamic)..."
@$(CXX) -g $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -85,13 +96,14 @@ ifeq ($(BUILD_LIB),true)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) release static)..."
@$(CXX) -Os $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CXX) release dynamic)..."
@$(CXX) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@ -107,8 +119,8 @@ clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CXX),g++ clang),$(CXX))
$(error Invalid compiler specified: `$(CXX)`)
ifneq ($(filter $(CC),g++ clang aarch64-linux-gnu-g++ arm-linux-gnueabihf-g++ musl-g++),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix

View File

@ -21,11 +21,11 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Debug Static)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C++ Example (Debug Dynamic)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@ -41,11 +41,11 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Release Static)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C++ Example (Release Dynamic)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -9,7 +9,7 @@
void my_function_string(webui::window::event* e) {
// JavaScript:
// webui.call('MyID_One', 'Hello', 'World`);
// my_function_string('Hello', 'World`);
std::string str_1 = e->get_string(); // Or e->get_string(0);
std::string str_2 = e->get_string(1);
@ -21,7 +21,7 @@ void my_function_string(webui::window::event* e) {
void my_function_integer(webui::window::event* e) {
// JavaScript:
// webui.call('MyID_Two', 123, 456, 789);
// my_function_integer(123, 456, 789);
long long number_1 = e->get_int(); // Or e->get_int(0);
long long number_2 = e->get_int(1);
@ -35,7 +35,7 @@ void my_function_integer(webui::window::event* e) {
void my_function_boolean(webui::window::event* e) {
// JavaScript:
// webui.call('MyID_Three', true, false);
// my_function_boolean(true, false);
bool status_1 = e->get_bool(); // Or e->get_bool(0);
bool status_2 = e->get_bool(1);
@ -47,7 +47,7 @@ void my_function_boolean(webui::window::event* e) {
void my_function_with_response(webui::window::event* e) {
// JavaScript:
// webui.call('MyID_Four', number, 2).then(...)
// my_function_with_response(number, 2).then(...)
long long number = e->get_int(0);
long long times = e->get_int(1);
@ -64,58 +64,58 @@ int main() {
// HTML
const std::string my_html = R"V0G0N(
<html>
<head>
<meta charset="UTF-8">
<script src="webui.js"></script>
<html>
<head>
<meta charset="UTF-8">
<script src="/webui.js"></script>
<title>Call C++ from JavaScript Example</title>
<style>
body {
background: linear-gradient(to left, #36265a, #654da9);
color: AliceBlue;
font-size: 16px sans-serif;
text-align: center;
margin-top: 30px;
}
button {
margin: 5px 0 10px;
}
</style>
</head>
<body>
<h1>WebUI - Call C++ from JavaScript</h1>
<p>Call C++ functions with arguments (<em>See the logs in your terminal</em>)</p>
<button onclick="webui.call('MyID_One', 'Hello', 'World');">Call my_function_string()</button>
<br>
<button onclick="webui.call('MyID_Two', 123, 456, 789);">Call my_function_integer()</button>
<br>
<button onclick="webui.call('MyID_Three', true, false);">Call my_function_boolean()</button>
<br>
<p>Call a C++ function that returns a response</p>
<button onclick="MyJS();">Call my_function_with_response()</button>
<div>Double: <input type="text" id="MyInputID" value="2"></div>
<script>
function MyJS() {
const MyInput = document.getElementById('MyInputID');
const number = MyInput.value;
webui.call('MyID_Four', number, 2).then((response) => {
MyInput.value = response;
});
}
</script>
</body>
</html>
)V0G0N";
<title>Call C++ from JavaScript Example</title>
<style>
body {
background: linear-gradient(to left, #36265a, #654da9);
color: AliceBlue;
font-size: 16px sans-serif;
text-align: center;
margin-top: 30px;
}
button {
margin: 5px 0 10px;
}
</style>
</head>
<body>
<h1>WebUI - Call C++ from JavaScript</h1>
<p>Call C++ functions with arguments (<em>See the logs in your terminal</em>)</p>
<button onclick="my_function_string('Hello', 'World');">Call my_function_string()</button>
<br>
<button onclick="my_function_integer(123, 456, 789);">Call my_function_integer()</button>
<br>
<button onclick="my_function_boolean(true, false);">Call my_function_boolean()</button>
<br>
<p>Call a C++ function that returns a response</p>
<button onclick="MyJS();">Call my_function_with_response()</button>
<div>Double: <input type="text" id="MyInputID" value="2"></div>
<script>
function MyJS() {
const MyInput = document.getElementById('MyInputID');
const number = MyInput.value;
my_function_with_response(number, 2).then((response) => {
MyInput.value = response;
});
}
</script>
</body>
</html>
)V0G0N";
// Create a window
webui::window my_window;
// Bind HTML elements with C++ functions
my_window.bind("MyID_One", my_function_string);
my_window.bind("MyID_Two", my_function_integer);
my_window.bind("MyID_Three", my_function_boolean);
my_window.bind("MyID_Four", my_function_with_response);
my_window.bind("my_function_string", my_function_string);
my_window.bind("my_function_integer", my_function_integer);
my_window.bind("my_function_boolean", my_function_boolean);
my_window.bind("my_function_with_response", my_function_with_response);
// Show the window
my_window.show(my_html); // webui_show_browser(my_window, my_html, Chrome);

View File

@ -4,7 +4,11 @@
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
@ -13,25 +17,28 @@ endif
# ARGS
# Set a compiler when running on Linux via `make CC=g++` / `make CC=clang`
CXX = g++
CC = g++
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
STATIC_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -Wl,-subsystem=console -luser32 -static
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -Wl,-subsystem=console -luser32
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
@ -40,14 +47,18 @@ else
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib"
CXX = clang
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CXX),clang)
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
@ -57,19 +68,19 @@ endif
all: release
debug: LIB_DIR := $(LIB_DIR)/debug
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) debug static)..."
@$(CXX) -g $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CXX) debug dynamic)..."
@$(CXX) -g $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -85,13 +96,14 @@ ifeq ($(BUILD_LIB),true)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) release static)..."
@$(CXX) -Os $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CXX) release dynamic)..."
@$(CXX) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@ -107,8 +119,8 @@ clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CXX),g++ clang),$(CXX))
$(error Invalid compiler specified: `$(CXX)`)
ifneq ($(filter $(CC),g++ clang aarch64-linux-gnu-g++ arm-linux-gnueabihf-g++ musl-g++),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix

View File

@ -21,11 +21,11 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Debug Static)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C++ Example (Debug Dynamic)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@ -41,11 +41,11 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Release Static)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C++ Example (Release Dynamic)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -17,8 +17,6 @@ void my_function_exit(webui::window::event* e) {
void my_function_count(webui::window::event* e) {
// This function gets called every time the user clicks on "MyButton1"
// Create a buffer to hold the response
char response[64];
@ -55,59 +53,59 @@ int main() {
// HTML
const std::string my_html = R"V0G0N(
<html>
<head>
<meta charset="UTF-8">
<script src="webui.js"></script>
<title>Call JavaScript from C++ Example</title>
<style>
body {
background: linear-gradient(to left, #36265a, #654da9);
color: AliceBlue;
font: 16px sans-serif;
text-align: center;
margin-top: 30px;
}
button {
margin: 5px 0 10px;
}
</style>
</head>
<body>
<h1>WebUI - Call JavaScript from C++</h1>
<br>
<h1 id="count">0</h1>
<br>
<button id="MyButton1">Manual Count</button>
<br>
<button id="MyTest" onclick="AutoTest();">Auto Count (Every 10ms)</button>
<br>
<button id="MyButton2">Exit</button>
<script>
let count = 0;
function GetCount() {
return count;
}
function SetCount(number) {
document.getElementById('count').innerHTML = number;
count = number;
}
function AutoTest(number) {
setInterval(function() {
webui.call('MyButton1');
}, 10);
}
</script>
</body>
</html>
)V0G0N";
<html>
<head>
<meta charset="UTF-8">
<script src="/webui.js"></script>
<title>Call JavaScript from C++ Example</title>
<style>
body {
background: linear-gradient(to left, #36265a, #654da9);
color: AliceBlue;
font: 16px sans-serif;
text-align: center;
margin-top: 30px;
}
button {
margin: 5px 0 10px;
}
</style>
</head>
<body>
<h1>WebUI - Call JavaScript from C++</h1>
<br>
<h1 id="count">0</h1>
<br>
<button OnClick="my_function_count();">Manual Count</button>
<br>
<button OnClick="AutoTest();">Auto Count (Every 10ms)</button>
<br>
<button id="Exit">Exit</button>
<script>
let count = 0;
function GetCount() {
return count;
}
function SetCount(number) {
document.getElementById('count').innerHTML = number;
count = number;
}
function AutoTest(number) {
setInterval(function() {
my_function_count();
}, 10);
}
</script>
</body>
</html>
)V0G0N";
// Create a window
webui::window my_window;
// Bind HTML elements with C++ functions
my_window.bind("MyButton1", my_function_count);
my_window.bind("MyButton2", my_function_exit);
my_window.bind("my_function_count", my_function_count);
my_window.bind("Exit", my_function_exit);
// Show the window
my_window.show(my_html); // my_window.show_browser(my_html, Chrome);

View File

@ -4,7 +4,11 @@
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
@ -13,25 +17,28 @@ endif
# ARGS
# Set a compiler when running on Linux via `make CC=g++` / `make CC=clang`
CXX = g++
CC = g++
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
STATIC_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -Wl,-subsystem=console -luser32 -static
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -Wl,-subsystem=console -luser32
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
@ -40,14 +47,18 @@ else
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib"
CXX = clang
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CXX),clang)
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
@ -57,19 +68,19 @@ endif
all: release
debug: LIB_DIR := $(LIB_DIR)/debug
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) debug static)..."
@$(CXX) -g $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CXX) debug dynamic)..."
@$(CXX) -g $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -85,13 +96,14 @@ ifeq ($(BUILD_LIB),true)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) release static)..."
@$(CXX) -Os $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CXX) release dynamic)..."
@$(CXX) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@ -107,8 +119,8 @@ clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CXX),g++ clang),$(CXX))
$(error Invalid compiler specified: `$(CXX)`)
ifneq ($(filter $(CC),g++ clang aarch64-linux-gnu-g++ arm-linux-gnueabihf-g++ musl-g++),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix

View File

@ -21,11 +21,11 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Debug Static)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C++ Example (Debug Dynamic)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@ -41,11 +41,11 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Release Static)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C++ Example (Release Dynamic)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -4,7 +4,11 @@
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
@ -13,25 +17,28 @@ endif
# ARGS
# Set a compiler when running on Linux via `make CC=g++` / `make CC=clang`
CXX = g++
CC = g++
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = -std=c++17 -lstdc++ main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
STATIC_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -Wl,-subsystem=console -luser32 -static
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -Wl,-subsystem=console -luser32
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
@ -40,14 +47,18 @@ else
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib"
CXX = clang
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
DYN_BUILD_FLAGS += "$(LIB_DIR)/$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CXX),clang)
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
@ -57,19 +68,19 @@ endif
all: release
debug: LIB_DIR := $(LIB_DIR)/debug
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) debug static)..."
@$(CXX) -g $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CXX) debug dynamic)..."
@$(CXX) -g $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -85,13 +96,14 @@ ifeq ($(BUILD_LIB),true)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CXX) release static)..."
@$(CXX) -Os $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@echo "Build C++ Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CXX) release dynamic)..."
@$(CXX) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@echo "Build C++ Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@ -107,8 +119,8 @@ clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CXX),g++ clang),$(CXX))
$(error Invalid compiler specified: `$(CXX)`)
ifneq ($(filter $(CC),g++ clang aarch64-linux-gnu-g++ arm-linux-gnueabihf-g++ musl-g++),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix

View File

@ -21,11 +21,11 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Debug Static)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C++ Example (Debug Dynamic)...
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@ -41,11 +41,11 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C++ Example (Release Static)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C++ Example (Release Dynamic)...
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -35,5 +35,5 @@
</body>
<!-- Connect this window to the background app -->
<script src="webui.js"></script>
<script src="/webui.js"></script>
</html>

View File

@ -22,5 +22,5 @@
</body>
<!-- Connect this window to the background app -->
<script src="webui.js"></script>
<script src="/webui.js"></script>
</html>

View File

@ -35,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
@ -44,19 +44,19 @@ else
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
CONSOLE_APP :=
GUI_APP :=
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib" "$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).dylib"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).so" "$(WEBUI_LIB_NAME).so"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
@ -75,12 +75,12 @@ endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -97,13 +97,13 @@ endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)

View File

@ -21,18 +21,17 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
release:
@ -42,12 +41,12 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -5,7 +5,7 @@
void my_function_string(webui_event_t* e) {
// JavaScript:
// webui.call('MyID_One', 'Hello', 'World`);
// my_function_string('Hello', 'World`);
const char* str_1 = webui_get_string(e); // Or webui_get_string_at(e, 0);
const char* str_2 = webui_get_string_at(e, 1);
@ -17,7 +17,10 @@ void my_function_string(webui_event_t* e) {
void my_function_integer(webui_event_t* e) {
// JavaScript:
// webui.call('MyID_Two', 123, 456, 789);
// my_function_integer(123, 456, 789, 12345.6789);
size_t count = webui_get_count(e);
printf("my_function_integer: There is %zu arguments in this event\n", count); // 4
long long number_1 = webui_get_int(e); // Or webui_get_int_at(e, 0);
long long number_2 = webui_get_int_at(e, 1);
@ -26,12 +29,16 @@ void my_function_integer(webui_event_t* e) {
printf("my_function_integer 1: %lld\n", number_1); // 123
printf("my_function_integer 2: %lld\n", number_2); // 456
printf("my_function_integer 3: %lld\n", number_3); // 789
double float_1 = webui_get_float_at(e, 3);
printf("my_function_integer 4: %f\n", float_1); // 12345.6789
}
void my_function_boolean(webui_event_t* e) {
// JavaScript:
// webui.call('MyID_Three', true, false);
// my_function_boolean(true, false);
bool status_1 = webui_get_bool(e); // Or webui_get_bool_at(e, 0);
bool status_2 = webui_get_bool_at(e, 1);
@ -43,7 +50,7 @@ void my_function_boolean(webui_event_t* e) {
void my_function_raw_binary(webui_event_t* e) {
// JavaScript:
// webui.call('MyID_RawBinary', new Uint8Array([0x41]), new Uint8Array([0x42, 0x43]));
// my_function_raw_binary(new Uint8Array([0x41]), new Uint8Array([0x42, 0x43]));
const unsigned char* raw_1 = (const unsigned char*)webui_get_string(e); // Or webui_get_string_at(e, 0);
const unsigned char* raw_2 = (const unsigned char*)webui_get_string_at(e, 1);
@ -70,7 +77,7 @@ void my_function_raw_binary(webui_event_t* e) {
void my_function_with_response(webui_event_t* e) {
// JavaScript:
// webui.call('MyID_Four', number, 2).then(...)
// my_function_with_response(number, 2).then(...)
long long number = webui_get_int(e); // Or webui_get_int_at(e, 0);
long long times = webui_get_int_at(e, 1);
@ -122,13 +129,13 @@ int main() {
" <body>"
" <h1>WebUI - Call C from JavaScript</h1>"
" <p>Call C functions with arguments (<em>See the logs in your terminal</em>)</p>"
" <button onclick=\"webui.call('MyID_One', 'Hello', 'World');\">Call my_function_string()</button>"
" <button onclick=\"my_function_string('Hello', 'World');\">Call my_function_string()</button>"
" <br>"
" <button onclick=\"webui.call('MyID_Two', 123, 456, 789);\">Call my_function_integer()</button>"
" <button onclick=\"my_function_integer(123, 456, 789, 12345.6789);\">Call my_function_integer()</button>"
" <br>"
" <button onclick=\"webui.call('MyID_Three', true, false);\">Call my_function_boolean()</button>"
" <button onclick=\"my_function_boolean(true, false);\">Call my_function_boolean()</button>"
" <br>"
" <button onclick=\"webui.call('MyID_RawBinary', new Uint8Array([0x41,0x42,0x43]), big_arr);\"> "
" <button onclick=\"my_function_raw_binary(new Uint8Array([0x41,0x42,0x43]), big_arr);\"> "
" Call my_function_raw_binary()</button>"
" <br>"
" <p>Call a C function that returns a response</p>"
@ -142,7 +149,7 @@ int main() {
" function MyJS() {"
" const MyInput = document.getElementById('MyInputID');"
" const number = MyInput.value;"
" webui.call('MyID_Four', number, 2).then((response) => {"
" my_function_with_response(number, 2).then((response) => {"
" MyInput.value = response;"
" });"
" }"
@ -154,11 +161,11 @@ int main() {
size_t my_window = webui_new_window();
// Bind HTML elements with C functions
webui_bind(my_window, "MyID_One", my_function_string);
webui_bind(my_window, "MyID_Two", my_function_integer);
webui_bind(my_window, "MyID_Three", my_function_boolean);
webui_bind(my_window, "MyID_Four", my_function_with_response);
webui_bind(my_window, "MyID_RawBinary", my_function_raw_binary);
webui_bind(my_window, "my_function_string", my_function_string);
webui_bind(my_window, "my_function_integer", my_function_integer);
webui_bind(my_window, "my_function_boolean", my_function_boolean);
webui_bind(my_window, "my_function_with_response", my_function_with_response);
webui_bind(my_window, "my_function_raw_binary", my_function_raw_binary);
// Show the window
webui_show(my_window, my_html); // webui_show_browser(my_window, my_html, Chrome);

View File

@ -35,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
@ -44,19 +44,19 @@ else
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
CONSOLE_APP :=
GUI_APP :=
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib" "$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).dylib"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).so" "$(WEBUI_LIB_NAME).so"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
@ -75,12 +75,12 @@ endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -97,13 +97,13 @@ endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)

View File

@ -21,18 +21,17 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
release:
@ -42,12 +41,12 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -10,7 +10,7 @@ void my_function_exit(webui_event_t* e) {
void my_function_count(webui_event_t* e) {
// This function gets called every time the user clicks on "MyButton1"
// This function gets called every time the user clicks on "my_function_count"
// Create a buffer to hold the response
char response[64];
@ -80,11 +80,11 @@ int main() {
" <br>"
" <h1 id=\"count\">0</h1>"
" <br>"
" <button id=\"MyButton1\">Manual Count</button>"
" <button OnClick=\"my_function_count();\">Manual Count</button>"
" <br>"
" <button id=\"MyTest\" OnClick=\"AutoTest();\">Auto Count (Every 10ms)</button>"
" <br>"
" <button id=\"MyButton2\">Exit</button>"
" <button OnClick=\"my_function_exit();\">Exit</button>"
" <script>"
" let count = 0;"
" function GetCount() {"
@ -95,7 +95,7 @@ int main() {
" count = number;"
" }"
" function AutoTest(number) {"
" setInterval(function(){ webui.call('MyButton1'); }, 10);"
" setInterval(function(){ my_function_count(); }, 10);"
" }"
" </script>"
" </body>"
@ -105,8 +105,8 @@ int main() {
size_t my_window = webui_new_window();
// Bind HTML elements with C functions
webui_bind(my_window, "MyButton1", my_function_count);
webui_bind(my_window, "MyButton2", my_function_exit);
webui_bind(my_window, "my_function_count", my_function_count);
webui_bind(my_window, "my_function_exit", my_function_exit);
// Show the window
webui_show(my_window, my_html); // webui_show_browser(my_window, my_html, Chrome);

View File

@ -0,0 +1,141 @@
# WebUI C Example
# == 1. VARIABLES =============================================================
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
WEBUI_LIB_NAME = webui-2-secure
endif
# ARGS
# Set a compiler when running on Linux via `make CC=gcc` / `make CC=clang`
CC = gcc
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
endif
# == 2.TARGETS ================================================================
all: release
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
release: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CC),gcc clang aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc musl-gcc),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix
--clean-macos: --clean-unix
--clean-unix:
- rm -f *.o
- rm -f *.a
- rm -f *.so
- rm -f *.dylib
- rm -rf *.dSYM
--clean-windows:
- del *.o >nul 2>&1
- del *.dll >nul 2>&1
- del *.a >nul 2>&1
- del *.exe >nul 2>&1

View File

@ -0,0 +1,64 @@
# WebUI C Example
# Windows - Microsoft Visual C
SHELL = CMD
LIB_DIR = ../../../dist
INCLUDE_DIR = ../../../include
WEBUI_LIB_NAME = webui-2
!IF "$(WEBUI_USE_TLS)" == "1"
WEBUI_LIB_NAME = webui-2-secure
!ENDIF
# Build the WebUI library if running `nmake BUILD_LIB=true`
BUILD_LIB =
all: release
debug:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE) debug
!ENDIF
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@echo Done.
release:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE)
!ENDIF
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
clean:
- del *.obj >nul 2>&1
- del *.ilk >nul 2>&1
- del *.pdb >nul 2>&1
- del *.exp >nul 2>&1
- del *.exe >nul 2>&1
- del *.lib >nul 2>&1

View File

@ -0,0 +1,98 @@
// WebUI C - ChatGPT HTTPS API Example
#include "webui.h"
// ChatGPT Configuration
#define USER_KEY "sk-proj-xxx-xxxxxxxxxxxxxxxxxxxxxxx_xxx"
#define USER_MODEL "gpt-4o"
#define USER_ASSISTANT "You are an assistant, answer with very short messages."
#define BUF_SIZE (1024)
size_t hiddenWindow = 0;
// HTML
const char* html = "<!DOCTYPE html>"
"<html>"
" <head>"
" <script src=\"webui.js\"></script>"
" </head>"
" <body>"
" <script>"
" function run_gpt_api(userKey, userModel, userAssistant, userContent) {"
" const xhr = new XMLHttpRequest();"
" xhr.open(\"POST\", \"https://api.openai.com/v1/chat/completions\", false);"
" xhr.setRequestHeader(\"Content-Type\", \"application/json\");"
" xhr.setRequestHeader(\"Authorization\", \"Bearer \" + userKey);"
" xhr.send(JSON.stringify({"
" model: userModel,"
" messages: ["
" { role: \"developer\", content: userAssistant },"
" { role: \"user\", content: userContent }"
" ]"
" }));"
" const responseJson = JSON.parse(xhr.responseText);"
" if (responseJson.error) {"
" return 'Error: ' + responseJson.error.message;"
" }"
" return (responseJson.choices[0].message.content).trim();"
" }"
" </script>"
" </body>"
"</html>";
bool run_ai_query(const char* user_query, char* ai_response) {
char js[BUF_SIZE];
memset(js, 0, BUF_SIZE);
// Generate JavaScript
sprintf(js,
"return run_gpt_api('%s', '%s', '%s', '%s');",
USER_KEY, USER_MODEL, USER_ASSISTANT, user_query
);
// Run HTTPS API
if (webui_script(hiddenWindow, js, 30, ai_response, BUF_SIZE)) {
return true;
}
return false;
}
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Please provide a query.\nExample: %s What is the capital of Canada?\n", argv[0]);
return 0;
}
// Initializing
char ai_response[BUF_SIZE];
char user_query[BUF_SIZE];
memset(ai_response, 0, BUF_SIZE);
memset(user_query, 0, BUF_SIZE);
// Get user query
for (int i = 1; i < argc; i++) {
strcat(user_query, argv[i]);
strcat(user_query, " ");
}
// Start WebUI server
hiddenWindow = webui_new_window();
webui_set_hide(hiddenWindow, true);
webui_show_browser(hiddenWindow, html, ChromiumBased);
// Run HTTPS API
if (run_ai_query(user_query, ai_response)) {
printf("AI Response: %s\n", ai_response);
} else {
printf("Error:\n%s\n", ai_response);
}
// Exit
webui_exit();
webui_clean();
return 0;
}

View File

@ -35,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
@ -44,19 +44,19 @@ else
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
CONSOLE_APP :=
GUI_APP :=
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib" "$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).dylib"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).so" "$(WEBUI_LIB_NAME).so"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
@ -75,12 +75,12 @@ endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -97,13 +97,13 @@ endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)

View File

@ -21,18 +21,17 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
release:
@ -42,12 +41,12 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -50,9 +50,9 @@ int main() {
// Bind HTML elements with C functions
webui_bind(window, "my_backend_func", my_backend_func);
// Set web server network port WebUI should use
// this mean `webui.js` will be available at:
// http://localhost:8081/webui.js
// Set the web-server/WebSocket port that WebUI should
// use. This means `webui.js` will be available at:
// http://localhost:MY_PORT_NUMBER/webui.js
webui_set_port(window, 8081);
// Show a new window and show our custom web server

View File

@ -0,0 +1,141 @@
# WebUI C Example
# == 1. VARIABLES =============================================================
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
WEBUI_LIB_NAME = webui-2-secure
endif
# ARGS
# Set a compiler when running on Linux via `make CC=gcc` / `make CC=clang`
CC = gcc
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
endif
# == 2.TARGETS ================================================================
all: release
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
release: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CC),gcc clang aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc musl-gcc),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix
--clean-macos: --clean-unix
--clean-unix:
- rm -f *.o
- rm -f *.a
- rm -f *.so
- rm -f *.dylib
- rm -rf *.dSYM
--clean-windows:
- del *.o >nul 2>&1
- del *.dll >nul 2>&1
- del *.a >nul 2>&1
- del *.exe >nul 2>&1

View File

@ -0,0 +1,64 @@
# WebUI C Example
# Windows - Microsoft Visual C
SHELL = CMD
LIB_DIR = ../../../dist
INCLUDE_DIR = ../../../include
WEBUI_LIB_NAME = webui-2
!IF "$(WEBUI_USE_TLS)" == "1"
WEBUI_LIB_NAME = webui-2-secure
!ENDIF
# Build the WebUI library if running `nmake BUILD_LIB=true`
BUILD_LIB =
all: release
debug:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE) debug
!ENDIF
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@echo Done.
release:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE)
!ENDIF
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
clean:
- del *.obj >nul 2>&1
- del *.ilk >nul 2>&1
- del *.pdb >nul 2>&1
- del *.exp >nul 2>&1
- del *.exe >nul 2>&1
- del *.lib >nul 2>&1

105
examples/C/frameless/main.c Normal file
View File

@ -0,0 +1,105 @@
// WebUI C - Frameless Example
#include "webui.h"
const char* html =
"<html>"
" <head>"
" <meta charset='UTF-8'>"
" <script src=\"webui.js\"></script>"
" <style>"
" * { margin: 0; padding: 0; box-sizing: border-box; }"
" html, body { height: 100%; width: 100%; overflow: hidden; background: transparent; }"
" #titlebar {"
" height: 40px;"
" background: linear-gradient(to right, #2c3e50, #34495e);"
" color: white;"
" display: flex;"
" align-items: center;"
" justify-content: space-between;"
" padding: 0 15px;"
" box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);"
" -webkit-app-region: drag;"
" font-family: Arial, sans-serif;"
" }"
" #title { font-size: 16px; font-weight: bold; }"
" #buttons { -webkit-app-region: no-drag; }"
" .button {"
" display: inline-block;"
" width: 24px;"
" height: 24px;"
" margin-left: 8px;"
" border-radius: 50%;"
" text-align: center;"
" line-height: 24px;"
" cursor: pointer;"
" transition: all 0.2s;"
" }"
" .minimize { background: #f1c40f; }"
" .maximize { background: #2ecc71; }"
" .close { background: #e74c3c; }"
" .button:hover { filter: brightness(120%); }"
" #content {"
" height: calc(100% - 40px);"
" background: rgba(0, 0, 0, 0.7);"
" display: flex;"
" align-items: center;"
" justify-content: center;"
" }"
" #message {"
" color: white;"
" font-size: 32px;"
" font-family: Arial, sans-serif;"
" text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);"
" }"
" </style>"
" </head>"
" <body>"
" <div id='titlebar'>"
" <span id='title'>WebUI Frameless Window</span>"
" <div id='buttons'>"
" <span class='button minimize' onclick='minimize()'></span>"
// " <span class='button maximize' onclick='maximize()'>□</span>"
" <span class='button close' onclick='close_win()'>✕</span>"
" </div>"
" </div>"
" <div id='content'>"
" <span id='message'>This is a WebUI frameless example</span>"
" </div>"
" </body>"
"</html>";
void minimize(webui_event_t* e) {
webui_minimize(e->window);
}
void maximize(webui_event_t* e) {
webui_maximize(e->window);
}
void close_win(webui_event_t* e) {
webui_close(e->window);
}
int main() {
size_t my_window = webui_new_window();
webui_bind(my_window, "minimize", minimize);
webui_bind(my_window, "maximize", maximize);
webui_bind(my_window, "close_win", close_win);
webui_set_size(my_window, 800, 600);
webui_set_frameless(my_window, true);
webui_set_transparent(my_window, true);
webui_set_resizable(my_window, false);
webui_set_center(my_window);
webui_show_wv(my_window, html);
webui_wait();
return 0;
}
#if defined(_MSC_VER)
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { return main(); }
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

View File

@ -35,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
@ -44,19 +44,19 @@ else
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
CONSOLE_APP :=
GUI_APP :=
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib" "$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).dylib"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).so" "$(WEBUI_LIB_NAME).so"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
@ -75,12 +75,12 @@ endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -97,13 +97,13 @@ endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)

View File

@ -21,18 +21,17 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
release:
@ -42,12 +41,12 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -0,0 +1,141 @@
# WebUI C Example
# == 1. VARIABLES =============================================================
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
WEBUI_LIB_NAME = webui-2-secure
endif
# ARGS
# Set a compiler when running on Linux via `make CC=gcc` / `make CC=clang`
CC = gcc
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
endif
# == 2.TARGETS ================================================================
all: release
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
release: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CC),gcc clang aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc musl-gcc),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix
--clean-macos: --clean-unix
--clean-unix:
- rm -f *.o
- rm -f *.a
- rm -f *.so
- rm -f *.dylib
- rm -rf *.dSYM
--clean-windows:
- del *.o >nul 2>&1
- del *.dll >nul 2>&1
- del *.a >nul 2>&1
- del *.exe >nul 2>&1

View File

@ -0,0 +1,64 @@
# WebUI C Example
# Windows - Microsoft Visual C
SHELL = CMD
LIB_DIR = ../../../dist
INCLUDE_DIR = ../../../include
WEBUI_LIB_NAME = webui-2
!IF "$(WEBUI_USE_TLS)" == "1"
WEBUI_LIB_NAME = webui-2-secure
!ENDIF
# Build the WebUI library if running `nmake BUILD_LIB=true`
BUILD_LIB =
all: release
debug:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE) debug
!ENDIF
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@echo Done.
release:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE)
!ENDIF
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
clean:
- del *.obj >nul 2>&1
- del *.ilk >nul 2>&1
- del *.pdb >nul 2>&1
- del *.exp >nul 2>&1
- del *.exe >nul 2>&1
- del *.lib >nul 2>&1

View File

@ -0,0 +1,126 @@
// Public Network Access Example
#include "webui.h"
// Windows
size_t private_window = 0;
size_t public_window = 0;
void app_exit(webui_event_t* e) {
webui_exit();
}
void public_window_events(webui_event_t* e) {
if (e->event_type == WEBUI_EVENT_CONNECTED) {
// New connection
webui_run(private_window, "document.getElementById(\"Logs\").value += \"New connection.\\n\";");
}
else if (e->event_type == WEBUI_EVENT_DISCONNECTED) {
// Disconnection
webui_run(private_window, "document.getElementById(\"Logs\").value += \"Disconnected.\\n\";");
}
}
void private_window_events(webui_event_t* e) {
if (e->event_type == WEBUI_EVENT_CONNECTED) {
// Get URL of public window
const char* public_win_url = webui_get_url(public_window);
char javascript[1024];
sprintf(javascript, "document.getElementById('urlSpan').innerHTML = '%s';", public_win_url);
webui_run(private_window, javascript);
}
}
int main() {
// Main Private Window HTML
const char* private_html = "<!DOCTYPE html>"
"<html>"
" <head>"
" <meta charset=\"UTF-8\">"
" <script src=\"webui.js\"></script>"
" <title>Public Network Access Example</title>"
" <style>"
" body {"
" font-family: 'Arial', sans-serif;"
" color: white;"
" background: linear-gradient(to right, #507d91, #1c596f, #022737);"
" text-align: center;"
" font-size: 18px;"
" }"
" button, input {"
" padding: 10px;"
" margin: 10px;"
" border-radius: 3px;"
" border: 1px solid #ccc;"
" box-shadow: 0 3px 5px rgba(0,0,0,0.1);"
" transition: 0.2s;"
" }"
" button {"
" background: #3498db;"
" color: #fff; "
" cursor: pointer;"
" font-size: 16px;"
" }"
" h1 { text-shadow: -7px 10px 7px rgb(67 57 57 / 76%); }"
" button:hover { background: #c9913d; }"
" input:focus { outline: none; border-color: #3498db; }"
" </style>"
" </head>"
" <body>"
" <h1>WebUI - Public Network Access Example</h1>"
" <br>"
" The second public window is configured to be accessible from <br>"
" any device in the public network. <br>"
" <br>"
" Second public window link: <br>"
" <h1 id=\"urlSpan\" style=\"color:#c9913d\">...</h1>"
" Second public window events: <br>"
" <textarea id=\"Logs\" rows=\"4\" cols=\"50\" style=\"width:80%\"></textarea>"
" <br>"
" <button id=\"Exit\">Exit</button>"
" </body>"
"</html>";
// Public Window HTML
const char* public_html = "<!DOCTYPE html>"
"<html>"
" <head>"
" <meta charset=\"UTF-8\">"
" <script src=\"webui.js\"></script>"
" <title>Welcome to Public UI</title>"
" </head>"
" <body>"
" <h1>Welcome to Public UI!</h1>"
" </body>"
"</html>";
// Create windows
private_window = webui_new_window();
public_window = webui_new_window();
// App
webui_set_timeout(0); // Wait forever (never timeout)
// Public Window
webui_set_public(public_window, true); // Make URL accessible from public networks
webui_bind(public_window, "", public_window_events); // Bind all events
webui_show_browser(public_window, public_html, NoBrowser); // Set public window HTML
// Private Window
webui_bind(private_window, "", private_window_events); // Run JS
webui_bind(private_window, "Exit", app_exit); // Bind exit button
webui_show(private_window, private_html); // Show the window
// Wait until all windows get closed
webui_wait();
// Free all memory resources (Optional)
webui_clean();
return 0;
}
#if defined(_MSC_VER)
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { return main(); }
#endif

View File

@ -0,0 +1,141 @@
# WebUI C Example
# == 1. VARIABLES =============================================================
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
WEBUI_LIB_NAME = webui-2-secure
endif
# ARGS
# Set a compiler when running on Linux via `make CC=gcc` / `make CC=clang`
CC = gcc
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
endif
# == 2.TARGETS ================================================================
all: release
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
release: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CC),gcc clang aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc musl-gcc),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix
--clean-macos: --clean-unix
--clean-unix:
- rm -f *.o
- rm -f *.a
- rm -f *.so
- rm -f *.dylib
- rm -rf *.dSYM
--clean-windows:
- del *.o >nul 2>&1
- del *.dll >nul 2>&1
- del *.a >nul 2>&1
- del *.exe >nul 2>&1

64
examples/C/react/Makefile Normal file
View File

@ -0,0 +1,64 @@
# WebUI C Example
# Windows - Microsoft Visual C
SHELL = CMD
LIB_DIR = ../../../dist
INCLUDE_DIR = ../../../include
WEBUI_LIB_NAME = webui-2
!IF "$(WEBUI_USE_TLS)" == "1"
WEBUI_LIB_NAME = webui-2-secure
!ENDIF
# Build the WebUI library if running `nmake BUILD_LIB=true`
BUILD_LIB =
all: release
debug:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE) debug
!ENDIF
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@echo Done.
release:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE)
!ENDIF
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
clean:
- del *.obj >nul 2>&1
- del *.ilk >nul 2>&1
- del *.pdb >nul 2>&1
- del *.exp >nul 2>&1
- del *.exe >nul 2>&1
- del *.lib >nul 2>&1

View File

@ -0,0 +1,22 @@
## React WebUI Example
This is a basic example of how to use WebUI with React to generate a portable single executable program. WebUI will run the internal web server and use any installed web browser as GUI to show the React UI.
A simple Python script `vfs.py` is used to generate `vfs.h` to embed the whole react's build folder into the portable single executable program.
![Screenshot](webui_react.png)
### How to use it?
1. Run script `build_react` to re-build the React project and compile the C file
### How to create a React WebUI project from scratch?
1. Run `npx create-react-app my-react-app` to create a React app using NPM
2. Add `<script src="webui.js"></script>` into `public/index.html` to connect UI with the backend
3. Run `python vfs.py "./my-react-app/build" "vfs.h"` to embed the build folder
4. Now, use any C compiler to compile `main.c` into a portable executable program
### Other backend languages examples:
- Coming soon...

View File

@ -0,0 +1,19 @@
@echo off
echo.
echo * Build React project...
cd webui-react-example
call npm install
call npm run build
cd ..
echo.
echo * Embedding React's build files into 'vfs.h'
python vfs.py "./webui-react-example/build" "vfs.h"
echo.
echo * Compiling 'main.c' into 'main.exe' using Microsoft Visual Studio...
nmake

View File

@ -0,0 +1,19 @@
#!/bin/bash
echo
echo "* Build React project..."
cd webui-react-example
npm install || exit
npm run build || exit
cd ..
echo
echo "* Embedding React's build files into 'vfs.h'"
python3 vfs.py "./webui-react-example/build" "vfs.h"
echo
echo "* Compiling 'main.c' into 'main' using GCC..."
make

59
examples/C/react/main.c Normal file
View File

@ -0,0 +1,59 @@
// React Example
#include "webui.h"
#include "vfs.h"
void exit_app(webui_event_t* e) {
webui_exit();
}
int main() {
// Create new windows
size_t react_window = webui_new_window();
// Set window size
webui_set_size(react_window, 550, 450);
// Set window position
webui_set_position(react_window, 250, 250);
// Allow multi-user connection to WebUI window
webui_set_config(multi_client, true);
// Disable WebUI's cookies
webui_set_config(use_cookies, false);
// Bind React HTML element IDs with a C functions
webui_bind(react_window, "Exit", exit_app);
// VSF (Virtual File System) Example
//
// 1. Run Python script to generate header file of a folder
// python vfs.py "/path/to/folder" "vfs.h"
//
// 2. Include header file in your C project
// #include "vfs.h"
//
// 3. use vfs in your custom files handler `webui_set_file_handler()`
// webui_set_file_handler(react_window, vfs);
// Set a custom files handler
webui_set_file_handler(react_window, vfs);
// Show the React window
// webui_show_browser(react_window, "index.html", Chrome);
webui_show(react_window, "index.html");
// Wait until all windows get closed
webui_wait();
// Free all memory resources (Optional)
webui_clean();
return 0;
}
#if defined(_MSC_VER)
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { return main(); }
#endif

142
examples/C/react/vfs.h Normal file

File diff suppressed because one or more lines are too long

117
examples/C/react/vfs.py Normal file
View File

@ -0,0 +1,117 @@
import os
import sys
def generate_vfs_header(directory, output_header):
files = []
index_files = {}
for root, _, filenames in os.walk(directory):
for filename in filenames:
filepath = os.path.join(root, filename)
relative_path = os.path.relpath(filepath, directory)
# Ensure path starts with a slash
relative_path = '/' + relative_path.replace('\\', '/')
files.append((relative_path, filepath))
# Check for index files
if filename.startswith("index."):
dir_path = os.path.dirname(relative_path)
if dir_path not in index_files:
index_files[dir_path] = relative_path
with open(output_header, 'w') as header:
header.write('#ifndef VIRTUAL_FILE_SYSTEM_H\n')
header.write('#define VIRTUAL_FILE_SYSTEM_H\n\n')
header.write('typedef struct {\n')
header.write(' const char *path;\n')
header.write(' const unsigned char *data;\n')
header.write(' int length;\n')
header.write('} VirtualFile;\n\n')
header.write('static const VirtualFile virtual_files[] = {\n')
for relative_path, filepath in files:
with open(filepath, 'rb') as f:
data = f.read()
header.write(' {\n')
header.write(f' "{relative_path}",\n')
header.write(' (const unsigned char[]){')
header.write(','.join(f'0x{byte:02x}' for byte in data))
header.write('},\n')
header.write(f' {len(data)}\n')
header.write(' },\n')
header.write('};\n\n')
header.write('static const int virtual_files_count = sizeof(virtual_files) / sizeof(virtual_files[0]);\n\n')
header.write('static const char* index_files[] = {\n')
for dir_path, index_path in index_files.items():
header.write(f' "{dir_path}/", "{index_path}",\n')
header.write(' NULL\n')
header.write('};\n\n')
header.write('bool virtual_file_system(const char* path, const unsigned char** file, int* length) {\n')
header.write(' for (int i = 0; i < virtual_files_count; ++i) {\n')
header.write(' if (strcmp(virtual_files[i].path, path) == 0) {\n')
header.write(' *file = virtual_files[i].data;\n')
header.write(' *length = virtual_files[i].length;\n')
header.write(' return true;\n')
header.write(' }\n')
header.write(' }\n')
header.write(' return false;\n')
header.write('}\n\n')
header.write('const void* vfs(const char* path, int* length) {\n')
header.write(' const unsigned char* file_data;\n')
header.write(' int file_length;\n\n')
header.write(' if (virtual_file_system(path, &file_data, &file_length)) {\n')
header.write(' const char* content_type = webui_get_mime_type(path);\n')
header.write(' const char* http_header_template = "HTTP/1.1 200 OK\\r\\n"\n')
header.write(' "Content-Type: %s\\r\\n"\n')
header.write(' "Content-Length: %d\\r\\n"\n')
header.write(' "Cache-Control: no-cache\\r\\n\\r\\n";\n')
header.write(' int header_length = snprintf(NULL, 0, http_header_template, content_type, file_length);\n')
header.write(' *length = header_length + file_length;\n')
header.write(' unsigned char* response = (unsigned char*) webui_malloc(*length);\n')
header.write(' snprintf((char*) response, header_length + 1, http_header_template, content_type, file_length);\n')
header.write(' memcpy(response + header_length, file_data, file_length);\n')
header.write(' return response;\n')
header.write(' } else {\n')
header.write(' // Check for index file redirection\n')
header.write(' char redirect_path[1024];\n')
header.write(' snprintf(redirect_path, sizeof(redirect_path), "%s", path);\n')
header.write(' size_t len = strlen(redirect_path);\n')
header.write(' if (redirect_path[len - 1] != \'/\') {\n')
header.write(' redirect_path[len] = \'/\';\n')
header.write(' redirect_path[len + 1] = \'\\0\';\n')
header.write(' }\n')
header.write(' for (int i = 0; index_files[i] != NULL; i += 2) {\n')
header.write(' if (strcmp(index_files[i], redirect_path) == 0) {\n')
header.write(' const char* location_header = "HTTP/1.1 302 Found\\r\\n"\n')
header.write(' "Location: %s\\r\\n"\n')
header.write(' "Cache-Control: no-cache\\r\\n\\r\\n";\n')
header.write(' int header_length = snprintf(NULL, 0, location_header, index_files[i + 1]);\n')
header.write(' *length = header_length;\n')
header.write(' unsigned char* response = (unsigned char*) webui_malloc(*length);\n')
header.write(' snprintf((char*) response, header_length + 1, location_header, index_files[i + 1]);\n')
header.write(' return response;\n')
header.write(' }\n')
header.write(' }\n')
header.write(' return NULL;\n')
header.write(' }\n')
header.write('}\n\n')
header.write('#endif // VIRTUAL_FILE_SYSTEM_H\n')
if __name__ == '__main__':
if len(sys.argv) != 3:
print(f'Usage: {sys.argv[0]} <directory> <output_header>')
sys.exit(1)
directory = sys.argv[1]
output_header = sys.argv[2]
generate_vfs_header(directory, output_header)
print(f'Generated {output_header} from {directory}')

View File

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
{
"name": "webui-react-example",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>WebUI React</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<!-- WebUI Script (Virtual File) -->
<script src="webui.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -0,0 +1,38 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@ -0,0 +1,75 @@
import React, { useState } from "react";
const App = () => {
const [value1, setValue1] = useState('');
const [value2, setValue2] = useState('');
const [result, setResult] = useState(null);
const calculateSum = () => {
const sum = parseFloat(value1 || 0) + parseFloat(value2 || 0);
setResult(sum);
};
return (
<div style={{ margin: '20px', fontFamily: 'Arial, sans-serif' }}>
<img src="logo192.png" width="64" height="64"></img>
<h2>WebUI React Example</h2>
<div style={{ marginBottom: '10px' }}>
<label>
<strong>Input 1:</strong>
</label>
<input
type="number"
value={value1}
onChange={(e) => setValue1(e.target.value)}
style={{ marginLeft: '10px', padding: '5px', fontSize: '16px' }}
/>
</div>
<div style={{ marginBottom: '10px' }}>
<label>
<strong>Input 2:</strong>
</label>
<input
type="number"
value={value2}
onChange={(e) => setValue2(e.target.value)}
style={{ marginLeft: '10px', padding: '5px', fontSize: '16px' }}
/>
</div>
<button
onClick={calculateSum}
style={{
padding: '10px 20px',
backgroundColor: '#4CAF50',
color: 'white',
fontSize: '16px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
marginRight: '10px',
}}
>
Calculate (React Frontend)
</button>
<button
id="Exit"
style={{
padding: '10px 20px',
backgroundColor: '#f44336',
color: 'white',
fontSize: '16px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
}}
>
Exit (WebUI Backend)
</button>
<div style={{ marginTop: '20px', fontSize: '18px' }}>
<strong>Result:</strong> {result !== null ? result : 'N/A'}
</div>
</div>
);
};
export default App;

View File

@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@ -0,0 +1,16 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #5ed2f2;
background-color: #2a2c2e;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

View File

@ -0,0 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@ -0,0 +1,5 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -35,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
@ -44,19 +44,19 @@ else
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
CONSOLE_APP :=
GUI_APP :=
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib" "$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).dylib"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).so" "$(WEBUI_LIB_NAME).so"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
@ -75,12 +75,12 @@ endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -97,13 +97,13 @@ endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)

View File

@ -21,18 +21,17 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
release:
@ -42,12 +41,12 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -0,0 +1,26 @@
// This file gets called like follow:
//
// 1. UI `Index.html` request:
// `http://localhost:xxx/bun_test.ts?foo=123&bar=456`
//
// 2. WebUI runs command:
// `bun run "bun_test.ts" "foo=123&bar=456"`
//
// 3. Bun parses args and prints the response
// Get Query (HTTP GET)
const args = process.argv.slice(2);
const query = args[0];
// Variables
let foo: string = '';
let bar: string = '';
// Read Query
const params = new URLSearchParams(query);
for (const [key, value] of params.entries()) {
if (key === 'foo') foo = value; // 123
else if (key === 'bar') bar = value; // 456
}
console.log('Response from Bun: ' + (parseInt(foo) + parseInt(bar))); // 579

View File

@ -1,7 +1,12 @@
// This file gets called like follow:
// `Index.html` ->
// `http://localhost:xxx/deno_test.ts?foo=123&bar=456` ->
// `deno run --allow-all --unstable "deno_test.ts" "foo=123&bar=456"`
//
// 1. UI `Index.html` request:
// `http://localhost:xxx/deno_test.ts?foo=123&bar=456`
//
// 2. WebUI runs command:
// `deno run --allow-all --unstable "deno_test.ts" "foo=123&bar=456"`
//
// 3. Deno parse args and print the response
// Import parse()
import { parse } from 'https://deno.land/std/flags/mod.ts';
@ -21,4 +26,4 @@ for (const [key, value] of params.entries()) {
else if (key == 'bar') bar = value; // 456
}
console.error('foo + bar = ' + (parseInt(foo) + parseInt(bar))); // 579
console.log('Response from Deno: ' + (parseInt(foo) + parseInt(bar))); // 579

View File

@ -66,7 +66,13 @@
By a simple HTTP request "deno_test.ts?foo=60&bar=40"
<br />
<br />
<button OnClick="call_deno_file();">deno_test.ts (Local file)</button>
<button OnClick="call_deno_file();">Deno_test.ts (Local file)</button>
<br />
<br />
<button OnClick="call_bun_file();">Bun_test.ts (Local file)</button>
<br />
<br />
<button OnClick="call_nodejs_file();">Nodejs_test.ts (Local file)</button>
<br />
<h4><a href="second.html">Second Page As A Simple Link (Local file)</a></h4>
<br />
@ -79,29 +85,109 @@
<h4><a href="dynamic.html">Dynamic file example (Embedded)</a></h4>
<p>
Unicode Test:<br /><br />
مرحبًا<br />
<!-- Arabic -->
你好<br />
<!-- Chinese -->
こんにちは
<!-- Japanese -->
مرحبًا<br /> <!-- Arabic -->
你好<br /> <!-- Chinese -->
こんにちは <!-- Japanese -->
</p>
</body>
<!-- Connect this window to the background app -->
<script src="webui.js"></script>
<script src="/webui.js"></script>
<script>
function call_deno_file() {
// Because `main.c` set Deno as the `.ts` and `.js` interpreter
// then a simple HTTP request to `/deno_test.ts` will be parsed
// of course Deno should be installed.
function call_deno_file() {
// Note:
// You need to set Deno as default runtime in the backend
// Simple HTTP Request
var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET', 'deno_test.ts?foo=60&bar=40', false);
xmlHttp.open('GET', 'deno_test.ts?foo=123&bar=456', false);
xmlHttp.send(null);
alert(xmlHttp.responseText);
}
function call_bun_file() {
// Note:
// You need to set Bun as default runtime in the backend
// Simple HTTP Request
var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET', 'bun_test.ts?foo=123&bar=456', false);
xmlHttp.send(null);
alert(xmlHttp.responseText);
}
function call_nodejs_file() {
// Note:
// You need to set Nodejs as default runtime in the backend
// Simple HTTP Request
var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET', 'node_test.js?foo=123&bar=456', false);
xmlHttp.send(null);
alert(xmlHttp.responseText);
}
// JavaScript Example
/*
document.addEventListener('DOMContentLoaded', function() {
// DOM is loaded. Check if `webui` object is available
if (typeof webui !== 'undefined') {
// Set events callback
webui.setEventCallback((e) => {
if (e == webui.event.CONNECTED) {
// Connection to the backend is established
console.log('Connected.');
webuiTest();
} else if (e == webui.event.DISCONNECTED) {
// Connection to the backend is lost
console.log('Disconnected.');
}
});
} else {
// The virtual file `webui.js` is not included
alert('Please add webui.js to your HTML.');
}
});
function webuiTest() {
// Call a backend function
if (webui.isConnected()) {
// When you bind a func in the backend
// webui will create the `func` object
// in three places:
//
// Global : func(...)
// Property : webui.func(...)
// Method : webui.call('func', ...)
//
// [!] Note: Objects creation fails when
// a similar object already exist.
const foo = 'Hello';
const bar = 123456;
// Calling as global object
myBackendFunction(foo, bar).then((response) => {
// Do something with `response`
});
// Calling as property of `webui.` object
webui.myBackendFunction(foo, bar).then((response) => {
// Do something with `response`
});
// Calling using the method `webui.call()`
webui.call('myBackendFunction', foo, bar).then((response) => {
// Do something with `response`
});
// Using await
// const response = await myBackendFunction(foo, bar);
// const response = await webui.myBackendFunction(foo, bar);
// const response = await webui.call('myBackendFunction', foo, bar);
}
}
*/
</script>
</html>

View File

@ -10,133 +10,155 @@
void exit_app(webui_event_t* e) {
// Close all opened windows
webui_exit();
// Close all opened windows
webui_exit();
}
void events(webui_event_t* e) {
// This function gets called every time
// there is an event
// This function gets called every time
// there is an event
if (e->event_type == WEBUI_EVENT_CONNECTED)
printf("Connected. \n");
else if (e->event_type == WEBUI_EVENT_DISCONNECTED)
printf("Disconnected. \n");
else if (e->event_type == WEBUI_EVENT_MOUSE_CLICK)
printf("Click. \n");
else if (e->event_type == WEBUI_EVENT_NAVIGATION) {
const char* url = webui_get_string(e);
printf("Starting navigation to: %s \n", url);
if (e->event_type == WEBUI_EVENT_CONNECTED)
printf("Connected. \n");
else if (e->event_type == WEBUI_EVENT_DISCONNECTED)
printf("Disconnected. \n");
else if (e->event_type == WEBUI_EVENT_MOUSE_CLICK)
printf("Click. \n");
else if (e->event_type == WEBUI_EVENT_NAVIGATION) {
const char* url = webui_get_string(e);
printf("Starting navigation to: %s \n", url);
// Because we used `webui_bind(MyWindow, "", events);`
// WebUI will block all `href` link clicks and sent here instead.
// We can then control the behaviour of links as needed.
webui_navigate(e->window, url);
}
// Because we used `webui_bind(MyWindow, "", events);`
// WebUI will block all `href` link clicks and sent here instead.
// We can then control the behaviour of links as needed.
webui_navigate(e->window, url);
}
}
void switch_to_second_page(webui_event_t* e) {
// This function gets called every
// time the user clicks on "SwitchToSecondPage"
// This function gets called every
// time the user clicks on "SwitchToSecondPage"
// Switch to `/second.html` in the same opened window.
webui_show(e->window, "second.html");
// Switch to `/second.html` in the same opened window.
webui_show(e->window, "second.html");
}
void show_second_window(webui_event_t* e) {
// This function gets called every
// time the user clicks on "OpenNewWindow"
// This function gets called every
// time the user clicks on "OpenNewWindow"
// Show a new window, and navigate to `/second.html`
// if it's already open, then switch in the same window
webui_show(MySecondWindow, "second.html");
// Show a new window, and navigate to `/second.html`
// if it's already open, then switch in the same window
webui_show(MySecondWindow, "second.html");
}
const void* my_files_handler(const char* filename, int* length) {
printf("File: %s \n", filename);
printf("File: %s \n", filename);
if (!strcmp(filename, "/test.txt")) {
if (!strcmp(filename, "/test.txt")) {
// Const static file example
// Note: The connection will drop if the content
// does not have `<script src="webui.js"></script>`
return "This is a embedded file content example.";
} else if (!strcmp(filename, "/dynamic.html")) {
// Const static file example
return "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 99\r\n\r\n"
"<html>"
" This is a static embedded file content example."
" <script src=\"webui.js\"></script>" // To keep connection with WebUI
"</html>";
}
else if (!strcmp(filename, "/dynamic.html")) {
// Dynamic file example
// Dynamic file example
// Allocate memory
char* dynamic_content = webui_malloc(1024);
// Allocate memory
char* body = webui_malloc(1024);
char* header_and_body = webui_malloc(1024);
// Generate content
static int count = 0;
sprintf(
dynamic_content,
"<html>"
" This is a dynamic file content example. <br>"
" Count: %d <a href=\"dynamic.html\">[Refresh]</a><br>"
" <script src=\"webui.js\"></script>" // To keep connection with WebUI
"</html>",
++count
);
// Generate body
static int count = 0;
sprintf(
body,
"<html>"
" This is a dynamic file content example. <br>"
" Count: %d <a href=\"dynamic.html\">[Refresh]</a><br>"
" <script src=\"webui.js\"></script>" // To keep connection with WebUI
"</html>",
++count
);
// Set len (optional)
*length = strlen(dynamic_content);
// Generate header + body
int body_size = strlen(body);
sprintf(
header_and_body,
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %d\r\n\r\n"
"%s",
body_size, body
);
// Free body buffer
webui_free(body);
// By allocating resources using webui_malloc()
// WebUI will automaticaly free the resources.
return dynamic_content;
}
// Set len (optional)
*length = strlen(header_and_body);
// Other files:
// A NULL return will make WebUI
// looks for the file locally.
return NULL;
// By allocating resources using webui_malloc()
// WebUI will automaticaly free the resources.
return header_and_body;
}
// Other files:
// A NULL return will make WebUI
// looks for the file locally.
return NULL;
}
int main() {
// Create new windows
webui_new_window_id(MyWindow);
webui_new_window_id(MySecondWindow);
// Create new windows
webui_new_window_id(MyWindow);
webui_new_window_id(MySecondWindow);
// Bind HTML element IDs with a C functions
webui_bind(MyWindow, "SwitchToSecondPage", switch_to_second_page);
webui_bind(MyWindow, "OpenNewWindow", show_second_window);
webui_bind(MyWindow, "Exit", exit_app);
webui_bind(MySecondWindow, "Exit", exit_app);
// Bind HTML element IDs with a C functions
webui_bind(MyWindow, "SwitchToSecondPage", switch_to_second_page);
webui_bind(MyWindow, "OpenNewWindow", show_second_window);
webui_bind(MyWindow, "Exit", exit_app);
webui_bind(MySecondWindow, "Exit", exit_app);
// Bind events
webui_bind(MyWindow, "", events);
// Bind events
webui_bind(MyWindow, "", events);
// Make Deno as the `.ts` and `.js` interpreter
webui_set_runtime(MyWindow, Deno);
// Set the `.ts` and `.js` runtime
// webui_set_runtime(MyWindow, NodeJS);
// webui_set_runtime(MyWindow, Bun);
webui_set_runtime(MyWindow, Deno);
// Set a custom files handler
webui_set_file_handler(MyWindow, my_files_handler);
// Set a custom files handler
webui_set_file_handler(MyWindow, my_files_handler);
// Set window size
webui_set_size(MyWindow, 800, 800);
// Set window size
webui_set_size(MyWindow, 800, 800);
// Set window position
webui_set_position(MyWindow, 200, 200);
// Set window position
webui_set_position(MyWindow, 200, 200);
// Show a new window
// webui_set_root_folder(MyWindow, "_MY_PATH_HERE_");
// webui_show_browser(MyWindow, "index.html", Chrome);
webui_show(MyWindow, "index.html");
// Show a new window
// webui_set_root_folder(MyWindow, "_MY_PATH_HERE_");
// webui_show_browser(MyWindow, "index.html", Chrome);
webui_show(MyWindow, "index.html");
// Wait until all windows get closed
webui_wait();
// Wait until all windows get closed
webui_wait();
// Free all memory resources (Optional)
webui_clean();
// Free all memory resources (Optional)
webui_clean();
return 0;
return 0;
}
#if defined(_MSC_VER)

View File

@ -0,0 +1,26 @@
// This file gets called like follow:
//
// 1. UI `Index.html` request:
// `http://localhost:xxx/node_test.js?foo=123&bar=456`
//
// 2. WebUI runs command:
// `node node_test.js "foo=123&bar=456"`
//
// 3. Node.js parses args and prints the response
// Get Query (HTTP GET)
const args = process.argv.slice(2);
const query = args[0];
// Variables
let foo = '';
let bar = '';
// Read Query
const params = new URLSearchParams(query);
for (const [key, value] of params.entries()) {
if (key === 'foo') foo = value; // 123
else if (key === 'bar') bar = value; // 456
}
console.log('Response from Node.js: ' + (parseInt(foo) + parseInt(bar))); // 579

View File

@ -44,5 +44,5 @@
</body>
<!-- Connect this window to the background app -->
<script src="webui.js"></script>
<script src="/webui.js"></script>
</html>

View File

@ -35,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
@ -44,19 +44,19 @@ else
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
CONSOLE_APP :=
GUI_APP :=
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).dylib" "$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).dylib"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/$(WEBUI_LIB_NAME).so" "$(WEBUI_LIB_NAME).so"
DYN_BUILD_FLAGS += "./$(WEBUI_LIB_NAME).so"
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
@ -75,12 +75,12 @@ endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
@ -97,13 +97,13 @@ endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) -o $(STATIC_OUT)
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) -o $(DYN_OUT)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)

View File

@ -21,18 +21,17 @@ debug:
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /MACHINE:X64 /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
release:
@ -42,12 +41,12 @@ release:
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib /OUT:main.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /MACHINE:X64 /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib /OUT:main-dyn.exe 1>NUL 2>&1
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1

View File

@ -2,7 +2,7 @@
#include "webui.h"
void Close(webui_event_t* e) {
void close_app(webui_event_t* e) {
printf("Exit.\n");
// Close all opened windows
@ -18,10 +18,10 @@ int main() {
webui_set_root_folder(MainWindow, "ui");
// Bind HTML elements with the specified ID to C functions
webui_bind(MainWindow, "__close-btn", Close);
webui_bind(MainWindow, "close_app", close_app);
// Show the window, preferably in a chromium based browser
if (!webui_show_browser(MainWindow, "index.html", ChromiumBased))
if (!webui_show_browser(MainWindow, "index.html", AnyBrowser))
webui_show(MainWindow, "index.html");
// Wait until all windows get closed

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,7 @@
<nav>
<button id="open-btn" title="Open file" type="button"><i class="fas fa-folder-open"></i></button>
<button id="save-btn" title="Save file" type="button" disabled><i class="fa fa-floppy-disk"></i></button>
<button id="__close-btn" title="Close file" type="button"><i class="fas fa-circle-xmark"></i></button>
<button id="close_app" title="Close file" type="button"><i class="fas fa-circle-xmark"></i></button>
<button id="about-btn" title="About Info" type="button"><i class="fas fa-question-circle"></i></button>
</nav>
<div class="main" id="main">
@ -27,7 +27,7 @@
<h1>WebUI Text Editor</h1>
v1.1
<p>Example of a text editor software in C using WebUI library.</p>
<p><a href="https://webui.me" target="_blank">webui.me</a> | (C)2023 Hassan Draga</p>
<p><a href="https://webui.me" target="_blank">webui.me</a> | (C)2025 Hassan Draga</p>
</div>
</div>
<script src="js/codemirror.min.js"></script>

View File

@ -0,0 +1,141 @@
# WebUI C Example
# == 1. VARIABLES =============================================================
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
TARGET := $(firstword $(MAKECMDGOALS))
LIB_DIR := $(PROJECT_DIR)/dist
ifeq ($(TARGET), debug)
LIB_DIR := $(LIB_DIR)/debug
endif
INCLUDE_DIR := $(PROJECT_DIR)/include
WEBUI_LIB_NAME = webui-2
ifeq ($(WEBUI_USE_TLS), 1)
WEBUI_LIB_NAME = webui-2-secure
endif
# ARGS
# Set a compiler when running on Linux via `make CC=gcc` / `make CC=clang`
CC = gcc
# Build the WebUI library if running via `make BUILD_LIB=true`
BUILD_LIB ?=
# BUILD FLAGS
STATIC_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
DYN_BUILD_FLAGS = main.c -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
# Platform conditions
ifeq ($(OS),Windows_NT)
# Windows
PLATFORM := windows
SHELL := CMD
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -static
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32
STATIC_OUT := main.exe
DYN_OUT := main-dyn.exe
LWS2_OPT := -lws2_32 -lole32
STRIP_OPT := --strip-all
CONSOLE_APP := -Wl,-subsystem=console
GUI_APP := -Wl,-subsystem=windows
else
STATIC_BUILD_FLAGS += -lpthread -lm -l$(WEBUI_LIB_NAME)-static
DYN_BUILD_FLAGS += -lpthread -lm
STATIC_OUT := main
DYN_OUT := main-dyn
ifeq ($(shell uname),Darwin)
# MacOS
PLATFORM := macos
CC = clang
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
else
# Linux
PLATFORM := linux
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
STATIC_BUILD_FLAGS += -ldl
DYN_BUILD_FLAGS += -ldl -l$(WEBUI_LIB_NAME)
STRIP_OPT := --strip-all
ifeq ($(CC),clang)
LLVM_OPT := llvm-
endif
endif
endif
# == 2.TARGETS ================================================================
all: release
debug: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE) debug
endif
# Static with Debug info
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) debug static)..."
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
endif
# Dynamic with Debug info
@echo "Build C Example ($(CC) debug dynamic)..."
$(COPY_LIB_CMD)
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
release: --validate-args
ifeq ($(BUILD_LIB),true)
@cd "$(PROJECT_DIR)" && $(MAKE)
endif
# Static Release
ifneq ($(WEBUI_USE_TLS), 1)
@echo "Build C Example ($(CC) release static)..."
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
endif
# Dynamic Release
@echo "Build C Example ($(CC) release dynamic)..."
$(COPY_LIB_CMD)
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
# Clean
ifeq ($(PLATFORM),windows)
@- del *.o >nul 2>&1
else
@- rm -f *.o
@- rm -rf *.dSYM # macOS
endif
@echo "Done."
clean: --clean-$(PLATFORM)
# INTERNAL TARGETS
--validate-args:
ifneq ($(filter $(CC),gcc clang aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc musl-gcc),$(CC))
$(error Invalid compiler specified: `$(CC)`)
endif
--clean-linux: --clean-unix
--clean-macos: --clean-unix
--clean-unix:
- rm -f *.o
- rm -f *.a
- rm -f *.so
- rm -f *.dylib
- rm -rf *.dSYM
--clean-windows:
- del *.o >nul 2>&1
- del *.dll >nul 2>&1
- del *.a >nul 2>&1
- del *.exe >nul 2>&1

View File

@ -0,0 +1,64 @@
# WebUI C Example
# Windows - Microsoft Visual C
SHELL = CMD
LIB_DIR = ../../../dist
INCLUDE_DIR = ../../../include
WEBUI_LIB_NAME = webui-2
!IF "$(WEBUI_USE_TLS)" == "1"
WEBUI_LIB_NAME = webui-2-secure
!ENDIF
# Build the WebUI library if running `nmake BUILD_LIB=true`
BUILD_LIB =
all: release
debug:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE) debug
!ENDIF
# Static with Debug info
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Debug)...
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic with Debug info
@echo Build C Example (Dynamic Debug)...
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl /Zi main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)\debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@echo Done.
release:
!IF "$(BUILD_LIB)" == "true"
@cd "$(LIB_DIR)" && cd .. && $(MAKE)
!ENDIF
# Static Release
!IF "$(WEBUI_USE_TLS)" != "1"
@echo Build C Example (Static Release)...
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
!ENDIF
# Dynamic Release
@echo Build C Example (Dynamic Release)...
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
@cl main.c /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
# Clean
@- del *.exp >nul 2>&1
@- del *.ilk >nul 2>&1
@- del *.lib >nul 2>&1
@- del *.obj >nul 2>&1
@- del *.pdb >nul 2>&1
@echo Done.
clean:
- del *.obj >nul 2>&1
- del *.ilk >nul 2>&1
- del *.pdb >nul 2>&1
- del *.exp >nul 2>&1
- del *.exe >nul 2>&1
- del *.lib >nul 2>&1

View File

@ -0,0 +1,47 @@
// Virtual File System Example
#include "webui.h"
#include "vfs.h"
void exit_app(webui_event_t* e) {
webui_exit();
}
int main() {
// Create new windows
size_t MyWindow = webui_new_window();
// Bind HTML element IDs with a C functions
webui_bind(MyWindow, "Exit", exit_app);
// VSF (Virtual File System) Example
//
// 1. Run Python script to generate header file of a folder
// python vfs.py "/path/to/folder" "vfs.h"
//
// 2. Include header file in your C project
// #include "vfs.h"
//
// 3. use vfs in your custom files handler `webui_set_file_handler()`
// webui_set_file_handler(MyWindow, vfs);
// Set a custom files handler
webui_set_file_handler(MyWindow, vfs);
// Show a new window
// webui_show_browser(MyWindow, "index.html", Chrome);
webui_show(MyWindow, "index.html");
// Wait until all windows get closed
webui_wait();
// Free all memory resources (Optional)
webui_clean();
return 0;
}
#if defined(_MSC_VER)
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { return main(); }
#endif

Some files were not shown because too many files have changed in this diff Show More