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.
@@ -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/WindowManager/window_manager.cpp
28
- Features/WebView/webview.cpp
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/webview.hpp>
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
- WebView App::Builder::build() {
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
- auto win = std::make_shared<Window>(Window::create(winConfig));
107
- win->show();
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
- wv.tray().setIcon(config.trayIconPath);
118
- wv.tray().setVisible(true);
120
+ win.tray().setIcon(config.trayIconPath);
121
+ win.tray().setVisible(true);
119
122
  if (!config.trayTooltip.empty()) {
120
- wv.tray().setTooltip(config.trayTooltip);
123
+ win.tray().setTooltip(config.trayTooltip);
121
124
  }
122
125
  }
123
126
 
124
- return wv;
127
+ return win;
125
128
  }
126
129
 
127
130
  App::Builder createApp() { return App::Builder(); }
@@ -11,6 +11,8 @@ export interface AppConfig {
11
11
  transparent?: boolean;
12
12
  decorations?: boolean;
13
13
  skipTaskbar?: boolean;
14
+ scrollbars?: boolean;
15
+ enableFileDrop?: boolean;
14
16
  }
15
17
 
16
18
  export interface InvokeOptions {
@@ -1,7 +1,7 @@
1
1
  #include <algorithm>
2
2
  #include <iostream>
3
3
  #include <plusui/browser.hpp>
4
- #include <plusui/webview.hpp>
4
+ #include <plusui/window.hpp>
5
5
  #include <plusui/window.hpp>
6
6
  #include <vector>
7
7
 
@@ -1,6 +1,6 @@
1
1
  #include <iostream>
2
2
  #include <plusui/menu.hpp>
3
- #include <plusui/webview.hpp>
3
+ #include <plusui/window.hpp>
4
4
  #include <sstream>
5
5
 
6
6
  #ifdef _WIN32
@@ -3,7 +3,7 @@
3
3
  #include <map>
4
4
  #include <plusui/tray.hpp>
5
5
  #include <plusui/webgpu.hpp>
6
- #include <plusui/webview.hpp>
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 WebView::Impl {
29
+ struct Window::Impl {
30
30
  void *nativeWebView = nullptr;
31
- WebViewConfig config;
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
- WebView::WebView() : pImpl(std::shared_ptr<Impl>(new Impl())) {}
67
+ Window::Window() : pImpl(std::shared_ptr<Impl>(new Impl())) {}
68
68
 
69
- WebView::~WebView() = default;
69
+ Window::~Window() = default;
70
70
 
71
- WebView::WebView(WebView &&other) noexcept = default;
72
- WebView &WebView::operator=(WebView &&other) noexcept = default;
71
+ Window::Window(Window &&other) noexcept = default;
72
+ Window &Window::operator=(Window &&other) noexcept = default;
73
73
 
74
- WebView WebView::create(void *windowHandle, const WebViewConfig &config) {
75
- WebView wv;
76
- wv.pImpl->config = config;
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 = wv.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 default webview drag & drop behavior
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
- std::string disableDragDropScript = R"(
147
- (function() {
148
- // Prevent default drag and drop behavior on document/window
149
- ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {
150
- document.addEventListener(eventName, function(e) {
151
- // Only prevent default on document.body or document.documentElement
152
- // to allow custom drop zones to still work
153
- if (e.target === document.body || e.target === document.documentElement || e.target === document) {
154
- e.preventDefault();
155
- e.stopPropagation();
156
- }
157
- }, true);
158
-
159
- window.addEventListener(eventName, function(e) {
160
- e.preventDefault();
161
- e.stopPropagation();
162
- }, true);
163
- });
164
- })();
165
- )";
166
- pImpl->webview->AddScriptToExecuteOnDocumentCreated(
167
- std::wstring(disableDragDropScript.begin(),
168
- disableDragDropScript.end())
169
- .c_str(),
170
- nullptr);
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 (wv.pImpl->config.devtools) {
673
+ if (win.pImpl->config.devtools) {
646
674
  [config.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
647
675
  }
648
676
 
649
- // Disable default drag & drop behavior to allow native FileDrop API
650
- NSString *disableDragDropScript = @"(function() {"
651
- "['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {"
652
- "document.addEventListener(eventName, function(e) {"
653
- "if (e.target === document.body || e.target === document.documentElement || e.target === document) {"
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
- "}, true);"
658
- "window.addEventListener(eventName, function(e) {"
659
- "e.preventDefault();"
660
- "e.stopPropagation();"
661
- "}, true);"
662
- "});"
663
- "})();";
664
-
665
- WKUserScript *userScript = [[WKUserScript alloc]
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 (!wv.pImpl->config.scrollbars) {
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
- wv.pImpl->wkWebView =
719
+ win.pImpl->wkWebView =
690
720
  [[WKWebView alloc] initWithFrame:parentView.bounds configuration:config];
691
- [parentView addSubview:wv.pImpl->wkWebView];
721
+ [parentView addSubview:win.pImpl->wkWebView];
692
722
 
693
- wv.pImpl->nativeWebView = (__bridge void *)wv.pImpl->wkWebView;
723
+ win.pImpl->nativeWebView = (__bridge void *)win.pImpl->wkWebView;
694
724
 
695
725
  #endif
696
726
 
697
- wv.pImpl->windowManager = std::make_unique<WindowManager>(windowHandle);
698
- wv.pImpl->trayManager = std::make_unique<TrayManager>();
699
- wv.pImpl->trayManager->setWindowHandle(windowHandle);
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 wv;
731
+ return win;
702
732
  }
703
733
 
704
- TrayManager &WebView::tray() { return *pImpl->trayManager; }
705
- WindowManager &WebView::window() { return *pImpl->windowManager; }
734
+ TrayManager &Window::tray() { return *pImpl->trayManager; }
735
+ WindowManager &Window::window() { return *pImpl->windowManager; }
706
736
 
707
- void WebView::setWindow(std::shared_ptr<Window> win) {
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 WebView::on(const std::string &event,
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 WebView::emit(const std::string &event, const std::string &data) {
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 WebView::navigate(const std::string &url) {
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 WebView::loadHTML(const std::string &html) {
814
+ void Window::loadHTML(const std::string &html) {
785
815
  loadHTML(html, "about:blank");
786
816
  }
787
817
 
788
- void WebView::loadHTML(const std::string &html, const std::string &baseURL) {
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 WebView::loadFile(const std::string &filePath) {
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 WebView::reload() {
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 WebView::stop() {
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 WebView::goBack() {
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 WebView::goForward() {
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 WebView::canGoBack() const {
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 WebView::canGoForward() const {
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 WebView::executeScript(const std::string &script) {
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 WebView::executeScript(const std::string &script,
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 WebView::bind(const std::string &name, JSCallback callback) {
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 WebView::unbind(const std::string &name) {
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 WebView::openDevTools() {
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 WebView::closeDevTools() {
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 WebView::setUserAgent(const std::string &userAgent) {
1042
- pImpl->config.userAgent = userAgent;
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 WebView::getUserAgent() const { return pImpl->config.userAgent; }
1093
+ std::string Window::getUserAgent() const { return pImpl->userAgent; }
1064
1094
 
1065
- void WebView::setZoom(double factor) {
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 WebView::getZoom() const { return pImpl->zoom; }
1113
+ double Window::getZoom() const { return pImpl->zoom; }
1084
1114
 
1085
- void WebView::injectCSS(const std::string &css) {
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 WebView::onNavigationStart(NavigationCallback callback) {
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 WebView::onNavigationComplete(LoadCallback callback) {
1171
+ void Window::onNavigationComplete(LoadCallback callback) {
1103
1172
  pImpl->navigationCompleteCallback = callback;
1104
1173
  }
1105
1174
 
1106
- void WebView::onLoadStart(LoadCallback callback) {
1175
+ void Window::onLoadStart(LoadCallback callback) {
1107
1176
  pImpl->loadStartCallback = callback;
1108
1177
  }
1109
1178
 
1110
- void WebView::onLoadEnd(LoadCallback callback) {
1179
+ void Window::onLoadEnd(LoadCallback callback) {
1111
1180
  pImpl->loadEndCallback = callback;
1112
1181
  }
1113
1182
 
1114
- void WebView::onLoadError(ErrorCallback callback) {
1183
+ void Window::onLoadError(ErrorCallback callback) {
1115
1184
  pImpl->errorCallback = callback;
1116
1185
  }
1117
1186
 
1118
- void WebView::onConsoleMessage(ConsoleCallback callback) {
1187
+ void Window::onConsoleMessage(ConsoleCallback callback) {
1119
1188
  pImpl->consoleCallback = callback;
1120
1189
  }
1121
1190
 
1122
- bool WebView::isLoading() const { return pImpl->loading; }
1191
+ bool Window::isLoading() const { return pImpl->loading; }
1123
1192
 
1124
- std::string WebView::getURL() const { return pImpl->currentURL; }
1193
+ std::string Window::getURL() const { return pImpl->currentURL; }
1125
1194
 
1126
- std::string WebView::getTitle() const { return pImpl->currentTitle; }
1195
+ std::string Window::getTitle() const { return pImpl->currentTitle; }
1127
1196
 
1128
- void *WebView::nativeHandle() const { return pImpl->nativeWebView; }
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 "webview.hpp"
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
- WebView build();
65
+ Window build();
64
66
 
65
67
  private:
66
68
  Config config;
@@ -35,6 +35,5 @@
35
35
  #include <plusui/native_bindings.hpp>
36
36
  #include <plusui/tray.hpp>
37
37
  #include <plusui/webgpu.hpp>
38
- #include <plusui/webview.hpp>
39
38
  #include <plusui/window.hpp>
40
39
  #include <plusui/window_manager.hpp>
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "plusui-native-core",
3
- "version": "0.1.23",
3
+ "version": "0.1.26",
4
4
  "description": "PlusUI Core framework (frontend + backend implementations)",
5
5
  "type": "module",
6
6
  "files": [
@@ -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