Skip to content

Commit 0c56ee6

Browse files
committed
Add WebView2 Rainmeter plugin with host object API for JavaScript interaction.
1 parent 63052c7 commit 0c56ee6

File tree

3 files changed

+153
-263
lines changed

3 files changed

+153
-263
lines changed

WebView2/Plugin.cpp

Lines changed: 30 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
4949

5050
// Measure constructor
5151
Measure::Measure() : rm(nullptr), skin(nullptr), skinWindow(nullptr),
52-
webViewWindow(nullptr), measureName(nullptr),
52+
measureName(nullptr),
5353
width(800), height(600), x(0), y(0),
54-
visible(true), initialized(false), isCleaningUp(false), webMessageToken{}
54+
visible(true), initialized(false), webMessageToken{}
5555
{
5656
// Initialize COM for this thread if not already done
5757
if (!g_comInitialized)
@@ -67,10 +67,7 @@ Measure::Measure() : rm(nullptr), skin(nullptr), skinWindow(nullptr),
6767
// Measure destructor
6868
Measure::~Measure()
6969
{
70-
// Mark that cleanup is in progress
71-
isCleaningUp = true;
72-
73-
// Proper cleanup sequence to prevent crashes and race conditions
70+
// Proper cleanup sequence to prevent crashes
7471

7572
// 1. Remove event handlers first
7673
if (webView && webMessageToken.value != 0)
@@ -92,19 +89,8 @@ Measure::~Measure()
9289
webView.reset(); // Explicit release
9390
}
9491

95-
// 4. Longer delay to ensure WebView2 runtime fully releases resources
96-
// This prevents 0x80080005 error on skin refresh
97-
Sleep(250);
98-
99-
// 5. Destroy window last
100-
if (webViewWindow && IsWindow(webViewWindow))
101-
{
102-
DestroyWindow(webViewWindow);
103-
webViewWindow = nullptr;
104-
}
105-
106-
// 6. Final delay to ensure complete cleanup
107-
Sleep(50);
92+
// 4. Brief delay to allow async cleanup
93+
Sleep(100);
10894
}
10995

11096
// Rainmeter Plugin Exports
@@ -170,7 +156,7 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
170156
measure->visible = RmReadInt(rm, L"Visible", 1) != 0;
171157

172158
// Create WebView2 if not already created
173-
if (!measure->initialized && !measure->isCleaningUp)
159+
if (!measure->initialized)
174160
{
175161
CreateWebView2(measure);
176162
}
@@ -182,24 +168,23 @@ PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
182168
measure->webView->Navigate(measure->url.c_str());
183169
}
184170

185-
// Update window position and size
186-
if (measure->webViewWindow)
171+
// Update WebView2 bounds
172+
if (measure->webViewController)
187173
{
188-
SetWindowPos(
189-
measure->webViewWindow,
190-
nullptr,
191-
measure->x, measure->y,
192-
measure->width, measure->height,
193-
SWP_NOZORDER | SWP_NOACTIVATE
194-
);
195-
196-
ShowWindow(measure->webViewWindow, measure->visible ? SW_SHOW : SW_HIDE);
197-
198-
// Update WebView2 controller visibility
199-
if (measure->webViewController)
174+
RECT bounds;
175+
GetClientRect(measure->skinWindow, &bounds);
176+
bounds.left = measure->x;
177+
bounds.top = measure->y;
178+
if (measure->width > 0)
179+
{
180+
bounds.right = measure->x + measure->width;
181+
}
182+
if (measure->height > 0)
200183
{
201-
measure->webViewController->put_IsVisible(measure->visible ? TRUE : FALSE);
184+
bounds.bottom = measure->y + measure->height;
202185
}
186+
measure->webViewController->put_Bounds(bounds);
187+
measure->webViewController->put_IsVisible(measure->visible ? TRUE : FALSE);
203188
}
204189
}
205190
}
@@ -264,30 +249,22 @@ PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args)
264249
}
265250
else if (_wcsicmp(action.c_str(), L"Show") == 0)
266251
{
267-
if (measure->webViewWindow)
252+
measure->visible = true;
253+
254+
// Make WebView2 controller visible
255+
if (measure->webViewController)
268256
{
269-
ShowWindow(measure->webViewWindow, SW_SHOW);
270-
measure->visible = true;
271-
272-
// Also make WebView2 controller visible
273-
if (measure->webViewController)
274-
{
275-
measure->webViewController->put_IsVisible(TRUE);
276-
}
257+
measure->webViewController->put_IsVisible(TRUE);
277258
}
278259
}
279260
else if (_wcsicmp(action.c_str(), L"Hide") == 0)
280261
{
281-
if (measure->webViewWindow)
262+
measure->visible = false;
263+
264+
// Hide WebView2 controller
265+
if (measure->webViewController)
282266
{
283-
ShowWindow(measure->webViewWindow, SW_HIDE);
284-
measure->visible = false;
285-
286-
// Also hide WebView2 controller
287-
if (measure->webViewController)
288-
{
289-
measure->webViewController->put_IsVisible(FALSE);
290-
}
267+
measure->webViewController->put_IsVisible(FALSE);
291268
}
292269
}
293270
else if (_wcsicmp(action.c_str(), L"ExecuteScript") == 0)

WebView2/Plugin.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ struct Measure
1717
void* rm;
1818
void* skin;
1919
HWND skinWindow;
20-
HWND webViewWindow;
2120
LPCWSTR measureName;
2221

2322
std::wstring url;
@@ -27,17 +26,19 @@ struct Measure
2726
int y;
2827
bool visible;
2928
bool initialized;
30-
bool isCleaningUp;
3129

3230
wil::com_ptr<ICoreWebView2Controller> webViewController;
3331
wil::com_ptr<ICoreWebView2> webView;
3432
EventRegistrationToken webMessageToken;
3533

3634
Measure();
3735
~Measure();
36+
37+
// Member callback functions for WebView2 creation
38+
HRESULT CreateEnvironmentHandler(HRESULT result, ICoreWebView2Environment* env);
39+
HRESULT CreateControllerHandler(HRESULT result, ICoreWebView2Controller* controller);
3840
};
3941

4042
// WebView2 functions
4143
void CreateWebView2(Measure* measure);
42-
void RegisterWebViewWindowClass();
43-
LRESULT CALLBACK WebViewWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
44+

0 commit comments

Comments
 (0)