plusui-native-core 0.1.23 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Core/CMakeLists.txt +2 -2
- package/Core/Features/App/app.cpp +18 -15
- package/Core/Features/App/app.ts +2 -0
- package/Core/Features/Browser/browser.cpp +1 -1
- package/Core/Features/Menu/menu.cpp +1 -1
- package/Core/Features/{WebView → Window}/webview.cpp +172 -103
- package/Core/Features/{WebView → Window}/webview.ts +6 -0
- package/Core/include/plusui/app.hpp +4 -2
- package/Core/include/plusui/plusui.hpp +0 -1
- package/Core/include/plusui/window.hpp +97 -0
- package/package.json +1 -1
- package/Core/include/plusui/webview.hpp +0 -142
- /package/Core/Features/{WindowManager → Window}/window_manager.cpp +0 -0
package/Core/CMakeLists.txt
CHANGED
|
@@ -24,8 +24,8 @@ add_library(plusui STATIC
|
|
|
24
24
|
Features/Bindings/CustomBindings/custom_bindings.cpp
|
|
25
25
|
Features/App/app.cpp
|
|
26
26
|
Features/Window/window.cpp
|
|
27
|
-
Features/
|
|
28
|
-
Features/
|
|
27
|
+
Features/Window/window_manager.cpp
|
|
28
|
+
Features/Window/webview.cpp
|
|
29
29
|
Features/Browser/browser.cpp
|
|
30
30
|
Features/Display/display.cpp
|
|
31
31
|
Features/Tray/tray.cpp
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
#include <plusui/app.hpp>
|
|
7
7
|
#include <plusui/tray.hpp>
|
|
8
|
-
#include <plusui/
|
|
8
|
+
#include <plusui/window.hpp>
|
|
9
9
|
#include <plusui/window.hpp>
|
|
10
10
|
#include <plusui/window_manager.hpp>
|
|
11
11
|
|
|
@@ -90,8 +90,12 @@ App::Builder &App::Builder::scrollbars(bool show) {
|
|
|
90
90
|
config.scrollbars = show;
|
|
91
91
|
return *this;
|
|
92
92
|
}
|
|
93
|
+
App::Builder &App::Builder::enableFileDrop(bool enable) {
|
|
94
|
+
config.enableFileDrop = enable;
|
|
95
|
+
return *this;
|
|
96
|
+
}
|
|
93
97
|
|
|
94
|
-
|
|
98
|
+
Window App::Builder::build() {
|
|
95
99
|
WindowConfig winConfig;
|
|
96
100
|
winConfig.title = config.title;
|
|
97
101
|
winConfig.width = config.width;
|
|
@@ -102,26 +106,25 @@ WebView App::Builder::build() {
|
|
|
102
106
|
winConfig.transparent = config.transparent;
|
|
103
107
|
winConfig.decorations = config.decorations;
|
|
104
108
|
winConfig.skipTaskbar = config.skipTaskbar;
|
|
109
|
+
winConfig.enableFileDrop = config.enableFileDrop;
|
|
110
|
+
|
|
111
|
+
// WebView configuration (now part of WindowConfig)
|
|
112
|
+
winConfig.devtools = config.devtools;
|
|
113
|
+
winConfig.scrollbars = config.scrollbars;
|
|
114
|
+
winConfig.disableWebviewDragDrop = config.enableFileDrop; // Auto-disable webview drag when FileDrop enabled
|
|
105
115
|
|
|
106
|
-
|
|
107
|
-
win
|
|
108
|
-
|
|
109
|
-
WebViewConfig webConfig;
|
|
110
|
-
webConfig.devtools = config.devtools;
|
|
111
|
-
webConfig.scrollbars = config.scrollbars;
|
|
112
|
-
|
|
113
|
-
WebView wv = WebView::create(win->nativeHandle(), webConfig);
|
|
114
|
-
wv.setWindow(win);
|
|
116
|
+
Window win = Window::create(winConfig);
|
|
117
|
+
win.show();
|
|
115
118
|
|
|
116
119
|
if (!config.trayIconPath.empty()) {
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
win.tray().setIcon(config.trayIconPath);
|
|
121
|
+
win.tray().setVisible(true);
|
|
119
122
|
if (!config.trayTooltip.empty()) {
|
|
120
|
-
|
|
123
|
+
win.tray().setTooltip(config.trayTooltip);
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
|
|
124
|
-
return
|
|
127
|
+
return win;
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
App::Builder createApp() { return App::Builder(); }
|
package/Core/Features/App/app.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#include <map>
|
|
4
4
|
#include <plusui/tray.hpp>
|
|
5
5
|
#include <plusui/webgpu.hpp>
|
|
6
|
-
#include <plusui/
|
|
6
|
+
#include <plusui/window.hpp>
|
|
7
7
|
#include <plusui/window.hpp>
|
|
8
8
|
#include <plusui/window_manager.hpp>
|
|
9
9
|
#include <regex>
|
|
@@ -26,11 +26,12 @@ using namespace Microsoft::WRL;
|
|
|
26
26
|
|
|
27
27
|
namespace plusui {
|
|
28
28
|
|
|
29
|
-
struct
|
|
29
|
+
struct Window::Impl {
|
|
30
30
|
void *nativeWebView = nullptr;
|
|
31
|
-
|
|
31
|
+
WindowConfig config;
|
|
32
32
|
std::string currentURL;
|
|
33
33
|
std::string currentTitle;
|
|
34
|
+
std::string userAgent; // Advanced webview setting
|
|
34
35
|
bool loading = false;
|
|
35
36
|
double zoom = 1.0;
|
|
36
37
|
bool ready = false;
|
|
@@ -43,7 +44,6 @@ struct WebView::Impl {
|
|
|
43
44
|
|
|
44
45
|
std::unique_ptr<TrayManager> trayManager;
|
|
45
46
|
std::unique_ptr<WindowManager> windowManager;
|
|
46
|
-
std::shared_ptr<Window> window; // Keep the window alive
|
|
47
47
|
std::map<std::string, std::function<void(const std::string &)>> events;
|
|
48
48
|
WebGPU webgpu; // WebGPU support
|
|
49
49
|
|
|
@@ -64,22 +64,22 @@ struct WebView::Impl {
|
|
|
64
64
|
#endif
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
Window::Window() : pImpl(std::shared_ptr<Impl>(new Impl())) {}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Window::~Window() = default;
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
Window::Window(Window &&other) noexcept = default;
|
|
72
|
+
Window &Window::operator=(Window &&other) noexcept = default;
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
Window Window::create(void *windowHandle, const WindowConfig &config) {
|
|
75
|
+
Window win;
|
|
76
|
+
win.pImpl->config = config;
|
|
77
77
|
|
|
78
78
|
#ifdef _WIN32
|
|
79
79
|
HWND hwnd = static_cast<HWND>(windowHandle);
|
|
80
80
|
|
|
81
81
|
// Create WebView2 environment and controller
|
|
82
|
-
auto pImpl =
|
|
82
|
+
auto pImpl = win.pImpl;
|
|
83
83
|
CreateCoreWebView2EnvironmentWithOptions(
|
|
84
84
|
nullptr, nullptr, nullptr,
|
|
85
85
|
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
|
@@ -140,34 +140,36 @@ WebView WebView::create(void *windowHandle, const WebViewConfig &config) {
|
|
|
140
140
|
nullptr);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
// Disable
|
|
143
|
+
// Disable webview drag & drop behavior if requested
|
|
144
144
|
// This prevents files from being loaded in the browser
|
|
145
145
|
// and allows the native FileDrop API to handle them instead
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
146
|
+
if (pImpl->config.disableWebviewDragDrop) {
|
|
147
|
+
std::string disableDragDropScript = R"(
|
|
148
|
+
(function() {
|
|
149
|
+
// Prevent default drag and drop behavior on document/window
|
|
150
|
+
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {
|
|
151
|
+
document.addEventListener(eventName, function(e) {
|
|
152
|
+
// Only prevent default on document.body or document.documentElement
|
|
153
|
+
// to allow custom drop zones to still work
|
|
154
|
+
if (e.target === document.body || e.target === document.documentElement || e.target === document) {
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
e.stopPropagation();
|
|
157
|
+
}
|
|
158
|
+
}, true);
|
|
159
|
+
|
|
160
|
+
window.addEventListener(eventName, function(e) {
|
|
161
|
+
e.preventDefault();
|
|
162
|
+
e.stopPropagation();
|
|
163
|
+
}, true);
|
|
164
|
+
});
|
|
165
|
+
})();
|
|
166
|
+
)";
|
|
167
|
+
pImpl->webview->AddScriptToExecuteOnDocumentCreated(
|
|
168
|
+
std::wstring(disableDragDropScript.begin(),
|
|
169
|
+
disableDragDropScript.end())
|
|
170
|
+
.c_str(),
|
|
171
|
+
nullptr);
|
|
172
|
+
}
|
|
171
173
|
|
|
172
174
|
// Set up WebMessageReceived handler for JS->C++ bridge
|
|
173
175
|
pImpl->webview->add_WebMessageReceived(
|
|
@@ -530,6 +532,32 @@ WebView WebView::create(void *windowHandle, const WebViewConfig &config) {
|
|
|
530
532
|
<< "[PlusUI] Unknown menu method: "
|
|
531
533
|
<< menuMethod << std::endl;
|
|
532
534
|
}
|
|
535
|
+
} else if (method.find("webview.") == 0) {
|
|
536
|
+
// WebView API routing
|
|
537
|
+
std::string webviewMethod = method.substr(8);
|
|
538
|
+
if (webviewMethod == "setWebviewDragDropEnabled") {
|
|
539
|
+
size_t p1 = msg.find("[");
|
|
540
|
+
size_t p2 = msg.find("]");
|
|
541
|
+
if (p1 != std::string::npos &&
|
|
542
|
+
p2 != std::string::npos) {
|
|
543
|
+
std::string params =
|
|
544
|
+
msg.substr(p1 + 1, p2 - p1 - 1);
|
|
545
|
+
bool enabled = params.find("true") != std::string::npos;
|
|
546
|
+
// Note: Need to call this on the WebView instance
|
|
547
|
+
// This is a placeholder - actual implementation needs WebView reference
|
|
548
|
+
// For now, execute script directly
|
|
549
|
+
std::string script;
|
|
550
|
+
if (enabled) {
|
|
551
|
+
script = "(function() { if (window.__plusui_dragDropDisabled) { delete window.__plusui_dragDropDisabled; } })();";
|
|
552
|
+
} else {
|
|
553
|
+
script = "(function() { if (window.__plusui_dragDropDisabled) return; window.__plusui_dragDropDisabled = true; ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) { document.addEventListener(eventName, function(e) { if (e.target === document.body || e.target === document.documentElement || e.target === document) { e.preventDefault(); e.stopPropagation(); } }, true); window.addEventListener(eventName, function(e) { e.preventDefault(); e.stopPropagation(); }, true); }); })();";
|
|
554
|
+
}
|
|
555
|
+
pImpl->webview->ExecuteScript(
|
|
556
|
+
std::wstring(script.begin(), script.end()).c_str(),
|
|
557
|
+
nullptr);
|
|
558
|
+
}
|
|
559
|
+
success = true;
|
|
560
|
+
}
|
|
533
561
|
} else if (method.find("webgpu.") == 0) {
|
|
534
562
|
// WebGPU API routing
|
|
535
563
|
std::string webgpuMethod = method.substr(
|
|
@@ -642,34 +670,36 @@ WebView WebView::create(void *windowHandle, const WebViewConfig &config) {
|
|
|
642
670
|
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
|
|
643
671
|
config.preferences.javaScriptEnabled = YES;
|
|
644
672
|
|
|
645
|
-
if (
|
|
673
|
+
if (win.pImpl->config.devtools) {
|
|
646
674
|
[config.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
|
|
647
675
|
}
|
|
648
676
|
|
|
649
|
-
// Disable
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
"
|
|
653
|
-
"
|
|
677
|
+
// Disable webview drag & drop behavior to allow native FileDrop API
|
|
678
|
+
if (win.pImpl->config.disableWebviewDragDrop) {
|
|
679
|
+
NSString *disableDragDropScript = @"(function() {"
|
|
680
|
+
"['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {"
|
|
681
|
+
"document.addEventListener(eventName, function(e) {"
|
|
682
|
+
"if (e.target === document.body || e.target === document.documentElement || e.target === document) {"
|
|
683
|
+
"e.preventDefault();"
|
|
684
|
+
"e.stopPropagation();"
|
|
685
|
+
"}"
|
|
686
|
+
"}, true);"
|
|
687
|
+
"window.addEventListener(eventName, function(e) {"
|
|
654
688
|
"e.preventDefault();"
|
|
655
689
|
"e.stopPropagation();"
|
|
656
|
-
"}"
|
|
657
|
-
"}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
initWithSource:disableDragDropScript
|
|
667
|
-
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
|
|
668
|
-
forMainFrameOnly:NO];
|
|
669
|
-
[config.userContentController addUserScript:userScript];
|
|
690
|
+
"}, true);"
|
|
691
|
+
"});"
|
|
692
|
+
"})();";
|
|
693
|
+
|
|
694
|
+
WKUserScript *userScript = [[WKUserScript alloc]
|
|
695
|
+
initWithSource:disableDragDropScript
|
|
696
|
+
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
|
|
697
|
+
forMainFrameOnly:NO];
|
|
698
|
+
[config.userContentController addUserScript:userScript];
|
|
699
|
+
}
|
|
670
700
|
|
|
671
701
|
// Hide scrollbars if disabled
|
|
672
|
-
if (!
|
|
702
|
+
if (!win.pImpl->config.scrollbars) {
|
|
673
703
|
NSString *scrollbarScript = @"(function() {"
|
|
674
704
|
"var css = 'html, body { overflow: hidden !important; margin: 0 !important; padding: 0 !important; } ::-webkit-scrollbar { display: none !important; width: 0 !important; height: 0 !important; }';"
|
|
675
705
|
"var style = document.createElement('style');"
|
|
@@ -686,25 +716,25 @@ WebView WebView::create(void *windowHandle, const WebViewConfig &config) {
|
|
|
686
716
|
}
|
|
687
717
|
|
|
688
718
|
NSView *parentView = (__bridge NSView *)windowHandle;
|
|
689
|
-
|
|
719
|
+
win.pImpl->wkWebView =
|
|
690
720
|
[[WKWebView alloc] initWithFrame:parentView.bounds configuration:config];
|
|
691
|
-
[parentView addSubview:
|
|
721
|
+
[parentView addSubview:win.pImpl->wkWebView];
|
|
692
722
|
|
|
693
|
-
|
|
723
|
+
win.pImpl->nativeWebView = (__bridge void *)win.pImpl->wkWebView;
|
|
694
724
|
|
|
695
725
|
#endif
|
|
696
726
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
727
|
+
win.pImpl->windowManager = std::make_unique<WindowManager>(windowHandle);
|
|
728
|
+
win.pImpl->trayManager = std::make_unique<TrayManager>();
|
|
729
|
+
win.pImpl->trayManager->setWindowHandle(windowHandle);
|
|
700
730
|
|
|
701
|
-
return
|
|
731
|
+
return win;
|
|
702
732
|
}
|
|
703
733
|
|
|
704
|
-
TrayManager &
|
|
705
|
-
WindowManager &
|
|
734
|
+
TrayManager &Window::tray() { return *pImpl->trayManager; }
|
|
735
|
+
WindowManager &Window::window() { return *pImpl->windowManager; }
|
|
706
736
|
|
|
707
|
-
void
|
|
737
|
+
void Window::setWindow(std::shared_ptr<Window> win) {
|
|
708
738
|
pImpl->window = win;
|
|
709
739
|
if (!win)
|
|
710
740
|
return;
|
|
@@ -746,18 +776,18 @@ void WebView::setWindow(std::shared_ptr<Window> win) {
|
|
|
746
776
|
#endif
|
|
747
777
|
}
|
|
748
778
|
|
|
749
|
-
void
|
|
779
|
+
void Window::on(const std::string &event,
|
|
750
780
|
std::function<void(const std::string &)> callback) {
|
|
751
781
|
pImpl->events[event] = callback;
|
|
752
782
|
}
|
|
753
783
|
|
|
754
|
-
void
|
|
784
|
+
void Window::emit(const std::string &event, const std::string &data) {
|
|
755
785
|
std::string js = "window.dispatchEvent(new CustomEvent('" + event +
|
|
756
786
|
"', {detail: " + data + "}))";
|
|
757
787
|
executeScript(js);
|
|
758
788
|
}
|
|
759
789
|
|
|
760
|
-
void
|
|
790
|
+
void Window::navigate(const std::string &url) {
|
|
761
791
|
pImpl->currentURL = url;
|
|
762
792
|
pImpl->loading = true;
|
|
763
793
|
|
|
@@ -781,11 +811,11 @@ void WebView::navigate(const std::string &url) {
|
|
|
781
811
|
#endif
|
|
782
812
|
}
|
|
783
813
|
|
|
784
|
-
void
|
|
814
|
+
void Window::loadHTML(const std::string &html) {
|
|
785
815
|
loadHTML(html, "about:blank");
|
|
786
816
|
}
|
|
787
817
|
|
|
788
|
-
void
|
|
818
|
+
void Window::loadHTML(const std::string &html, const std::string &baseURL) {
|
|
789
819
|
pImpl->loading = true;
|
|
790
820
|
|
|
791
821
|
#ifdef _WIN32
|
|
@@ -810,7 +840,7 @@ void WebView::loadHTML(const std::string &html, const std::string &baseURL) {
|
|
|
810
840
|
#endif
|
|
811
841
|
}
|
|
812
842
|
|
|
813
|
-
void
|
|
843
|
+
void Window::loadFile(const std::string &filePath) {
|
|
814
844
|
std::ifstream file(filePath);
|
|
815
845
|
if (!file) {
|
|
816
846
|
std::cerr << "PlusUI: Failed to open file: " << filePath << std::endl;
|
|
@@ -826,7 +856,7 @@ void WebView::loadFile(const std::string &filePath) {
|
|
|
826
856
|
loadHTML(buffer.str(), baseURL);
|
|
827
857
|
}
|
|
828
858
|
|
|
829
|
-
void
|
|
859
|
+
void Window::reload() {
|
|
830
860
|
#ifdef _WIN32
|
|
831
861
|
if (pImpl->webview) {
|
|
832
862
|
pImpl->webview->Reload();
|
|
@@ -842,7 +872,7 @@ void WebView::reload() {
|
|
|
842
872
|
#endif
|
|
843
873
|
}
|
|
844
874
|
|
|
845
|
-
void
|
|
875
|
+
void Window::stop() {
|
|
846
876
|
#ifdef _WIN32
|
|
847
877
|
if (pImpl->webview) {
|
|
848
878
|
pImpl->webview->Stop();
|
|
@@ -858,7 +888,7 @@ void WebView::stop() {
|
|
|
858
888
|
#endif
|
|
859
889
|
}
|
|
860
890
|
|
|
861
|
-
void
|
|
891
|
+
void Window::goBack() {
|
|
862
892
|
#ifdef _WIN32
|
|
863
893
|
if (pImpl->webview) {
|
|
864
894
|
pImpl->webview->GoBack();
|
|
@@ -874,7 +904,7 @@ void WebView::goBack() {
|
|
|
874
904
|
#endif
|
|
875
905
|
}
|
|
876
906
|
|
|
877
|
-
void
|
|
907
|
+
void Window::goForward() {
|
|
878
908
|
#ifdef _WIN32
|
|
879
909
|
if (pImpl->webview) {
|
|
880
910
|
pImpl->webview->GoForward();
|
|
@@ -890,7 +920,7 @@ void WebView::goForward() {
|
|
|
890
920
|
#endif
|
|
891
921
|
}
|
|
892
922
|
|
|
893
|
-
bool
|
|
923
|
+
bool Window::canGoBack() const {
|
|
894
924
|
#ifdef _WIN32
|
|
895
925
|
if (pImpl->webview) {
|
|
896
926
|
BOOL canGoBack;
|
|
@@ -909,7 +939,7 @@ bool WebView::canGoBack() const {
|
|
|
909
939
|
return false;
|
|
910
940
|
}
|
|
911
941
|
|
|
912
|
-
bool
|
|
942
|
+
bool Window::canGoForward() const {
|
|
913
943
|
#ifdef _WIN32
|
|
914
944
|
if (pImpl->webview) {
|
|
915
945
|
BOOL canGoForward;
|
|
@@ -928,7 +958,7 @@ bool WebView::canGoForward() const {
|
|
|
928
958
|
return false;
|
|
929
959
|
}
|
|
930
960
|
|
|
931
|
-
void
|
|
961
|
+
void Window::executeScript(const std::string &script) {
|
|
932
962
|
#ifdef _WIN32
|
|
933
963
|
if (pImpl->ready && pImpl->webview) {
|
|
934
964
|
pImpl->webview->ExecuteScript(
|
|
@@ -949,7 +979,7 @@ void WebView::executeScript(const std::string &script) {
|
|
|
949
979
|
#endif
|
|
950
980
|
}
|
|
951
981
|
|
|
952
|
-
void
|
|
982
|
+
void Window::executeScript(const std::string &script,
|
|
953
983
|
std::function<void(const std::string &)> callback) {
|
|
954
984
|
#ifdef _WIN32
|
|
955
985
|
if (pImpl->webview) {
|
|
@@ -987,7 +1017,7 @@ void WebView::executeScript(const std::string &script,
|
|
|
987
1017
|
#endif
|
|
988
1018
|
}
|
|
989
1019
|
|
|
990
|
-
void
|
|
1020
|
+
void Window::bind(const std::string &name, JSCallback callback) {
|
|
991
1021
|
pImpl->bindings[name] = callback;
|
|
992
1022
|
|
|
993
1023
|
// Inject bridge code to expose function to JavaScript
|
|
@@ -1001,14 +1031,14 @@ void WebView::bind(const std::string &name, JSCallback callback) {
|
|
|
1001
1031
|
executeScript(bridgeScript);
|
|
1002
1032
|
}
|
|
1003
1033
|
|
|
1004
|
-
void
|
|
1034
|
+
void Window::unbind(const std::string &name) {
|
|
1005
1035
|
pImpl->bindings.erase(name);
|
|
1006
1036
|
|
|
1007
1037
|
std::string script = "delete window." + name + ";";
|
|
1008
1038
|
executeScript(script);
|
|
1009
1039
|
}
|
|
1010
1040
|
|
|
1011
|
-
void
|
|
1041
|
+
void Window::openDevTools() {
|
|
1012
1042
|
#ifdef _WIN32
|
|
1013
1043
|
if (pImpl->webview) {
|
|
1014
1044
|
pImpl->webview->OpenDevToolsWindow();
|
|
@@ -1024,7 +1054,7 @@ void WebView::openDevTools() {
|
|
|
1024
1054
|
#endif
|
|
1025
1055
|
}
|
|
1026
1056
|
|
|
1027
|
-
void
|
|
1057
|
+
void Window::closeDevTools() {
|
|
1028
1058
|
#ifdef _WIN32
|
|
1029
1059
|
// WebView2 doesn't have explicit close
|
|
1030
1060
|
#elif defined(__APPLE__)
|
|
@@ -1038,8 +1068,8 @@ void WebView::closeDevTools() {
|
|
|
1038
1068
|
#endif
|
|
1039
1069
|
}
|
|
1040
1070
|
|
|
1041
|
-
void
|
|
1042
|
-
pImpl->
|
|
1071
|
+
void Window::setUserAgent(const std::string &userAgent) {
|
|
1072
|
+
pImpl->userAgent = userAgent;
|
|
1043
1073
|
|
|
1044
1074
|
#ifdef _WIN32
|
|
1045
1075
|
if (pImpl->webview) {
|
|
@@ -1060,9 +1090,9 @@ void WebView::setUserAgent(const std::string &userAgent) {
|
|
|
1060
1090
|
#endif
|
|
1061
1091
|
}
|
|
1062
1092
|
|
|
1063
|
-
std::string
|
|
1093
|
+
std::string Window::getUserAgent() const { return pImpl->userAgent; }
|
|
1064
1094
|
|
|
1065
|
-
void
|
|
1095
|
+
void Window::setZoom(double factor) {
|
|
1066
1096
|
pImpl->zoom = factor;
|
|
1067
1097
|
|
|
1068
1098
|
#ifdef _WIN32
|
|
@@ -1080,9 +1110,9 @@ void WebView::setZoom(double factor) {
|
|
|
1080
1110
|
#endif
|
|
1081
1111
|
}
|
|
1082
1112
|
|
|
1083
|
-
double
|
|
1113
|
+
double Window::getZoom() const { return pImpl->zoom; }
|
|
1084
1114
|
|
|
1085
|
-
void
|
|
1115
|
+
void Window::injectCSS(const std::string &css) {
|
|
1086
1116
|
std::string script = R"(
|
|
1087
1117
|
(function() {
|
|
1088
1118
|
const style = document.createElement('style');
|
|
@@ -1095,36 +1125,75 @@ void WebView::injectCSS(const std::string &css) {
|
|
|
1095
1125
|
executeScript(script);
|
|
1096
1126
|
}
|
|
1097
1127
|
|
|
1098
|
-
void
|
|
1128
|
+
void Window::setWebviewDragDropEnabled(bool enabled) {
|
|
1129
|
+
std::string script;
|
|
1130
|
+
|
|
1131
|
+
if (enabled) {
|
|
1132
|
+
// Enable webview drag-drop by removing our prevention handlers
|
|
1133
|
+
script = R"(
|
|
1134
|
+
(function() {
|
|
1135
|
+
if (window.__plusui_dragDropDisabled) {
|
|
1136
|
+
delete window.__plusui_dragDropDisabled;
|
|
1137
|
+
}
|
|
1138
|
+
})();
|
|
1139
|
+
)";
|
|
1140
|
+
} else {
|
|
1141
|
+
// Disable webview drag-drop by preventing default behavior
|
|
1142
|
+
script = R"(
|
|
1143
|
+
(function() {
|
|
1144
|
+
if (window.__plusui_dragDropDisabled) return; // Already disabled
|
|
1145
|
+
window.__plusui_dragDropDisabled = true;
|
|
1146
|
+
|
|
1147
|
+
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {
|
|
1148
|
+
document.addEventListener(eventName, function(e) {
|
|
1149
|
+
if (e.target === document.body || e.target === document.documentElement || e.target === document) {
|
|
1150
|
+
e.preventDefault();
|
|
1151
|
+
e.stopPropagation();
|
|
1152
|
+
}
|
|
1153
|
+
}, true);
|
|
1154
|
+
|
|
1155
|
+
window.addEventListener(eventName, function(e) {
|
|
1156
|
+
e.preventDefault();
|
|
1157
|
+
e.stopPropagation();
|
|
1158
|
+
}, true);
|
|
1159
|
+
});
|
|
1160
|
+
})();
|
|
1161
|
+
)";
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
executeScript(script);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
void Window::onNavigationStart(NavigationCallback callback) {
|
|
1099
1168
|
pImpl->navigationCallback = callback;
|
|
1100
1169
|
}
|
|
1101
1170
|
|
|
1102
|
-
void
|
|
1171
|
+
void Window::onNavigationComplete(LoadCallback callback) {
|
|
1103
1172
|
pImpl->navigationCompleteCallback = callback;
|
|
1104
1173
|
}
|
|
1105
1174
|
|
|
1106
|
-
void
|
|
1175
|
+
void Window::onLoadStart(LoadCallback callback) {
|
|
1107
1176
|
pImpl->loadStartCallback = callback;
|
|
1108
1177
|
}
|
|
1109
1178
|
|
|
1110
|
-
void
|
|
1179
|
+
void Window::onLoadEnd(LoadCallback callback) {
|
|
1111
1180
|
pImpl->loadEndCallback = callback;
|
|
1112
1181
|
}
|
|
1113
1182
|
|
|
1114
|
-
void
|
|
1183
|
+
void Window::onLoadError(ErrorCallback callback) {
|
|
1115
1184
|
pImpl->errorCallback = callback;
|
|
1116
1185
|
}
|
|
1117
1186
|
|
|
1118
|
-
void
|
|
1187
|
+
void Window::onConsoleMessage(ConsoleCallback callback) {
|
|
1119
1188
|
pImpl->consoleCallback = callback;
|
|
1120
1189
|
}
|
|
1121
1190
|
|
|
1122
|
-
bool
|
|
1191
|
+
bool Window::isLoading() const { return pImpl->loading; }
|
|
1123
1192
|
|
|
1124
|
-
std::string
|
|
1193
|
+
std::string Window::getURL() const { return pImpl->currentURL; }
|
|
1125
1194
|
|
|
1126
|
-
std::string
|
|
1195
|
+
std::string Window::getTitle() const { return pImpl->currentTitle; }
|
|
1127
1196
|
|
|
1128
|
-
void *
|
|
1197
|
+
void *Window::nativeHandle() const { return pImpl->nativeWebView; }
|
|
1129
1198
|
|
|
1130
1199
|
} // namespace plusui
|
|
@@ -20,6 +20,7 @@ export interface WebViewConfig {
|
|
|
20
20
|
allowRemoteContent?: boolean;
|
|
21
21
|
dataPath?: string;
|
|
22
22
|
cacheSize?: number; // MB
|
|
23
|
+
disableWebviewDragDrop?: boolean; // Disable webview drag-drop (auto-set by WindowConfig.enableFileDrop)
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export type WindowId = number;
|
|
@@ -71,6 +72,7 @@ export interface WebViewAPI {
|
|
|
71
72
|
getZoom(): Promise<number>;
|
|
72
73
|
setBackgroundColor(r: number, g: number, b: number, a?: number): Promise<void>;
|
|
73
74
|
setScrollbarsVisible(visible: boolean): Promise<void>;
|
|
75
|
+
setWebviewDragDropEnabled(enabled: boolean): Promise<void>; // Runtime toggle for webview drag-drop
|
|
74
76
|
|
|
75
77
|
// CSS injection
|
|
76
78
|
injectCSS(css: string): Promise<void>;
|
|
@@ -300,6 +302,10 @@ export class WebView implements WebViewAPI {
|
|
|
300
302
|
await this.invokeFn('webview.setScrollbarsVisible', [visible]);
|
|
301
303
|
}
|
|
302
304
|
|
|
305
|
+
async setWebviewDragDropEnabled(enabled: boolean): Promise<void> {
|
|
306
|
+
await this.invokeFn('webview.setWebviewDragDropEnabled', [enabled]);
|
|
307
|
+
}
|
|
308
|
+
|
|
303
309
|
// CSS injection
|
|
304
310
|
async injectCSS(css: string): Promise<void> {
|
|
305
311
|
await this.invokeFn('webview.injectCSS', [css]);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#define PLUSUI_APP_H
|
|
3
3
|
|
|
4
4
|
#include "tray.hpp"
|
|
5
|
-
#include "
|
|
5
|
+
#include "window.hpp"
|
|
6
6
|
#include "window_manager.hpp"
|
|
7
7
|
#include <functional>
|
|
8
8
|
#include <future>
|
|
@@ -42,6 +42,7 @@ public:
|
|
|
42
42
|
bool decorations = true;
|
|
43
43
|
bool skipTaskbar = false;
|
|
44
44
|
bool scrollbars = true;
|
|
45
|
+
bool enableFileDrop = true;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
Builder();
|
|
@@ -59,8 +60,9 @@ public:
|
|
|
59
60
|
Builder &decorations(bool decorations);
|
|
60
61
|
Builder &skipTaskbar(bool skip);
|
|
61
62
|
Builder &scrollbars(bool show);
|
|
63
|
+
Builder &enableFileDrop(bool enable);
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
Window build();
|
|
64
66
|
|
|
65
67
|
private:
|
|
66
68
|
Config config;
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <functional>
|
|
4
|
+
#include <future>
|
|
5
|
+
#include <map>
|
|
4
6
|
#include <memory>
|
|
5
7
|
#include <string>
|
|
6
8
|
#include <vector>
|
|
7
9
|
|
|
8
10
|
namespace plusui {
|
|
9
11
|
|
|
12
|
+
class TrayManager;
|
|
13
|
+
class WindowManager;
|
|
14
|
+
|
|
10
15
|
struct WindowConfig {
|
|
16
|
+
// Window properties
|
|
11
17
|
std::string title = "PlusUI Window";
|
|
12
18
|
int x = -1;
|
|
13
19
|
int y = -1;
|
|
@@ -29,6 +35,20 @@ struct WindowConfig {
|
|
|
29
35
|
bool skipTaskbar = false;
|
|
30
36
|
double opacity = 1.0;
|
|
31
37
|
bool fullscreen = false;
|
|
38
|
+
bool enableFileDrop = true; // Enable native FileDrop API (auto-disables webview drag-drop)
|
|
39
|
+
|
|
40
|
+
// WebView properties
|
|
41
|
+
std::string userAgent = "";
|
|
42
|
+
bool devtools = true;
|
|
43
|
+
bool contextMenu = true;
|
|
44
|
+
bool javascript = true;
|
|
45
|
+
bool webSecurity = true;
|
|
46
|
+
bool allowFileAccess = false;
|
|
47
|
+
bool allowRemoteContent = true;
|
|
48
|
+
std::string dataPath = "";
|
|
49
|
+
int cacheSize = 100; // MB
|
|
50
|
+
bool scrollbars = true; // Show/hide scrollbars
|
|
51
|
+
bool disableWebviewDragDrop = true; // Disable webview drag-drop (usually set by enableFileDrop)
|
|
32
52
|
};
|
|
33
53
|
|
|
34
54
|
struct WindowState {
|
|
@@ -103,6 +123,83 @@ public:
|
|
|
103
123
|
|
|
104
124
|
void *nativeHandle() const;
|
|
105
125
|
|
|
126
|
+
// WebView methods (content loading)
|
|
127
|
+
using StringCallback = std::function<void(const std::string &result)>;
|
|
128
|
+
using BoolCallback = std::function<bool(const std::string &url)>;
|
|
129
|
+
using ErrorCallback = std::function<void(const std::string &error, int code)>;
|
|
130
|
+
using ConsoleCallback = std::function<void(
|
|
131
|
+
const std::string &message, int level, const std::string &source)>;
|
|
132
|
+
using JSCallback = std::function<std::string(const std::string &args)>;
|
|
133
|
+
using NavigationCallback = std::function<bool(const std::string &url)>;
|
|
134
|
+
using LoadCallback = std::function<void()>;
|
|
135
|
+
|
|
136
|
+
void loadURL(const std::string &url);
|
|
137
|
+
void loadHTML(const std::string &html);
|
|
138
|
+
void loadHTML(const std::string &html, const std::string &baseURL);
|
|
139
|
+
void loadFile(const std::string &filePath);
|
|
140
|
+
void navigate(const std::string &url);
|
|
141
|
+
|
|
142
|
+
// Navigation
|
|
143
|
+
void reload();
|
|
144
|
+
void stop();
|
|
145
|
+
void goBack();
|
|
146
|
+
void goForward();
|
|
147
|
+
bool canGoBack() const;
|
|
148
|
+
bool canGoForward() const;
|
|
149
|
+
|
|
150
|
+
// Scripting
|
|
151
|
+
void executeScript(const std::string &script);
|
|
152
|
+
void executeScript(const std::string &script, StringCallback callback);
|
|
153
|
+
void eval(const std::string &js) {
|
|
154
|
+
executeScript(js);
|
|
155
|
+
} // Alias for compatibility
|
|
156
|
+
|
|
157
|
+
template <typename T> std::future<T> evaluate(const std::string &js) {
|
|
158
|
+
// Implementation in cpp or inline
|
|
159
|
+
return std::future<T>();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Bindings
|
|
163
|
+
void bind(const std::string &name, JSCallback callback);
|
|
164
|
+
void unbind(const std::string &name);
|
|
165
|
+
|
|
166
|
+
template <typename F> void expose(const std::string &name, F &&callback) {
|
|
167
|
+
// Implementation for simplified expose
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Dev tools
|
|
171
|
+
void openDevTools();
|
|
172
|
+
void closeDevTools();
|
|
173
|
+
|
|
174
|
+
// Events
|
|
175
|
+
void on(const std::string &event,
|
|
176
|
+
std::function<void(const std::string &)> callback);
|
|
177
|
+
void emit(const std::string &event, const std::string &data = "");
|
|
178
|
+
|
|
179
|
+
// WebView settings
|
|
180
|
+
void setUserAgent(const std::string &userAgent);
|
|
181
|
+
std::string getUserAgent() const;
|
|
182
|
+
void setZoom(double factor);
|
|
183
|
+
double getZoom() const;
|
|
184
|
+
void injectCSS(const std::string &css);
|
|
185
|
+
void setWebviewDragDropEnabled(bool enabled); // Enable/disable webview drag-drop at runtime
|
|
186
|
+
|
|
187
|
+
// WebView callbacks
|
|
188
|
+
void onNavigationStart(NavigationCallback callback);
|
|
189
|
+
void onNavigationComplete(LoadCallback callback);
|
|
190
|
+
void onLoadStart(LoadCallback callback);
|
|
191
|
+
void onLoadEnd(LoadCallback callback);
|
|
192
|
+
void onLoadError(ErrorCallback callback);
|
|
193
|
+
void onConsoleMessage(ConsoleCallback callback);
|
|
194
|
+
|
|
195
|
+
// WebView state
|
|
196
|
+
bool isLoading() const;
|
|
197
|
+
std::string getURL() const;
|
|
198
|
+
|
|
199
|
+
// Features
|
|
200
|
+
TrayManager &tray();
|
|
201
|
+
WindowManager &windowManager();
|
|
202
|
+
|
|
106
203
|
private:
|
|
107
204
|
struct Impl;
|
|
108
205
|
std::shared_ptr<Impl> pImpl;
|
package/package.json
CHANGED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include <functional>
|
|
4
|
-
#include <future>
|
|
5
|
-
#include <map>
|
|
6
|
-
#include <memory>
|
|
7
|
-
#include <string>
|
|
8
|
-
#include <vector>
|
|
9
|
-
|
|
10
|
-
namespace plusui {
|
|
11
|
-
|
|
12
|
-
class TrayManager;
|
|
13
|
-
class WindowManager;
|
|
14
|
-
class Window;
|
|
15
|
-
|
|
16
|
-
struct WebViewConfig {
|
|
17
|
-
std::string userAgent = "";
|
|
18
|
-
bool devtools = true;
|
|
19
|
-
bool contextMenu = true;
|
|
20
|
-
bool javascript = true;
|
|
21
|
-
bool webSecurity = true;
|
|
22
|
-
bool allowFileAccess = false;
|
|
23
|
-
bool allowRemoteContent = true;
|
|
24
|
-
std::string dataPath = "";
|
|
25
|
-
int cacheSize = 100; // MB
|
|
26
|
-
bool scrollbars = true; // Show/hide scrollbars
|
|
27
|
-
|
|
28
|
-
// App Builder style config
|
|
29
|
-
std::string title;
|
|
30
|
-
int width = 800;
|
|
31
|
-
int height = 600;
|
|
32
|
-
bool resizable = true;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
class WebView {
|
|
36
|
-
public:
|
|
37
|
-
using WindowId = uint64_t;
|
|
38
|
-
|
|
39
|
-
// Callback types
|
|
40
|
-
using VoidCallback = std::function<void()>;
|
|
41
|
-
using StringCallback = std::function<void(const std::string &result)>;
|
|
42
|
-
using BoolCallback = std::function<bool(const std::string &url)>;
|
|
43
|
-
using ErrorCallback = std::function<void(const std::string &error, int code)>;
|
|
44
|
-
using ConsoleCallback = std::function<void(
|
|
45
|
-
const std::string &message, int level, const std::string &source)>;
|
|
46
|
-
using JSCallback = std::function<std::string(const std::string &args)>;
|
|
47
|
-
using NavigationCallback = std::function<bool(const std::string &url)>;
|
|
48
|
-
using LoadCallback = std::function<void()>;
|
|
49
|
-
|
|
50
|
-
WebView();
|
|
51
|
-
// Constructor used by App::Builder
|
|
52
|
-
struct AppConfig;
|
|
53
|
-
// WebView(const AppConfig& config); // We'll handle this via create or
|
|
54
|
-
// similar
|
|
55
|
-
|
|
56
|
-
~WebView();
|
|
57
|
-
|
|
58
|
-
// Move only
|
|
59
|
-
WebView(WebView &&other) noexcept;
|
|
60
|
-
WebView &operator=(WebView &&other) noexcept;
|
|
61
|
-
WebView(const WebView &) = delete;
|
|
62
|
-
WebView &operator=(const WebView &) = delete;
|
|
63
|
-
|
|
64
|
-
static WebView create(void *windowHandle, const WebViewConfig &config = {});
|
|
65
|
-
|
|
66
|
-
// Content loading
|
|
67
|
-
void loadURL(const std::string &url);
|
|
68
|
-
void loadHTML(const std::string &html);
|
|
69
|
-
void loadHTML(const std::string &html, const std::string &baseURL);
|
|
70
|
-
void loadFile(const std::string &filePath);
|
|
71
|
-
void navigate(const std::string &url);
|
|
72
|
-
|
|
73
|
-
// Navigation
|
|
74
|
-
void reload();
|
|
75
|
-
void stop();
|
|
76
|
-
void goBack();
|
|
77
|
-
void goForward();
|
|
78
|
-
bool canGoBack() const;
|
|
79
|
-
bool canGoForward() const;
|
|
80
|
-
|
|
81
|
-
// Scripting
|
|
82
|
-
void executeScript(const std::string &script);
|
|
83
|
-
void executeScript(const std::string &script, StringCallback callback);
|
|
84
|
-
void eval(const std::string &js) {
|
|
85
|
-
executeScript(js);
|
|
86
|
-
} // Alias for compatibility
|
|
87
|
-
|
|
88
|
-
template <typename T> std::future<T> evaluate(const std::string &js) {
|
|
89
|
-
// Implementation in cpp or inline
|
|
90
|
-
return std::future<T>();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Bindings
|
|
94
|
-
void bind(const std::string &name, JSCallback callback);
|
|
95
|
-
void unbind(const std::string &name);
|
|
96
|
-
|
|
97
|
-
template <typename F> void expose(const std::string &name, F &&callback) {
|
|
98
|
-
// Implementation for simplified expose
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Dev tools
|
|
102
|
-
void openDevTools();
|
|
103
|
-
void closeDevTools();
|
|
104
|
-
|
|
105
|
-
// Events
|
|
106
|
-
void on(const std::string &event,
|
|
107
|
-
std::function<void(const std::string &)> callback);
|
|
108
|
-
void emit(const std::string &event, const std::string &data = "");
|
|
109
|
-
|
|
110
|
-
// Settings
|
|
111
|
-
void setUserAgent(const std::string &userAgent);
|
|
112
|
-
std::string getUserAgent() const;
|
|
113
|
-
void setZoom(double factor);
|
|
114
|
-
double getZoom() const;
|
|
115
|
-
void injectCSS(const std::string &css);
|
|
116
|
-
|
|
117
|
-
// Callbacks
|
|
118
|
-
void onNavigationStart(NavigationCallback callback);
|
|
119
|
-
void onNavigationComplete(LoadCallback callback);
|
|
120
|
-
void onLoadStart(LoadCallback callback);
|
|
121
|
-
void onLoadEnd(LoadCallback callback);
|
|
122
|
-
void onLoadError(ErrorCallback callback);
|
|
123
|
-
void onConsoleMessage(ConsoleCallback callback);
|
|
124
|
-
|
|
125
|
-
// State
|
|
126
|
-
bool isLoading() const;
|
|
127
|
-
std::string getURL() const;
|
|
128
|
-
std::string getTitle() const;
|
|
129
|
-
void *nativeHandle() const;
|
|
130
|
-
void *nativeWindow() { return nativeHandle(); } // Alias
|
|
131
|
-
|
|
132
|
-
// Features
|
|
133
|
-
void setWindow(std::shared_ptr<Window> win);
|
|
134
|
-
TrayManager &tray();
|
|
135
|
-
WindowManager &window();
|
|
136
|
-
|
|
137
|
-
private:
|
|
138
|
-
struct Impl;
|
|
139
|
-
std::shared_ptr<Impl> pImpl;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
} // namespace plusui
|
|
File without changes
|