From ab008f64fbbca23cb31ce00d97027e66a0bf7608 Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Sun, 7 Dec 2025 07:51:54 +0500 Subject: [PATCH 01/21] Add WebView2 Rainmeter plugin with bang command support and an example skin. --- Build-CPP.ps1 | 2 +- .../WebView2/BangCommand/BangCommand.ini | 23 ++++++++++++++++--- WebView2/Plugin.cpp | 10 ++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Build-CPP.ps1 b/Build-CPP.ps1 index c05a923..238d8fb 100644 --- a/Build-CPP.ps1 +++ b/Build-CPP.ps1 @@ -1,4 +1,4 @@ -#usage -----> powershell -ExecutionPolicy Bypass -Command "& {. .\Build-CPP.ps1; Dist -major 0 -minor 0 -patch 5}" +#usage -----> powershell -ExecutionPolicy Bypass -Command "& {. .\Build-CPP.ps1; Dist -major 0 -minor 0 -patch 6}" $msbuild = "C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin\MSBuild.exe" function Add-RMSkinFooter { diff --git a/Resources/Skins/WebView2/BangCommand/BangCommand.ini b/Resources/Skins/WebView2/BangCommand/BangCommand.ini index 8de6710..b0a7fc0 100644 --- a/Resources/Skins/WebView2/BangCommand/BangCommand.ini +++ b/Resources/Skins/WebView2/BangCommand/BangCommand.ini @@ -13,10 +13,11 @@ License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 [Variables] WebURL=https://nstechbytes.pages.dev/ WebW=600 -WebH=350 +WebH=410 WebX=300 -WebY=25 +WebY=45 Hidden=0 +ClickThrough=0 ; ======================================== ; Measure ; ======================================== @@ -29,6 +30,7 @@ H=#WebH# X=#WebX# Y=#WebY# Hidden=#Hidden# +ClickThrough=#ClickThrough# DynamicVariables=1 ; ======================================== @@ -36,7 +38,7 @@ DynamicVariables=1 ; ======================================== [MeterBackground] Meter=Shape -Shape=Rectangle 0,0,950,420,12 | FillColor 0,0,0,200 | StrokeWidth 0 +Shape=Rectangle 0,0,950,480,12 | FillColor 0,0,0,200 | StrokeWidth 0 [Title] Meter=String @@ -179,5 +181,20 @@ X=150 Y=388 LeftMouseUpAction=[!SetVariable WebY 50][!UpdateMeasure MeasureWebView][!Redraw] +[TxtSetEnableClickThrough] +Meter=String +MeterStyle=StyleButtonText +Text=Set ClickThrough: 1 (via Variable) +X=150 +Y=418 +LeftMouseUpAction=[!SetVariable ClickThrough 1][!UpdateMeasure MeasureWebView][!Redraw] + +[TxtSetDisableClickThrough] +Meter=String +MeterStyle=StyleButtonText +Text=Set ClickThrough: 0 (via Variable) +X=150 +Y=448 +LeftMouseUpAction=[!SetVariable ClickThrough 0][!UpdateMeasure MeasureWebView][!Redraw] diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index cc41929..239d3aa 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -114,6 +114,16 @@ void UpdateClickthrough(Measure* measure) // EnableWindow(FALSE) makes it ignore mouse input (Clickthrough=1) // EnableWindow(TRUE) makes it accept mouse input (Clickthrough=0) EnableWindow(child, !measure->clickthrough); + + // If enabling clickthrough (disabling input), ensure it loses focus + if (measure->clickthrough) + { + HWND focusedWindow = GetFocus(); + if (focusedWindow && (focusedWindow == child || IsChild(child, focusedWindow))) + { + SetFocus(nullptr); + } + } child = GetWindow(child, GW_HWNDNEXT); } From 9388022b72d3a1fbeb4f2168efc5d28f66a65b3f Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:41:59 -0600 Subject: [PATCH 02/21] Add new member variables for action handling Added isCreationInProgress boolean and onFinishAction and onPageLoadAction --- WebView2/Plugin.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WebView2/Plugin.h b/WebView2/Plugin.h index 0ea5939..a7f650a 100644 --- a/WebView2/Plugin.h +++ b/WebView2/Plugin.h @@ -29,7 +29,10 @@ struct Measure bool visible; bool initialized; bool clickthrough; - + bool isCreationInProgress = false; + std::wstring onFinishAction; + std::wstring onPageLoadAction; + wil::com_ptr webViewController; wil::com_ptr webView; EventRegistrationToken webMessageToken; From aa35a930ee175806bb983d6aeb8aa7ec9d058f90 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:44:54 -0600 Subject: [PATCH 03/21] Add OnFinishAction and OnPageLoadAction handling Added OnFinishAction and OnPageLoadAction handling and fixed a race condition when creating WebView by using the new isCreationInProgress boolean. --- WebView2/Plugin.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index 239d3aa..66b0ad9 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -185,9 +185,26 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) bool newVisible = RmReadInt(rm, L"Hidden", 0) == 0; bool newClickthrough = RmReadInt(rm, L"Clickthrough", 0) != 0; + // Read OnFinishAction + std::wstring newOnFinishAction; + LPCWSTR onFinishOption = RmReadString(rm, L"OnFinishAction", L"", FALSE); + if (onFinishOption && wcslen(onFinishOption) > 0) + { + newOnFinishAction = onFinishOption; + } + + // Read OnPageLoadAction + std::wstring newOnPageLoadAction; + LPCWSTR onPageLoadOption = RmReadString(rm, L"OnPageLoadAction", L"", FALSE); + if (onPageLoadOption && wcslen(onPageLoadOption) > 0) + { + newOnPageLoadAction = onPageLoadOption; + } + // Check if URL has changed (requires recreation) bool urlChanged = (newUrl != measure->url); + // Check if dimensions or position changed (can be updated dynamically) bool dimensionsChanged = (newWidth != measure->width || newHeight != measure->height || @@ -205,7 +222,9 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) measure->y = newY; measure->visible = newVisible; measure->clickthrough = newClickthrough; - + measure->onFinishAction = newOnFinishAction; + measure->onPageLoadAction = newOnPageLoadAction; + // Only create WebView2 if not initialized OR if URL changed if (!measure->initialized || urlChanged) { @@ -220,7 +239,13 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) else { // First initialization - create WebView2 + if (measure->isCreationInProgress) + { + // Avoid re-entrancy if creation is already in progress + return; + } CreateWebView2(measure); + } } else From 67d78120fea1edb1e8d31fb090da2d412b9d4fcc Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:48:13 -0600 Subject: [PATCH 04/21] Prevent multiple creation of WebView2 environment Added checks to prevent multiple creation attempts of WebView2 environment and controller. Removed unnecessary global meter and redraw bangs. Changed Initialized notice to debug. Added onPageLoadAction and onFinishAction. --- WebView2/WebView2.cpp | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/WebView2/WebView2.cpp b/WebView2/WebView2.cpp index a3db632..854b2e9 100644 --- a/WebView2/WebView2.cpp +++ b/WebView2/WebView2.cpp @@ -6,12 +6,19 @@ // Create WebView2 environment and controller void CreateWebView2(Measure* measure) { + if (measure && measure->isCreationInProgress) + { + return; + } + if (!measure || !measure->skinWindow) { if (measure && measure->rm) RmLog(measure->rm, LOG_ERROR, L"WebView2: Invalid measure or skin window"); return; } + + measure->isCreationInProgress = true; // Create user data folder in TEMP directory to avoid permission issues wchar_t tempPath[MAX_PATH]; @@ -28,6 +35,7 @@ void CreateWebView2(Measure* measure) measure, &Measure::CreateEnvironmentHandler ).Get() + ); if (FAILED(hr)) @@ -46,6 +54,7 @@ HRESULT Measure::CreateEnvironmentHandler(HRESULT result, ICoreWebView2Environme { if (FAILED(result)) { + isCreationInProgress = false; if (rm) { wchar_t errorMsg[256]; @@ -70,6 +79,7 @@ HRESULT Measure::CreateEnvironmentHandler(HRESULT result, ICoreWebView2Environme // Controller creation callback HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller* controller) { + if (FAILED(result)) { if (rm) @@ -78,6 +88,7 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller swprintf_s(errorMsg, L"WebView2: Failed to create controller (HRESULT: 0x%08X)", result); RmLog(rm, LOG_ERROR, errorMsg); } + isCreationInProgress = false; return result; } @@ -85,6 +96,7 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller { if (rm) RmLog(rm, LOG_ERROR, L"WebView2: Controller is null"); + isCreationInProgress = false; return S_FALSE; } @@ -166,16 +178,15 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller // Store the callback result if (!result.empty() && result != L"null") { - callbackResult = result; - - // Trigger Rainmeter redraw after callback completes - if (skin) - { - RmExecute(skin, L"!UpdateMeter *"); - RmExecute(skin, L"!Redraw"); - } + callbackResult = result; } } + + if (wcslen(onPageLoadAction.c_str()) > 0) + { + RmExecute(skin, onPageLoadAction.c_str()); + } + return S_OK; } ).Get() @@ -194,11 +205,19 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller initialized = true; + isCreationInProgress = false; + if (rm) - RmLog(rm, LOG_NOTICE, L"WebView2: Initialized successfully with COM Host Objects"); + RmLog(rm, LOG_DEBUG, L"WebView2: Initialized successfully with COM Host Objects"); + if (wcslen(onFinishAction.c_str()) > 0) + { + RmExecute(skin, onFinishAction.c_str()); + } + // Apply initial clickthrough state UpdateClickthrough(this); return S_OK; } + From c3643f743b9f5d92836073c85df6011835d07896 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Mon, 8 Dec 2025 01:34:14 -0600 Subject: [PATCH 05/21] Refactor WebView2 creation logic for better validation Re-ordered creation check added check for initialization added missing reset when hr fails. --- WebView2/WebView2.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/WebView2/WebView2.cpp b/WebView2/WebView2.cpp index 854b2e9..5b51a7c 100644 --- a/WebView2/WebView2.cpp +++ b/WebView2/WebView2.cpp @@ -6,15 +6,20 @@ // Create WebView2 environment and controller void CreateWebView2(Measure* measure) { - if (measure && measure->isCreationInProgress) + if (!measure || !measure->skinWindow) { + if (measure && measure->rm) + RmLog(measure->rm, LOG_ERROR, L"WebView2: Invalid measure or skin window"); return; } - if (!measure || !measure->skinWindow) + if (measure->initialized) + { + return; + } + + if (measure->isCreationInProgress) { - if (measure && measure->rm) - RmLog(measure->rm, LOG_ERROR, L"WebView2: Invalid measure or skin window"); return; } @@ -40,6 +45,7 @@ void CreateWebView2(Measure* measure) if (FAILED(hr)) { + measure->isCreationInProgress = false; if (measure->rm) { wchar_t errorMsg[512]; From 8e1c7f2ac0abc8ba3f1a5f829681468084e1be5b Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Mon, 8 Dec 2025 17:21:16 -0600 Subject: [PATCH 06/21] Remove unnecessary Rainmeter redraw triggers Removed redundant redraw calls after callback completion. This was causing CallJS to execute twice.. --- WebView2/Plugin.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index 66b0ad9..49c02e2 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -300,13 +300,6 @@ PLUGIN_EXPORT double Update(void* data) { measure->callbackResult = result; } - - // Trigger Rainmeter redraw after callback completes - if (measure->skin) - { - RmExecute(measure->skin, L"!UpdateMeter *"); - RmExecute(measure->skin, L"!Redraw"); - } } return S_OK; } From e0111e18e319db154d709db96fc3be749c03280d Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Mon, 8 Dec 2025 23:31:56 -0600 Subject: [PATCH 07/21] Implement synchronous script execution in WebView2 Ok, here's my attempt to solve the sync issue. Unfortunately, all my attempts to add a similar solution for window.OnInitialize and CallJS failed, both create a deadlock when implemented this way. However, this appears to solve the issue on window.OnUpdate which I think is the most important. Please build my Working2 branch and test it, you should see now both Status: Update #N on Rainmeter and on WebView are correctly synced. As well as the Measure's string value. Also add OnPageLoadAction=[!UpdateMeter *][!Redraw] on the WebView measure to correctly see the "Initialized!" message on the status string. --- WebView2/Plugin.cpp | 130 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 27 deletions(-) diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index 49c02e2..94c456e 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2025 nstechbytes. All rights reserved. #include "Plugin.h" #include "../API/RainmeterAPI.h" +#include #pragma comment(lib, "ole32.lib") #pragma comment(lib, "oleaut32.lib") @@ -274,40 +275,114 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) } } +// Synchronously execute script on the same thread as the WebView (pumps messages). +static std::wstring ExecuteScriptSync(ICoreWebView2* webview, const std::wstring& script, DWORD timeoutMs = 300) +{ + if (!webview) return L""; + + HANDLE hEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (!hEvent) return L""; + + std::wstring resultJson; + HRESULT execHr = E_FAIL; + + auto handler = Callback( + [&resultJson, &execHr, hEvent](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + execHr = errorCode; + if (SUCCEEDED(errorCode) && resultObjectAsJson) + { + resultJson.assign(resultObjectAsJson); + } + SetEvent(hEvent); + return S_OK; + } + ); + + HRESULT hr = webview->ExecuteScript(script.c_str(), handler.Get()); + if (FAILED(hr)) + { + CloseHandle(hEvent); + return L""; + } + + auto start = std::chrono::steady_clock::now(); + for (;;) + { + auto elapsed = std::chrono::duration_cast( + std::chrono::steady_clock::now() - start).count(); + DWORD remaining = (elapsed >= timeoutMs) ? 0 : static_cast(timeoutMs - elapsed); + + DWORD wait = ::MsgWaitForMultipleObjects(1, &hEvent, FALSE, remaining, QS_ALLINPUT); + + if (wait == WAIT_OBJECT_0) + { + // event signaled + break; + } + else if (wait == WAIT_OBJECT_0 + 1) + { + // pump messages so callback runs + MSG msg; + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + // continue loop (respect remaining timeout) + } + else if (wait == WAIT_TIMEOUT) + { + // timeout; break and treat as failure/empty + break; + } + else + { + // unexpected error; break + break; + } + } + + CloseHandle(hEvent); + + if (FAILED(execHr)) + { + return L""; + } + + return resultJson; +} + PLUGIN_EXPORT double Update(void* data) { Measure* measure = (Measure*)data; - // Call JavaScript OnUpdate callback if WebView is initialized - if (measure->initialized && measure->webView) + // If not initialized return 0.0 + if (!measure->initialized || !measure->webView) + return 0.0; + + std::wstring script = L"(function() { try { if (typeof window.OnUpdate === 'function') { var result = window.OnUpdate(); return result !== undefined ? String(result) : ''; } return ''; } catch(e) { return ''; } })();"; + + // Synchronously execute the script on the plugin main thread, pumping messages. + std::wstring json = ExecuteScriptSync(measure->webView.get(), script, 500); + + if (!json.empty()) { - measure->webView->ExecuteScript( - L"(function() { if (typeof window.OnUpdate === 'function') { var result = window.OnUpdate(); return result !== undefined ? String(result) : ''; } return ''; })();", - Callback( - [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT - { - if (SUCCEEDED(errorCode) && resultObjectAsJson) - { - // Remove quotes from JSON string result - std::wstring result = resultObjectAsJson; - if (result.length() >= 2 && result.front() == L'"' && result.back() == L'"') - { - result = result.substr(1, result.length() - 2); - } - - // Store the callback result - if (!result.empty() && result != L"null") - { - measure->callbackResult = result; - } - } - return S_OK; - } - ).Get() - ); + std::wstring result = json; + if (result.length() >= 2 && result.front() == L'"' && result.back() == L'"') + { + result = result.substr(1, result.length() - 2); + } + + // Store the latest result + if (!result.empty() && result != L"null") + { + measure->callbackResult = result; + } } - return measure->initialized ? 1.0 : 0.0; + // Return 1.0 when initialized + return 1.0; } PLUGIN_EXPORT LPCWSTR GetString(void* data) @@ -322,6 +397,7 @@ PLUGIN_EXPORT LPCWSTR GetString(void* data) return L"0"; } + PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) { Measure* measure = (Measure*)data; From 38992007632d59f1cc4815b44438c5d8e124fac7 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:38:44 -0600 Subject: [PATCH 08/21] Restore to previous working version. Removed synchronous script execution function and adjusted script execution logic in Update function. --- WebView2/Plugin.cpp | 130 ++++++++++---------------------------------- 1 file changed, 28 insertions(+), 102 deletions(-) diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index 94c456e..9e790c5 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -1,7 +1,6 @@ // Copyright (C) 2025 nstechbytes. All rights reserved. #include "Plugin.h" #include "../API/RainmeterAPI.h" -#include #pragma comment(lib, "ole32.lib") #pragma comment(lib, "oleaut32.lib") @@ -275,114 +274,41 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) } } -// Synchronously execute script on the same thread as the WebView (pumps messages). -static std::wstring ExecuteScriptSync(ICoreWebView2* webview, const std::wstring& script, DWORD timeoutMs = 300) -{ - if (!webview) return L""; - - HANDLE hEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); - if (!hEvent) return L""; - - std::wstring resultJson; - HRESULT execHr = E_FAIL; - - auto handler = Callback( - [&resultJson, &execHr, hEvent](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT - { - execHr = errorCode; - if (SUCCEEDED(errorCode) && resultObjectAsJson) - { - resultJson.assign(resultObjectAsJson); - } - SetEvent(hEvent); - return S_OK; - } - ); - - HRESULT hr = webview->ExecuteScript(script.c_str(), handler.Get()); - if (FAILED(hr)) - { - CloseHandle(hEvent); - return L""; - } - - auto start = std::chrono::steady_clock::now(); - for (;;) - { - auto elapsed = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start).count(); - DWORD remaining = (elapsed >= timeoutMs) ? 0 : static_cast(timeoutMs - elapsed); - - DWORD wait = ::MsgWaitForMultipleObjects(1, &hEvent, FALSE, remaining, QS_ALLINPUT); - - if (wait == WAIT_OBJECT_0) - { - // event signaled - break; - } - else if (wait == WAIT_OBJECT_0 + 1) - { - // pump messages so callback runs - MSG msg; - while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - // continue loop (respect remaining timeout) - } - else if (wait == WAIT_TIMEOUT) - { - // timeout; break and treat as failure/empty - break; - } - else - { - // unexpected error; break - break; - } - } - - CloseHandle(hEvent); - - if (FAILED(execHr)) - { - return L""; - } - - return resultJson; -} - PLUGIN_EXPORT double Update(void* data) { Measure* measure = (Measure*)data; - // If not initialized return 0.0 - if (!measure->initialized || !measure->webView) - return 0.0; - - std::wstring script = L"(function() { try { if (typeof window.OnUpdate === 'function') { var result = window.OnUpdate(); return result !== undefined ? String(result) : ''; } return ''; } catch(e) { return ''; } })();"; - - // Synchronously execute the script on the plugin main thread, pumping messages. - std::wstring json = ExecuteScriptSync(measure->webView.get(), script, 500); - - if (!json.empty()) + // Call JavaScript OnUpdate callback if WebView is initialized + if (measure->initialized && measure->webView) { - std::wstring result = json; - if (result.length() >= 2 && result.front() == L'"' && result.back() == L'"') - { - result = result.substr(1, result.length() - 2); - } - - // Store the latest result - if (!result.empty() && result != L"null") - { - measure->callbackResult = result; - } + measure->webView->ExecuteScript( + L"(function() { if (typeof window.OnUpdate === 'function') { var result = window.OnUpdate(); return result !== undefined ? String(result) : ''; } return ''; })();", + Callback( + [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + if (SUCCEEDED(errorCode) && resultObjectAsJson) + { + // Remove quotes from JSON string result + std::wstring result = resultObjectAsJson; + if (result.length() >= 2 && result.front() == L'"' && result.back() == L'"') + { + result = result.substr(1, result.length() - 2); + } + + // Store the callback result + if (!result.empty() && result != L"null") + { + measure->callbackResult = result; + } + + } + return S_OK; + } + ).Get() + ); } - // Return 1.0 when initialized - return 1.0; + return measure->initialized ? 1.0 : 0.0; } PLUGIN_EXPORT LPCWSTR GetString(void* data) From fcfc0772abdf6eeb1d64a0909c03cfe2ecc508f5 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:28:34 -0600 Subject: [PATCH 09/21] Add new properties and UpdateRaincontext function Renamed `OnFinishAction` to `OnWebViewLoadAction` Added actions: `OnWebViewFailAction` `OnPageFirstLoadAction` `OnPageReloadAction` Added `raincontext` and `isFirstLoad` booleans. Added `UpdateRaincontext()` function. --- WebView2/Plugin.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/WebView2/Plugin.h b/WebView2/Plugin.h index a7f650a..5a0ce63 100644 --- a/WebView2/Plugin.h +++ b/WebView2/Plugin.h @@ -30,8 +30,13 @@ struct Measure bool initialized; bool clickthrough; bool isCreationInProgress = false; - std::wstring onFinishAction; + bool raincontext; + std::wstring OnWebViewLoadAction; + std::wstring OnWebViewFailAction; + std::wstring onPageFirstLoadAction; std::wstring onPageLoadAction; + std::wstring onPageReloadAction; + bool isFirstLoad = true; wil::com_ptr webViewController; wil::com_ptr webView; @@ -52,4 +57,5 @@ struct Measure // WebView2 functions void CreateWebView2(Measure* measure); void UpdateClickthrough(Measure* measure); +void UpdateRaincontext(Measure* measure); From b48bf009af036a87f0a015a2c525dedb262891b2 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:40:27 -0600 Subject: [PATCH 10/21] Add raincontext management to Measure class Added raincontext handling to the Measure class, including updates to the Reload function for new actions. Implemented UpdateRaincontext function to manage the raincontext state within the WebView. --- WebView2/Plugin.cpp | 106 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 22 deletions(-) diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index 9e790c5..8f4cab5 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -52,7 +52,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) Measure::Measure() : rm(nullptr), skin(nullptr), skinWindow(nullptr), measureName(nullptr), width(800), height(600), x(0), y(0), - visible(true), initialized(false), clickthrough(false), webMessageToken{} + visible(true), initialized(false), clickthrough(false), raincontext(true), webMessageToken{} { // Initialize COM for this thread if not already done if (!g_comInitialized) @@ -129,6 +129,35 @@ void UpdateClickthrough(Measure* measure) } } +void UpdateRaincontext(Measure* measure) +{ + if (!measure->webView) return; + + if (measure->raincontext) + { + measure->webView->ExecuteScript( + L"rm_setRaincontext(true);", + Callback( + [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + return S_OK; + } + ).Get() + ); + } + else { + measure->webView->ExecuteScript( + L"rm_setRaincontext(false);", + Callback( + [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + return S_OK; + } + ).Get() + ); + } +} + PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) { Measure* measure = (Measure*)data; @@ -182,24 +211,49 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) int newHeight = RmReadInt(rm, L"H", 600); int newX = RmReadInt(rm, L"X", 0); int newY = RmReadInt(rm, L"Y", 0); - bool newVisible = RmReadInt(rm, L"Hidden", 0) == 0; - bool newClickthrough = RmReadInt(rm, L"Clickthrough", 0) != 0; + bool newVisible = RmReadInt(rm, L"Hidden", 0) <= 0; + bool newClickthrough = RmReadInt(rm, L"Clickthrough", 0) >= 1; + bool newRaincontext = RmReadInt(rm, L"Raincontext", 1) >= 1; - // Read OnFinishAction - std::wstring newOnFinishAction; - LPCWSTR onFinishOption = RmReadString(rm, L"OnFinishAction", L"", FALSE); - if (onFinishOption && wcslen(onFinishOption) > 0) - { - newOnFinishAction = onFinishOption; - } + // Read OnWebViewLoadAction + std::wstring newOnWebViewLoadAction; + LPCWSTR onWebViewLoadOption = RmReadString(rm, L"OnWebViewLoadAction", L"", FALSE); + if (onWebViewLoadOption && wcslen(onWebViewLoadOption) > 0) + { + newOnWebViewLoadAction = onWebViewLoadOption; + } + + // Read OnWebViewFailAction + std::wstring newOnWebViewFailAction; + LPCWSTR onWebViewFailOption = RmReadString(rm, L"OnWebViewFailAction", L"", FALSE); + if (onWebViewFailOption && wcslen(onWebViewFailOption) > 0) + { + newOnWebViewFailAction = onWebViewFailOption; + } - // Read OnPageLoadAction - std::wstring newOnPageLoadAction; - LPCWSTR onPageLoadOption = RmReadString(rm, L"OnPageLoadAction", L"", FALSE); - if (onPageLoadOption && wcslen(onPageLoadOption) > 0) - { - newOnPageLoadAction = onPageLoadOption; - } + // Read OnPageFirstLoadAction + std::wstring newOnPageFirstLoadAction; + LPCWSTR onPageFirstLoadOption = RmReadString(rm, L"OnPageFirstLoadAction", L"", FALSE); + if (onPageFirstLoadOption && wcslen(onPageFirstLoadOption) > 0) + { + newOnPageFirstLoadAction = onPageFirstLoadOption; + } + + // Read OnPageLoadAction + std::wstring newOnPageLoadAction; + LPCWSTR onPageLoadOption = RmReadString(rm, L"OnPageLoadAction", L"", FALSE); + if (onPageLoadOption && wcslen(onPageLoadOption) > 0) + { + newOnPageLoadAction = onPageLoadOption; + } + + // Read OnPageReloadAction + std::wstring newOnPageReloadAction; + LPCWSTR onPageReloadOption = RmReadString(rm, L"OnPageReloadAction", L"", FALSE); + if (onPageReloadOption && wcslen(onPageReloadOption) > 0) + { + newOnPageReloadAction = onPageReloadOption; + } // Check if URL has changed (requires recreation) bool urlChanged = (newUrl != measure->url); @@ -213,7 +267,8 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) bool visibilityChanged = (newVisible != measure->visible); bool clickthroughChanged = (newClickthrough != measure->clickthrough); - + bool raincontextChanged = (newRaincontext != measure->raincontext); + // Update stored values measure->url = newUrl; measure->width = newWidth; @@ -222,8 +277,12 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) measure->y = newY; measure->visible = newVisible; measure->clickthrough = newClickthrough; - measure->onFinishAction = newOnFinishAction; - measure->onPageLoadAction = newOnPageLoadAction; + measure->raincontext = newRaincontext; + measure->OnWebViewLoadAction = newOnWebViewLoadAction; + measure->OnWebViewFailAction = newOnWebViewFailAction; + measure->onPageFirstLoadAction = newOnPageFirstLoadAction; + measure->onPageLoadAction = newOnPageLoadAction; + measure->onPageReloadAction = newOnPageReloadAction; // Only create WebView2 if not initialized OR if URL changed if (!measure->initialized || urlChanged) @@ -245,7 +304,6 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) return; } CreateWebView2(measure); - } } else @@ -271,6 +329,11 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) { UpdateClickthrough(measure); } + + if (raincontextChanged) + { + UpdateRaincontext(measure); + } } } @@ -300,7 +363,6 @@ PLUGIN_EXPORT double Update(void* data) { measure->callbackResult = result; } - } return S_OK; } From edb5084af8e1c182c7088b143c181537bff447b3 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:04:51 -0600 Subject: [PATCH 11/21] Added handling of new actions and raincontext. --- WebView2/WebView2.cpp | 71 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/WebView2/WebView2.cpp b/WebView2/WebView2.cpp index 5b51a7c..f3c3533 100644 --- a/WebView2/WebView2.cpp +++ b/WebView2/WebView2.cpp @@ -45,13 +45,17 @@ void CreateWebView2(Measure* measure) if (FAILED(hr)) { - measure->isCreationInProgress = false; if (measure->rm) { wchar_t errorMsg[512]; swprintf_s(errorMsg, L"WebView2: Failed to start creation process (HRESULT: 0x%08X). Make sure WebView2 Runtime is installed.", hr); RmLog(measure->rm, LOG_ERROR, errorMsg); } + if (measure->skin && wcslen(measure->OnWebViewFailAction.c_str()) > 0) + { + RmExecute(measure->skin, measure->OnWebViewFailAction.c_str()); + } + measure->isCreationInProgress = false; } } @@ -60,13 +64,17 @@ HRESULT Measure::CreateEnvironmentHandler(HRESULT result, ICoreWebView2Environme { if (FAILED(result)) { - isCreationInProgress = false; if (rm) { wchar_t errorMsg[256]; swprintf_s(errorMsg, L"WebView2: Failed to create environment (HRESULT: 0x%08X)", result); RmLog(rm, LOG_ERROR, errorMsg); } + if (skin && wcslen(OnWebViewFailAction.c_str()) > 0) + { + RmExecute(skin, OnWebViewFailAction.c_str()); + } + isCreationInProgress = false; return result; } @@ -94,6 +102,10 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller swprintf_s(errorMsg, L"WebView2: Failed to create controller (HRESULT: 0x%08X)", result); RmLog(rm, LOG_ERROR, errorMsg); } + if (skin && wcslen(OnWebViewFailAction.c_str()) > 0) + { + RmExecute(skin, OnWebViewFailAction.c_str()); + } isCreationInProgress = false; return result; } @@ -102,6 +114,10 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller { if (rm) RmLog(rm, LOG_ERROR, L"WebView2: Controller is null"); + if (skin && wcslen(OnWebViewFailAction.c_str()) > 0) + { + RmExecute(skin, OnWebViewFailAction.c_str()); + } isCreationInProgress = false; return S_FALSE; } @@ -166,6 +182,20 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller Callback( [this](ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT { + // Inject script to capture page load events for drag/move and context menu + webView->ExecuteScript( + L"let rm_raincontext=false,rm_RaincontextOn=false,rm_RaincontextClientX=0,rm_RaincontextClientY=0;function rm_setRaincontext(v){rm_raincontext=!!v;if(!rm_raincontext)rm_RaincontextOn=false;}document.body.onpointerdown=e=>{if(!rm_raincontext)return;if(e.button===0&&e.ctrlKey){e.preventDefault();e.stopImmediatePropagation();rm_RaincontextOn=true;rm_RaincontextClientX=e.clientX;rm_RaincontextClientY=e.clientY;try{document.body.setPointerCapture(e.pointerId);}catch{}}};document.body.onpointermove=e=>{if(!rm_raincontext||!rm_RaincontextOn)return;e.preventDefault();RainmeterAPI.Bang('[!Move '+(e.screenX-RainmeterAPI.ReadFormula('X',0)-rm_RaincontextClientX)+' '+(e.screenY-RainmeterAPI.ReadFormula('Y',0)-rm_RaincontextClientY)+']');};document.body.onpointerup=e=>{if(!rm_raincontext)return;if(e.button===0){e.preventDefault();rm_RaincontextOn=false;try{document.body.releasePointerCapture(e.pointerId);}catch{}}};document.body.oncontextmenu=e=>{if(!rm_raincontext)return;if(e.button===2&&e.ctrlKey){e.preventDefault();RainmeterAPI.Bang('[!SkinMenu]');}};", + Callback( + [this](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + return S_OK; + } + ).Get() + ); + + // Apply initial raincontext state + UpdateRaincontext(this); + // Call JavaScript OnInitialize callback if it exists and capture return value webView->ExecuteScript( L"(function() { if (typeof window.OnInitialize === 'function') { var result = window.OnInitialize(); return result !== undefined ? String(result) : ''; } return ''; })();", @@ -188,10 +218,28 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller } } - if (wcslen(onPageLoadAction.c_str()) > 0) - { - RmExecute(skin, onPageLoadAction.c_str()); - } + if (isFirstLoad) + { + if (wcslen(onPageFirstLoadAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageFirstLoadAction.c_str()); + } + isFirstLoad = false; + } + else { + if (wcslen(onPageReloadAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageReloadAction.c_str()); + } + } + + if (wcslen(onPageLoadAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageLoadAction.c_str()); + } return S_OK; } @@ -214,16 +262,15 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller isCreationInProgress = false; if (rm) - RmLog(rm, LOG_DEBUG, L"WebView2: Initialized successfully with COM Host Objects"); + RmLog(rm, LOG_NOTICE, L"WebView2: Initialized successfully with COM Host Objects"); - if (wcslen(onFinishAction.c_str()) > 0) - { - RmExecute(skin, onFinishAction.c_str()); - } + if (wcslen(OnWebViewLoadAction.c_str()) > 0) + { + RmExecute(skin, OnWebViewLoadAction.c_str()); + } // Apply initial clickthrough state UpdateClickthrough(this); return S_OK; } - From 8e397a91a2795113d08ba63789a1adcbe17e06db Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:40:48 -0600 Subject: [PATCH 12/21] Refactor for dual control handling Added new actions. --- WebView2/Plugin.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/WebView2/Plugin.h b/WebView2/Plugin.h index 5a0ce63..b554e40 100644 --- a/WebView2/Plugin.h +++ b/WebView2/Plugin.h @@ -30,13 +30,17 @@ struct Measure bool initialized; bool clickthrough; bool isCreationInProgress = false; - bool raincontext; - std::wstring OnWebViewLoadAction; - std::wstring OnWebViewFailAction; + bool isFirstLoad = true; + bool allowDualControl; + bool isAllowDualControlInjected = false; + + std::wstring onWebViewLoadAction; + std::wstring onWebViewFailAction; std::wstring onPageFirstLoadAction; - std::wstring onPageLoadAction; + std::wstring onPageLoadStartAction; + std::wstring onPageLoadingAction; + std::wstring onPageLoadFinishAction; std::wstring onPageReloadAction; - bool isFirstLoad = true; wil::com_ptr webViewController; wil::com_ptr webView; @@ -57,5 +61,7 @@ struct Measure // WebView2 functions void CreateWebView2(Measure* measure); void UpdateClickthrough(Measure* measure); -void UpdateRaincontext(Measure* measure); +void InjectAllowDualControl(Measure* measure); +void UpdateAllowDualControl(Measure* measure); + From 90c430d2a5898028826fab839390835eaa54ad19 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:51:40 -0600 Subject: [PATCH 13/21] Implement AllowDualControl feature Raincontext is now called AllowDualControl. The script is no longer injected when the option is disabled. Added new actions. --- WebView2/Plugin.cpp | 151 ++++++++++++++++++++++++++++---------------- 1 file changed, 97 insertions(+), 54 deletions(-) diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index 8f4cab5..bca0b66 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -52,7 +52,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) Measure::Measure() : rm(nullptr), skin(nullptr), skinWindow(nullptr), measureName(nullptr), width(800), height(600), x(0), y(0), - visible(true), initialized(false), clickthrough(false), raincontext(true), webMessageToken{} + visible(true), initialized(false), clickthrough(false), allowDualControl(true), webMessageToken{} { // Initialize COM for this thread if not already done if (!g_comInitialized) @@ -129,33 +129,52 @@ void UpdateClickthrough(Measure* measure) } } -void UpdateRaincontext(Measure* measure) +// Inject AllowDualControl script into the WebView +void InjectAllowDualControl(Measure* measure) { - if (!measure->webView) return; + if (!measure->webView) return; + // Inject script to capture page load events for drag/move and context menu + measure->webView->ExecuteScript( + L"let rm_AllowDualControl=false,rm_AllowDualControlOn=false,rm_AllowDualControlClientX=0,rm_AllowDualControlClientY=0;function rm_SetAllowDualControl(v){rm_AllowDualControl=!!v;if(!rm_AllowDualControl)rm_AllowDualControlOn=false;}document.body.onpointerdown=e=>{if(!rm_AllowDualControl)return;if(e.button===0&&e.ctrlKey){e.preventDefault();e.stopImmediatePropagation();rm_AllowDualControlOn=true;rm_AllowDualControlClientX=e.clientX;rm_AllowDualControlClientY=e.clientY;try{document.body.setPointerCapture(e.pointerId);}catch{}}};document.body.onpointermove=e=>{if(!rm_AllowDualControl||!rm_AllowDualControlOn)return;e.preventDefault();RainmeterAPI.Bang('[!Move '+(e.screenX-RainmeterAPI.ReadFormula('X',0)-rm_AllowDualControlClientX)+' '+(e.screenY-RainmeterAPI.ReadFormula('Y',0)-rm_AllowDualControlClientY)+']');};document.body.onpointerup=e=>{if(!rm_AllowDualControl)return;if(e.button===0){e.preventDefault();rm_AllowDualControlOn=false;try{document.body.releasePointerCapture(e.pointerId);}catch{}}};document.body.oncontextmenu=e=>{if(!rm_AllowDualControl)return;if(e.button===2&&e.ctrlKey){e.preventDefault();RainmeterAPI.Bang('[!SkinMenu]');}};", + Callback( + [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + return S_OK; + } + ).Get() + ); + measure->isAllowDualControlInjected = true; + UpdateAllowDualControl(measure); +} - if (measure->raincontext) - { - measure->webView->ExecuteScript( - L"rm_setRaincontext(true);", - Callback( - [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT - { - return S_OK; - } - ).Get() - ); - } - else { - measure->webView->ExecuteScript( - L"rm_setRaincontext(false);", - Callback( - [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT - { - return S_OK; - } - ).Get() - ); - } +// Update AllowDualControl state in the WebView +void UpdateAllowDualControl(Measure* measure) +{ + if (!measure->webView) return; + + if (measure->allowDualControl) + { + measure->webView->ExecuteScript( + L"rm_SetAllowDualControl(true);", + Callback( + [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + return S_OK; + } + ).Get() + ); + } + else { + measure->webView->ExecuteScript( + L"rm_SetAllowDualControl(false);", + Callback( + [measure](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT + { + return S_OK; + } + ).Get() + ); + } } PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) @@ -213,22 +232,48 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) int newY = RmReadInt(rm, L"Y", 0); bool newVisible = RmReadInt(rm, L"Hidden", 0) <= 0; bool newClickthrough = RmReadInt(rm, L"Clickthrough", 0) >= 1; - bool newRaincontext = RmReadInt(rm, L"Raincontext", 1) >= 1; - + + // Read AllowDualControl for Yincognito's script injection + bool newAllowDualControl = RmReadInt(rm, L"AllowDualControl", 1) >= 1; + // Read OnWebViewLoadAction std::wstring newOnWebViewLoadAction; LPCWSTR onWebViewLoadOption = RmReadString(rm, L"OnWebViewLoadAction", L"", FALSE); if (onWebViewLoadOption && wcslen(onWebViewLoadOption) > 0) { - newOnWebViewLoadAction = onWebViewLoadOption; + newOnWebViewLoadAction = onWebViewLoadOption; } - + // Read OnWebViewFailAction std::wstring newOnWebViewFailAction; LPCWSTR onWebViewFailOption = RmReadString(rm, L"OnWebViewFailAction", L"", FALSE); if (onWebViewFailOption && wcslen(onWebViewFailOption) > 0) { - newOnWebViewFailAction = onWebViewFailOption; + newOnWebViewFailAction = onWebViewFailOption; + } + + // Read OnPageLoadStartAction + std::wstring newOnPageLoadStartAction; + LPCWSTR onPageLoadStartOption = RmReadString(rm, L"OnPageLoadStartAction", L"", FALSE); + if (onPageLoadStartOption && wcslen(onPageLoadStartOption) > 0) + { + newOnPageLoadStartAction = onPageLoadStartOption; + } + + // Read OnPageLoadingAction + std::wstring newOnPageLoadingAction; + LPCWSTR onPageLoadingOption = RmReadString(rm, L"OnPageLoadingAction", L"", FALSE); + if (onPageLoadingOption && wcslen(onPageLoadingOption) > 0) + { + newOnPageLoadingAction = onPageLoadingOption; + } + + // Read OnPageLoadFinishAction + std::wstring newOnPageLoadFinishAction; + LPCWSTR onPageLoadFinishOption = RmReadString(rm, L"OnPageLoadFinishAction", L"", FALSE); + if (onPageLoadFinishOption && wcslen(onPageLoadFinishOption) > 0) + { + newOnPageLoadFinishAction = onPageLoadFinishOption; } // Read OnPageFirstLoadAction @@ -236,15 +281,7 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) LPCWSTR onPageFirstLoadOption = RmReadString(rm, L"OnPageFirstLoadAction", L"", FALSE); if (onPageFirstLoadOption && wcslen(onPageFirstLoadOption) > 0) { - newOnPageFirstLoadAction = onPageFirstLoadOption; - } - - // Read OnPageLoadAction - std::wstring newOnPageLoadAction; - LPCWSTR onPageLoadOption = RmReadString(rm, L"OnPageLoadAction", L"", FALSE); - if (onPageLoadOption && wcslen(onPageLoadOption) > 0) - { - newOnPageLoadAction = onPageLoadOption; + newOnPageFirstLoadAction = onPageFirstLoadOption; } // Read OnPageReloadAction @@ -252,12 +289,11 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) LPCWSTR onPageReloadOption = RmReadString(rm, L"OnPageReloadAction", L"", FALSE); if (onPageReloadOption && wcslen(onPageReloadOption) > 0) { - newOnPageReloadAction = onPageReloadOption; + newOnPageReloadAction = onPageReloadOption; } - + // Check if URL has changed (requires recreation) bool urlChanged = (newUrl != measure->url); - // Check if dimensions or position changed (can be updated dynamically) bool dimensionsChanged = (newWidth != measure->width || @@ -267,7 +303,7 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) bool visibilityChanged = (newVisible != measure->visible); bool clickthroughChanged = (newClickthrough != measure->clickthrough); - bool raincontextChanged = (newRaincontext != measure->raincontext); + bool allowDualControlChanged = (newAllowDualControl != measure->allowDualControl); // Update stored values measure->url = newUrl; @@ -277,12 +313,14 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) measure->y = newY; measure->visible = newVisible; measure->clickthrough = newClickthrough; - measure->raincontext = newRaincontext; - measure->OnWebViewLoadAction = newOnWebViewLoadAction; - measure->OnWebViewFailAction = newOnWebViewFailAction; - measure->onPageFirstLoadAction = newOnPageFirstLoadAction; - measure->onPageLoadAction = newOnPageLoadAction; - measure->onPageReloadAction = newOnPageReloadAction; + measure->allowDualControl = newAllowDualControl; + measure->onWebViewLoadAction = newOnWebViewLoadAction; + measure->onWebViewFailAction = newOnWebViewFailAction; + measure->onPageLoadStartAction = newOnPageLoadStartAction; + measure->onPageLoadingAction = newOnPageLoadingAction; + measure->onPageLoadFinishAction = newOnPageLoadFinishAction; + measure->onPageFirstLoadAction = newOnPageFirstLoadAction; + measure->onPageReloadAction = newOnPageReloadAction; // Only create WebView2 if not initialized OR if URL changed if (!measure->initialized || urlChanged) @@ -330,10 +368,15 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) UpdateClickthrough(measure); } - if (raincontextChanged) - { - UpdateRaincontext(measure); - } + if (allowDualControlChanged) + { + if (!measure->isAllowDualControlInjected) + { + InjectAllowDualControl(measure); + } + else + UpdateAllowDualControl(measure); + } } } From 38144bc65342de184b9d514beb107b0ee291b8a0 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:52:43 -0600 Subject: [PATCH 14/21] Add currentUrl member to Plugin class --- WebView2/Plugin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/WebView2/Plugin.h b/WebView2/Plugin.h index b554e40..a1581ab 100644 --- a/WebView2/Plugin.h +++ b/WebView2/Plugin.h @@ -22,6 +22,7 @@ struct Measure LPCWSTR measureName; std::wstring url; + std::wstring currentUrl; int width; int height; int x; From 899ddf84e93eee228ac2603d99a1d050bcd4259a Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Thu, 11 Dec 2025 12:02:36 -0600 Subject: [PATCH 15/21] Update WebView2.cpp Added new event listeners for triggering new actions. --- WebView2/WebView2.cpp | 179 +++++++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 62 deletions(-) diff --git a/WebView2/WebView2.cpp b/WebView2/WebView2.cpp index f3c3533..a11b77d 100644 --- a/WebView2/WebView2.cpp +++ b/WebView2/WebView2.cpp @@ -51,10 +51,10 @@ void CreateWebView2(Measure* measure) swprintf_s(errorMsg, L"WebView2: Failed to start creation process (HRESULT: 0x%08X). Make sure WebView2 Runtime is installed.", hr); RmLog(measure->rm, LOG_ERROR, errorMsg); } - if (measure->skin && wcslen(measure->OnWebViewFailAction.c_str()) > 0) - { - RmExecute(measure->skin, measure->OnWebViewFailAction.c_str()); - } + if (measure->skin && wcslen(measure->onWebViewFailAction.c_str()) > 0) + { + RmExecute(measure->skin, measure->onWebViewFailAction.c_str()); + } measure->isCreationInProgress = false; } } @@ -70,10 +70,10 @@ HRESULT Measure::CreateEnvironmentHandler(HRESULT result, ICoreWebView2Environme swprintf_s(errorMsg, L"WebView2: Failed to create environment (HRESULT: 0x%08X)", result); RmLog(rm, LOG_ERROR, errorMsg); } - if (skin && wcslen(OnWebViewFailAction.c_str()) > 0) - { - RmExecute(skin, OnWebViewFailAction.c_str()); - } + if (skin && wcslen(onWebViewFailAction.c_str()) > 0) + { + RmExecute(skin, onWebViewFailAction.c_str()); + } isCreationInProgress = false; return result; } @@ -102,10 +102,10 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller swprintf_s(errorMsg, L"WebView2: Failed to create controller (HRESULT: 0x%08X)", result); RmLog(rm, LOG_ERROR, errorMsg); } - if (skin && wcslen(OnWebViewFailAction.c_str()) > 0) - { - RmExecute(skin, OnWebViewFailAction.c_str()); - } + if (skin && wcslen(onWebViewFailAction.c_str()) > 0) + { + RmExecute(skin, onWebViewFailAction.c_str()); + } isCreationInProgress = false; return result; } @@ -114,10 +114,10 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller { if (rm) RmLog(rm, LOG_ERROR, L"WebView2: Controller is null"); - if (skin && wcslen(OnWebViewFailAction.c_str()) > 0) - { - RmExecute(skin, OnWebViewFailAction.c_str()); - } + if (skin && wcslen(onWebViewFailAction.c_str()) > 0) + { + RmExecute(skin, onWebViewFailAction.c_str()); + } isCreationInProgress = false; return S_FALSE; } @@ -176,26 +176,81 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller L"window.RainmeterAPI = chrome.webview.hostObjects.sync.RainmeterAPI", nullptr ); - - // Add NavigationCompleted event to call OnInitialize after page loads + + // Add SourceChanged event to detect changes in URL + webView->add_SourceChanged( + Callback( + [this](ICoreWebView2* sender, ICoreWebView2SourceChangedEventArgs* args) -> HRESULT + { + wil::unique_cotaskmem_string updatedUri; + + if (SUCCEEDED(sender->get_Source(&updatedUri)) && updatedUri.get() != nullptr) + { + std::wstring newUrl = updatedUri.get(); + + if (currentUrl != newUrl) + { + // URL changed + isFirstLoad = true; + currentUrl = newUrl; + } + else + { + // URL did not change + isFirstLoad = false; + } + } + return S_OK; + } + ).Get(), + nullptr + ); + + // Add NavigationStarting event to call action when navigation starts + webView->add_NavigationStarting( + Callback( + [this](ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT + { + if (wcslen(onPageLoadStartAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageLoadStartAction.c_str()); + } + return S_OK; + } + ).Get(), + nullptr + ); + + // Add ContentLoading event to call action when page starts loading + webView->add_ContentLoading( + Callback( + [this](ICoreWebView2* sender, ICoreWebView2ContentLoadingEventArgs* args) -> HRESULT + { + if (wcslen(onPageLoadingAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageLoadingAction.c_str()); + } + return S_OK; + } + ).Get(), + nullptr + ); + + // Add NavigationCompleted event to call OnInitialize after page loads and handle load actions webView->add_NavigationCompleted( Callback( [this](ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT { - // Inject script to capture page load events for drag/move and context menu - webView->ExecuteScript( - L"let rm_raincontext=false,rm_RaincontextOn=false,rm_RaincontextClientX=0,rm_RaincontextClientY=0;function rm_setRaincontext(v){rm_raincontext=!!v;if(!rm_raincontext)rm_RaincontextOn=false;}document.body.onpointerdown=e=>{if(!rm_raincontext)return;if(e.button===0&&e.ctrlKey){e.preventDefault();e.stopImmediatePropagation();rm_RaincontextOn=true;rm_RaincontextClientX=e.clientX;rm_RaincontextClientY=e.clientY;try{document.body.setPointerCapture(e.pointerId);}catch{}}};document.body.onpointermove=e=>{if(!rm_raincontext||!rm_RaincontextOn)return;e.preventDefault();RainmeterAPI.Bang('[!Move '+(e.screenX-RainmeterAPI.ReadFormula('X',0)-rm_RaincontextClientX)+' '+(e.screenY-RainmeterAPI.ReadFormula('Y',0)-rm_RaincontextClientY)+']');};document.body.onpointerup=e=>{if(!rm_raincontext)return;if(e.button===0){e.preventDefault();rm_RaincontextOn=false;try{document.body.releasePointerCapture(e.pointerId);}catch{}}};document.body.oncontextmenu=e=>{if(!rm_raincontext)return;if(e.button===2&&e.ctrlKey){e.preventDefault();RainmeterAPI.Bang('[!SkinMenu]');}};", - Callback( - [this](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT - { - return S_OK; - } - ).Get() - ); + isAllowDualControlInjected = false; - // Apply initial raincontext state - UpdateRaincontext(this); - + // Inject script to capture page load events for drag/move and context menu + if (allowDualControl) + { + InjectAllowDualControl(this); + } + // Call JavaScript OnInitialize callback if it exists and capture return value webView->ExecuteScript( L"(function() { if (typeof window.OnInitialize === 'function') { var result = window.OnInitialize(); return result !== undefined ? String(result) : ''; } return ''; })();", @@ -210,47 +265,47 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller { result = result.substr(1, result.length() - 2); } - + // Store the callback result if (!result.empty() && result != L"null") { - callbackResult = result; + callbackResult = result; } } - - if (isFirstLoad) - { - if (wcslen(onPageFirstLoadAction.c_str()) > 0) - { - if (skin) - RmExecute(skin, onPageFirstLoadAction.c_str()); - } - isFirstLoad = false; - } - else { - if (wcslen(onPageReloadAction.c_str()) > 0) - { - if (skin) - RmExecute(skin, onPageReloadAction.c_str()); - } - } - - if (wcslen(onPageLoadAction.c_str()) > 0) - { - if (skin) - RmExecute(skin, onPageLoadAction.c_str()); - } - return S_OK; } ).Get() ); + + if (isFirstLoad) // First load + { + if (wcslen(onPageFirstLoadAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageFirstLoadAction.c_str()); + } + isFirstLoad = false; + } + else // Page reload + { + if (wcslen(onPageReloadAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageReloadAction.c_str()); + } + } + // Common action after any page load + if (wcslen(onPageLoadFinishAction.c_str()) > 0) + { + if (skin) + RmExecute(skin, onPageLoadFinishAction.c_str()); + } return S_OK; } ).Get(), nullptr ); - + // Navigate to URL if (!url.empty()) { @@ -264,10 +319,10 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller if (rm) RmLog(rm, LOG_NOTICE, L"WebView2: Initialized successfully with COM Host Objects"); - if (wcslen(OnWebViewLoadAction.c_str()) > 0) - { - RmExecute(skin, OnWebViewLoadAction.c_str()); - } + if (wcslen(onWebViewLoadAction.c_str()) > 0) + { + RmExecute(skin, onWebViewLoadAction.c_str()); + } // Apply initial clickthrough state UpdateClickthrough(this); From 24ce69e02352c81f885041f183e7b87b9d614ed6 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:10:47 -0600 Subject: [PATCH 16/21] added zoomFactor double --- WebView2/Plugin.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/WebView2/Plugin.h b/WebView2/Plugin.h index a1581ab..c51e5d6 100644 --- a/WebView2/Plugin.h +++ b/WebView2/Plugin.h @@ -20,20 +20,21 @@ struct Measure void* skin; HWND skinWindow; LPCWSTR measureName; - + std::wstring url; std::wstring currentUrl; int width; int height; int x; int y; + double zoomFactor; bool visible; bool initialized; bool clickthrough; bool isCreationInProgress = false; bool isFirstLoad = true; bool allowDualControl; - bool isAllowDualControlInjected = false; + bool isAllowDualControlInjected = false; std::wstring onWebViewLoadAction; std::wstring onWebViewFailAction; @@ -46,14 +47,14 @@ struct Measure wil::com_ptr webViewController; wil::com_ptr webView; EventRegistrationToken webMessageToken; - + std::wstring buffer; // Buffer for section variable return values std::wstring callbackResult; // Stores return value from OnInitialize/OnUpdate callbacks std::map jsResults; // Cache for CallJS results - + Measure(); ~Measure(); - + // Member callback functions for WebView2 creation HRESULT CreateEnvironmentHandler(HRESULT result, ICoreWebView2Environment* env); HRESULT CreateControllerHandler(HRESULT result, ICoreWebView2Controller* controller); From 3de406e8b5b2e9869de9734d508f20483c879aa0 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:18:19 -0600 Subject: [PATCH 17/21] added zoomFactor --- WebView2/Plugin.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/WebView2/Plugin.cpp b/WebView2/Plugin.cpp index bca0b66..dbab4cd 100644 --- a/WebView2/Plugin.cpp +++ b/WebView2/Plugin.cpp @@ -51,7 +51,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) // Measure constructor Measure::Measure() : rm(nullptr), skin(nullptr), skinWindow(nullptr), measureName(nullptr), - width(800), height(600), x(0), y(0), + width(800), height(600), x(0), y(0), zoomFactor(1.0), visible(true), initialized(false), clickthrough(false), allowDualControl(true), webMessageToken{} { // Initialize COM for this thread if not already done @@ -230,6 +230,7 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) int newHeight = RmReadInt(rm, L"H", 600); int newX = RmReadInt(rm, L"X", 0); int newY = RmReadInt(rm, L"Y", 0); + double newZoomFactor = RmReadFormula(rm, L"ZoomFactor", 1.0); bool newVisible = RmReadInt(rm, L"Hidden", 0) <= 0; bool newClickthrough = RmReadInt(rm, L"Clickthrough", 0) >= 1; @@ -304,13 +305,15 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) bool visibilityChanged = (newVisible != measure->visible); bool clickthroughChanged = (newClickthrough != measure->clickthrough); bool allowDualControlChanged = (newAllowDualControl != measure->allowDualControl); - + bool zoomFactorChanged = (newZoomFactor != measure->zoomFactor); + // Update stored values measure->url = newUrl; measure->width = newWidth; measure->height = newHeight; measure->x = newX; measure->y = newY; + measure->zoomFactor = newZoomFactor; measure->visible = newVisible; measure->clickthrough = newClickthrough; measure->allowDualControl = newAllowDualControl; @@ -362,6 +365,11 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) { measure->webViewController->put_IsVisible(measure->visible ? TRUE : FALSE); } + + if (zoomFactorChanged && measure->webViewController) + { + measure->webViewController->put_ZoomFactor(measure->zoomFactor); + } if (clickthroughChanged) { From 2834a3a188d2ca25554d205ce2dedb6260b1a5f0 Mon Sep 17 00:00:00 2001 From: RicardoTM05 <168048518+RicardoTM05@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:20:40 -0600 Subject: [PATCH 18/21] Added ZoomFactor --- WebView2/WebView2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WebView2/WebView2.cpp b/WebView2/WebView2.cpp index a11b77d..6eb16b6 100644 --- a/WebView2/WebView2.cpp +++ b/WebView2/WebView2.cpp @@ -142,7 +142,10 @@ HRESULT Measure::CreateControllerHandler(HRESULT result, ICoreWebView2Controller // Set initial visibility webViewController->put_IsVisible(visible ? TRUE : FALSE); - + + // Set initial zoom factor + webViewController->put_ZoomFactor(zoomFactor); + // Transparent background auto controller2 = webViewController.query(); if (controller2) From a678ab95e1cece90e14a511a7d8e01ca69ddc617 Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Sun, 14 Dec 2025 08:02:49 +0500 Subject: [PATCH 19/21] updated skin provided by the RicardoTM. --- .../WebView2/BangCommand/BangCommand.ini | 77 ++++++++++++++----- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/Resources/Skins/WebView2/BangCommand/BangCommand.ini b/Resources/Skins/WebView2/BangCommand/BangCommand.ini index b0a7fc0..f6f85d5 100644 --- a/Resources/Skins/WebView2/BangCommand/BangCommand.ini +++ b/Resources/Skins/WebView2/BangCommand/BangCommand.ini @@ -13,11 +13,14 @@ License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 [Variables] WebURL=https://nstechbytes.pages.dev/ WebW=600 -WebH=410 +WebH=500 WebX=300 WebY=45 +ZoomFactor=1.0 Hidden=0 ClickThrough=0 +AllowDualControl=1 + ; ======================================== ; Measure ; ======================================== @@ -29,8 +32,17 @@ W=#WebW# H=#WebH# X=#WebX# Y=#WebY# +ZoomFactor=#ZoomFactor# Hidden=#Hidden# ClickThrough=#ClickThrough# +AllowDualControl=#AllowDualControl# +OnWebViewLoadAction=[!log "WebView loaded succesfully!"] +OnWebViewFailAction=[!log "WebView failed :("] +OnPageFirstLoadAction=[!log "First time on this page!"] +OnPageLoadStartAction=[!log "Navigation has started!"] +OnPageLoadingAction=[!log "Page is loading!"] +OnPageLoadFinishAction=[!log "Navigation has finished!"] +OnPageReloadAction=[!log "Page has been reloaded!"] DynamicVariables=1 ; ======================================== @@ -38,7 +50,7 @@ DynamicVariables=1 ; ======================================== [MeterBackground] Meter=Shape -Shape=Rectangle 0,0,950,480,12 | FillColor 0,0,0,200 | StrokeWidth 0 +Shape=Rectangle 0,0,920,570,12 | FillColor 0,0,0,200 | StrokeWidth 0 [Title] Meter=String @@ -67,7 +79,7 @@ MeterStyle=StyleButtonText Text=Navigate to Google (via Variable) X=150 Y=58 -LeftMouseUpAction=[!SetVariable WebURL "https://www.google.com"][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable WebURL "https://www.google.com"][!UpdateMeasure MeasureWebView] [TxtNavigateGitHub] Meter=String @@ -75,15 +87,15 @@ MeterStyle=StyleButtonText Text=Navigate to GitHub (via Variable) X=150 Y=88 -LeftMouseUpAction=[!SetVariable WebURL "https://github.com"][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable WebURL "https://github.com"][!UpdateMeasure MeasureWebView] -[TxtNavigateExample] +[TxtNavigateForum] Meter=String MeterStyle=StyleButtonText -Text=Navigate to Example (via Bang) +Text=Navigate to Forum (via Bang) X=150 Y=118 -LeftMouseUpAction=[!CommandMeasure MeasureWebView "Navigate https://example.com"] +LeftMouseUpAction=[!CommandMeasure MeasureWebView "Navigate https://forum.rainmeter.net/"] [TxtReload] Meter=String @@ -121,7 +133,7 @@ W=122 H=24 X=86 Y=208 -LeftMouseUpAction=[!SetVariable Hidden 0][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable Hidden 0][!UpdateMeasure MeasureWebView] [TxtHide] Meter=String @@ -131,7 +143,7 @@ W=125 H=24 X=212 Y=208 -LeftMouseUpAction=[!SetVariable Hidden 1][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable Hidden 1][!UpdateMeasure MeasureWebView] [TxtExecuteScript] Meter=String @@ -139,7 +151,7 @@ MeterStyle=StyleButtonText Text=Execute Script X=150 Y=238 -LeftMouseUpAction=[!CommandMeasure MeasureWebView "ExecuteScript alert('Hello!')"] +LeftMouseUpAction=[!CommandMeasure MeasureWebView "ExecuteScript console.log('Script has been executed.')"] [TxtOpenDevTools] Meter=String @@ -155,7 +167,8 @@ MeterStyle=StyleButtonText Text=Set Width: 500 (via Variable) X=150 Y=298 -LeftMouseUpAction=[!SetVariable WebW 500][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable WebW (#WebW#=600?500:600)][!UpdateMeasure MeasureWebView][!UpdateMeter #CURRENTSECTION#][!Redraw] +DynamicVariables=1 [TxtSetHeight] Meter=String @@ -163,15 +176,17 @@ MeterStyle=StyleButtonText Text=Set Height: 400 (via Variable) X=150 Y=328 -LeftMouseUpAction=[!SetVariable WebH 400][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable WebH (#WebH#=410?470:410)][!UpdateMeasure MeasureWebView][!UpdateMeter #CURRENTSECTION#][!Redraw] +DynamicVariables=1 [TxtSetX] Meter=String MeterStyle=StyleButtonText -Text=Set X: 100 (via Variable) +Text=Set X: 320 (via Variable) X=150 Y=358 -LeftMouseUpAction=[!SetVariable WebX 100][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable WebX (#WebX#=300?320:300)][!UpdateMeasure MeasureWebView][!UpdateMeter #CURRENTSECTION#][!Redraw] +DynamicVariables=1 [TxtSetY] Meter=String @@ -179,22 +194,46 @@ MeterStyle=StyleButtonText Text=Set Y: 50 (via Variable) X=150 Y=388 -LeftMouseUpAction=[!SetVariable WebY 50][!UpdateMeasure MeasureWebView][!Redraw] +LeftMouseUpAction=[!SetVariable WebY (#WebY#=45?50:45)][!UpdateMeasure MeasureWebView][!UpdateMeter #CURRENTSECTION#][!Redraw] +DynamicVariables=1 + +[TxtSetZoom] +Meter=String +MeterStyle=StyleButtonText +Text=Set ZoomFactor: 2.0 (via Variable) +X=150 +Y=418 +LeftMouseUpAction=[!SetVariable ZoomFactor (#ZoomFactor#=1?2:1)][!UpdateMeasure MeasureWebView][!UpdateMeter #CURRENTSECTION#][!Redraw] +DynamicVariables=1 [TxtSetEnableClickThrough] Meter=String MeterStyle=StyleButtonText Text=Set ClickThrough: 1 (via Variable) X=150 -Y=418 -LeftMouseUpAction=[!SetVariable ClickThrough 1][!UpdateMeasure MeasureWebView][!Redraw] +Y=448 +LeftMouseUpAction=[!SetVariable ClickThrough 1][!UpdateMeasure MeasureWebView] [TxtSetDisableClickThrough] Meter=String MeterStyle=StyleButtonText Text=Set ClickThrough: 0 (via Variable) X=150 -Y=448 -LeftMouseUpAction=[!SetVariable ClickThrough 0][!UpdateMeasure MeasureWebView][!Redraw] +Y=478 +LeftMouseUpAction=[!SetVariable ClickThrough 0][!UpdateMeasure MeasureWebView] +[TxtSetEnableAllowDualControl] +Meter=String +MeterStyle=StyleButtonText +Text=Set AllowDualControl: 1 (Variable) +X=150 +Y=508 +LeftMouseUpAction=[!SetVariable AllowDualControl 1][!UpdateMeasure MeasureWebView] +[TxtSetDisableAllowDualControl] +Meter=String +MeterStyle=StyleButtonText +Text=Set AllowDualControl: 0 (Variable) +X=150 +Y=538 +LeftMouseUpAction=[!SetVariable AllowDualControl 0][!UpdateMeasure MeasureWebView] From 42d1be5b7268c59fc94dad3e4cc315048554c3e0 Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Sun, 14 Dec 2025 08:03:50 +0500 Subject: [PATCH 20/21] updated skins version from 0.0.6 to 0.0.7 --- Resources/Skins/WebView2/BangCommand/BangCommand.ini | 2 +- Resources/Skins/WebView2/Calendar/Calendar.ini | 2 +- Resources/Skins/WebView2/Clock/Clock.ini | 2 +- .../Skins/WebView2/InformationProperty/InformationProperty.ini | 2 +- Resources/Skins/WebView2/IslamicDate/IslamicDate.ini | 2 +- Resources/Skins/WebView2/JSInteraction/JSInteraction.ini | 2 +- .../Skins/WebView2/ReadMeasureOption/ReadMeasureOption.ini | 2 +- .../Skins/WebView2/ReadSectionOption/ReadSectionOption.ini | 2 +- Resources/Skins/WebView2/UtilityFunction/UtilityFunction.ini | 2 +- Resources/Skins/WebView2/Weather/Weather.ini | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Resources/Skins/WebView2/BangCommand/BangCommand.ini b/Resources/Skins/WebView2/BangCommand/BangCommand.ini index f6f85d5..54485b4 100644 --- a/Resources/Skins/WebView2/BangCommand/BangCommand.ini +++ b/Resources/Skins/WebView2/BangCommand/BangCommand.ini @@ -7,7 +7,7 @@ DynamicWindowSize=1 Name=BangCommand Author=nstechbytes Information=Demonstrates controlling WebView2 via !CommandMeasure bangs. -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 [Variables] diff --git a/Resources/Skins/WebView2/Calendar/Calendar.ini b/Resources/Skins/WebView2/Calendar/Calendar.ini index f1fcfc0..65c57a6 100644 --- a/Resources/Skins/WebView2/Calendar/Calendar.ini +++ b/Resources/Skins/WebView2/Calendar/Calendar.ini @@ -5,7 +5,7 @@ Update=1000 Name=Calendar Author=nstechbytes Information=Calendar Widget using WebView2 -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 ; ======================================== ; Measure diff --git a/Resources/Skins/WebView2/Clock/Clock.ini b/Resources/Skins/WebView2/Clock/Clock.ini index 830ef3d..2b61529 100644 --- a/Resources/Skins/WebView2/Clock/Clock.ini +++ b/Resources/Skins/WebView2/Clock/Clock.ini @@ -5,7 +5,7 @@ Update=1000 Name=Calendar Author=nstechbytes Information=Calendar Widget using WebView2 -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 ; ======================================== ; Measure diff --git a/Resources/Skins/WebView2/InformationProperty/InformationProperty.ini b/Resources/Skins/WebView2/InformationProperty/InformationProperty.ini index 021bcb2..dc7f22e 100644 --- a/Resources/Skins/WebView2/InformationProperty/InformationProperty.ini +++ b/Resources/Skins/WebView2/InformationProperty/InformationProperty.ini @@ -7,7 +7,7 @@ DynamicWindowSize=1 Name=InformationProperty Author=nstechbytes Information=Shows Rainmeter information properties via WebView2. -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 ; ======================================== ; Measure diff --git a/Resources/Skins/WebView2/IslamicDate/IslamicDate.ini b/Resources/Skins/WebView2/IslamicDate/IslamicDate.ini index fa8609d..3aa32d9 100644 --- a/Resources/Skins/WebView2/IslamicDate/IslamicDate.ini +++ b/Resources/Skins/WebView2/IslamicDate/IslamicDate.ini @@ -5,7 +5,7 @@ Update=1000 Name=Islamic Date Author=nstechbytes Information=Islamic (Hijri) Date Widget using WebView2 -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 ; ======================================== ; Measure diff --git a/Resources/Skins/WebView2/JSInteraction/JSInteraction.ini b/Resources/Skins/WebView2/JSInteraction/JSInteraction.ini index 71833fd..3e1ba0b 100644 --- a/Resources/Skins/WebView2/JSInteraction/JSInteraction.ini +++ b/Resources/Skins/WebView2/JSInteraction/JSInteraction.ini @@ -7,7 +7,7 @@ DynamicWindowSize=1 Name=JSInteraction Author=nstechbytes Information=Demonstrates JavaScript interaction (OnInitialize, OnUpdate, CallJS) with the WebView2 plugin. -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 ; ======================================== diff --git a/Resources/Skins/WebView2/ReadMeasureOption/ReadMeasureOption.ini b/Resources/Skins/WebView2/ReadMeasureOption/ReadMeasureOption.ini index cc2110b..6e2729c 100644 --- a/Resources/Skins/WebView2/ReadMeasureOption/ReadMeasureOption.ini +++ b/Resources/Skins/WebView2/ReadMeasureOption/ReadMeasureOption.ini @@ -7,7 +7,7 @@ DynamicWindowSize=1 Name=ReadMeasureOption Author=nstechbytes Information=Demonstrates reading options from the current measure using the WebView2 plugin. -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 ; ======================================== ; Measure diff --git a/Resources/Skins/WebView2/ReadSectionOption/ReadSectionOption.ini b/Resources/Skins/WebView2/ReadSectionOption/ReadSectionOption.ini index f19dc6a..62d4c9e 100644 --- a/Resources/Skins/WebView2/ReadSectionOption/ReadSectionOption.ini +++ b/Resources/Skins/WebView2/ReadSectionOption/ReadSectionOption.ini @@ -7,7 +7,7 @@ DynamicWindowSize=1 Name=ReadSectionOption Demo Author=nstechbytes Information=Demonstrates reading options from other sections using WebView2 -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 [Variables] diff --git a/Resources/Skins/WebView2/UtilityFunction/UtilityFunction.ini b/Resources/Skins/WebView2/UtilityFunction/UtilityFunction.ini index 90b87e3..79d64f3 100644 --- a/Resources/Skins/WebView2/UtilityFunction/UtilityFunction.ini +++ b/Resources/Skins/WebView2/UtilityFunction/UtilityFunction.ini @@ -7,7 +7,7 @@ DynamicWindowSize=1 Name=UtilityFunction Author=nstechbytes Information=Demonstrates RainmeterAPI utility functions using the WebView2 plugin. -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 [Variables] diff --git a/Resources/Skins/WebView2/Weather/Weather.ini b/Resources/Skins/WebView2/Weather/Weather.ini index 02b8340..66e0189 100644 --- a/Resources/Skins/WebView2/Weather/Weather.ini +++ b/Resources/Skins/WebView2/Weather/Weather.ini @@ -5,7 +5,7 @@ Update=1000 Name=Weather Author=nstechbytes Information=Weather Widget using WebView2 -Version=0.0.6 +Version=0.0.7 License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0 ; ======================================== ; Measure From 53ebe6f0d070357ee5f775054abf29c2a6ac2bbe Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Sun, 14 Dec 2025 08:05:24 +0500 Subject: [PATCH 21/21] updated plugin version from 0.0.6 to 0.0.7 --- Resources/skin_definition.json | 4 ++-- WebView2/WebView2.rc | Bin 1624 -> 1624 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/skin_definition.json b/Resources/skin_definition.json index 8c25266..d8ceb85 100644 --- a/Resources/skin_definition.json +++ b/Resources/skin_definition.json @@ -1,6 +1,6 @@ { "skinDir": ".\\Resources\\Skins", - "version": "0.0.6", + "version": "0.0.7", "minimumVersion": "4.5", "author": "nstechbytes", "variableFiles": "", @@ -17,5 +17,5 @@ "load": "WebView2\\Clock\\Clock.ini", "headerImage": ".\\Resources\\banner.bmp", "configPrefix": "WebView2", - "output": ".\\dist\\WebView2_v0.0.6_Alpha6.rmskin" + "output": ".\\dist\\WebView2_v0.0.7_Alpha7.rmskin" } diff --git a/WebView2/WebView2.rc b/WebView2/WebView2.rc index 89c9450b92785dfa43f3749c9c0feab48bc84180..9b0f1ed7d95478fe8567f5c08bb55062b53cf9cb 100644 GIT binary patch delta 24 gcmcb?bAxBX5k~WgN9~!-8I&gbGm3APW3*xg0B=ACQ2+n{ delta 24 gcmcb?bAxBX5k|9#N9~!-7?dXaGm3APW3*xg0B<7)PXGV_