Skip to content

Conversation

@RicardoTM05
Copy link
Contributor

@RicardoTM05 RicardoTM05 commented Jan 12, 2026

This update contains the following:

Measure Returns Rework

Measure Returns Rework

Number Value
The measure's number value now represents the state of WebView2 before any navigation, and the state of the navigation afterwards. The following numbers apply:

  • -2 WebView failed
  • -1 WebView not running
  • 0 WebView Initializing
  • 1 WebView Initialized
  • 100 Navigation Start
  • 200 Loading Site
  • 300 DOM Content loaded
  • 400 Navigation Complete

String Value

  • Current URL
    Now the measure will return the current URL whenever is available.
    Example: https://www.forum.rainmeter.net/
New Actions

New Actions
To reflect states, we also have new actions.

  • OnWebViewStopAction
    Triggers when WebView stops successfully.
  • OnStateChangeAction
    Triggers every time the state changes
  • OnUrlChangeAction
    Triggers every time the URL changes
  • OnPageDOMLoadAction
    Triggers when the DOM content finishes loading, it triggers before OnPageLoadFinishAction.
Commands Rework

Commands Rework
There are now only 4 commands:

WebView

  • Start
    e.g: [!CommandMeasure WebView "WebView Start"]
  • Stop
    e.g: [!CommandMeasure WebView "WebView Stop"]
  • Restart
    e.g: [!CommandMeasure WebView "WebView Restart"]

Navigate

  • Home
    e.g: [!CommandMeasure WebView "Navigate Home"]
  • Back
    e.g: [!CommandMeasure WebView "Navigate Back"]
  • Forward
    e.g: [!CommandMeasure WebView "Navigate Forward"]
  • Reload
    e.g: [!CommandMeasure WebView "Navigate Reload"]
  • Stop
    e.g: [!CommandMeasure WebView "Navigate Stop"]
  • URL
    e.g: [!CommandMeasure WebView "Navigate http://example.com/"]

Open

  • DevTools
    e.g: [!CommandMeasure WebView "Open DevTools"]
  • TaskManager
    e.g: [!CommandMeasure WebView "Open TaskManager"]

ExecuteScript
Remains untouched. This command may change in the future to Execute.

New Options

New Options

  • Clickthrough default: 2
    Allows the user to interact with the meters behind the WebView2 window, it has 3 modes:
    0 disabled: No skin interaction (full WebView interaction)
    1 enabled: Full skin interaction (no WebView interaction)
    2 toggle: Full skin interaction while holding CTRL.
    This option is especially useful to drag the skin. By default all WebView2 skins that don't set this option to something other than 2 will be draggable while holding CTRL.

  • NewWindow default: 0
    When enabled, the user will be able to open new windows, while disabled all navigations will happen on the main window.

  • AllowNotifications default: 0
    WebView doesn't allow to use the Notifications API by default, now we can use it by setting this option to 1.

  • AutoStart defalut: 1
    When disabled, WebView will not start automatically when the skin loads.

  • UserAgent default: ""
    Allows to enter a custom user agent.

  • ZoomControl default: 1
    When disabled, internal browser zoom control will be disabled. This means the user won't be able to alter the zoom through default hotkeys such as: CTRL + SCROLL CTRL + PLUS CTRL + MINUS CTRL + 0

  • AssistiveFeatures default: 1
    Allows to disable assistive browser features: 'Find', 'Print' and 'Caret Browsing'.

Special Feature: Virtual Host

Special Feature: Virtual Host
Now the plugin supports internal virtual hosts. A new example skin called YoutubePlayer shows how it works.
This replaces the need to install a http-server. Although it doesn't come without a cost, skins that use a virtual host will take a little longer to load (not horribly longer though).

This feature includes the following options:

  • HostSecurity default: 1
    Choose between http and https protocols.
    0 Not secure: http
    1 Secure: https

  • HostOrigin default: 1
    Choose between using the Root Config or the Current Config as the origin.
    0 Current config
    1 Root config
    Choosing between one or the other lets you decide how the Local Storage will behave:
    Choosing current config will make the local storage accessible only to the current skin (config).
    Choosing root config will make local storage accessible to all skins (configs) that belong to the same root (good for suites).

  • HostPath default: ""
    Enter the path to the folder where your file.html is.
    e.g: HostPath = #@#
    This option alone tells the plugin that the user wants to use a virtual host, then generates an URL that's mapped to that folder, using a host name according to the HostOrigin option, and a protocol according to the HostSecurity option.

How it works:
The plugin knows you want to use a virtual host when the HostPath option links to a valid folder. Then it starts the virtual host and generates a new URL that can then be used to access the virtual host.
e.g: Let's say this code is in the Illustro\Clock skin.

; HostSecurity:
; 0 = http  (insecure context)
; 1 = https (secure context)
; Using HTTPS allows to use certain APIs blocked by CORS.
HostSecurity=1

; HostOrigin:
; 1 = root config
; 0 = current config only
; Using current config isolates storage to this skin
HostOrigin=0

; Folder containing the HTML and assets
HostPath=#@#

URL=index.html

On the code above, we chose https as our protocol and Illustro\Clock as our origin. The index.html file is inside @Resources folder. The generated URL then will be:
https://illustro-clock/
Now we can simply navigate to it by setting the URL option to that:
URL=https://illustro-clock/index.html
We can also simply do:
URL=index.html
The URL option will automatically know that we are using a virtual host and will navigate to the correct URL.
The local storage will be exclusive to the Illustro\Clock skin. Or, in other words, to the https://illustro-clock/ origin.

The other way would be:

HostSecurity=0
HostOrigin=1
HostPath=#@#Clock\
URL=clock.html

On the code above, we chose http as our protocol and Illustro as our origin. The clock.html file is inside @Resources\Clock\ folder. The generated URL then will be:
http://illustro/
Now we can simply navigate to it by setting the URL option to that:
URL=http://illustro/clock.html
We can also simply do:
URL=clock.html
The local storage will be shared between all configs that belong to the Illustro root config. Or, in other words, to the http://illustro/ origin.

External User Settings

External User Settings
When the WebView2 environment is created, a user folder called RainmeterWebView2 is also created at: C:\Users\User\AppData\Local\Temp\RainmeterWebView2\. A new file is now automatically created at this folder location, called UserSettings.ini. This new file holds some personal settings that the user can change by manually modifying it. All options will be set to their Defaults automatically when the plugin is loaded for the first time.

All options in this file affect all skins, that's why they can't be exposed to the plugin's measure, also some of them require the environment to be re-created, which means the user requires to exit Rainmeter and then launch it again.

UserSettings.ini
Path: C:\Users\User\AppData\Local\Temp\RainmeterWebView2\UserSettings.ini

[Environment]
Extensions = false
FluentOverlayScrollBars = true
TrackingPrevention = true
BrowserLocale = system
BrowserArguments = --allow-file-access-from-files


[Controller]
ScriptLocale = system
PrivateMode = false


[Core]
StatusBar = true
PinchZoom = true
SwipeNavigation = true
SmartScreen = true


[Profile]
DownloadsFolderPath = 
ColorScheme = auto
PasswordAutoSave = false
GeneralAutoFill = true

[Environment]
These options require Rainmeter to be restarted to take effect. Changing any of this options while using the plugin will make WebView2 fail to start, simply restart Rainmeter.

[Controller]
These options require Rainmeter to be refreshed (using Refresh all), or the plugin to be restarted using WebView Restart command.

  • ScriptLocale default: system
    This option determines the default language for JavaScript. It's the default for all Intl based JS functions, such as dates, decimal separators, etc.
    Locales need to be in the format of BCP 47 Language Tags. e.g: en-US es-MX fr-FR ja-JP
    If set to 'system', it will use the default OS locale.
    A list of locales can be found here: https://appmakers.substack.com/p/bcp-47-language-codes-list

  • PrivateMode default: false
    Allows to use the private mode, aka incognito mode.

[Core]
These options require Rainmeter to be refreshed (using Refresh all), or the plugin to be restarted using WebView Restart command.

  • StatusBar default: true
    Allows to disable the status bar.

  • PinchZoom default: true
    Pinch zoom functionality on tactile screens.

  • SwipeNavigation default: true
    Swipe navigation functionality on tactile screens.

  • SmartScreen default: true
    Microsoft Defender SmartScreen ("SmartScreen") is a security feature that is enabled by default to help users safely browse the web.
    More info: https://learn.microsoft.com/en-us/legal/microsoft-edge/privacy#smartscreen

[Profile]
These options require Rainmeter to be refreshed (using Refresh all), or the plugin to be restarted using WebView Restart command.

  • DownloadsFolderPath default: ""
    By default WebView2 will use the Windows Downloads folder. This option allows you to choose another folder as the default.

  • ColorScheme default: system
    Allows to choose a preferred color scheme for WebView2's UI's like the context menu and others.
    Options are:
    system: System preference
    light: Light theme
    dark: Dark theme

  • PaswordAutoSave default: false
    When enabled, password information is auto-populated, suggestions are shown and clicking on one will populate the fields, new data is saved, and a Save/Update Password prompt is displayed

  • GeneralAutoFill default: true
    Determines whether general form information will be saved and autofilled.

Other Changes

Other Changes

  • AllowDualControl has been removed.
  • Clickthrough has acquired a new value: 2.
  • window.OnInitialize and window.OnUpdate no longer change the measure’s string nor number values.
  • The URL option on the measure now works as a Home Page URL and is the URL to which WebView2 will navigate after starting. To navigate somewhere else you now have to use the Navigate command. To navigate back to the home page set on the URL option you now use the Navigate Home command. In other words, dynamically updating the URL option will not navigate, it will only set the new URL as the Home Page.
  • Now websites won't be able to trigger undesired pop-up windows.
  • It is now possible to frame websites, but this requires the use of a virtual host or a http-server. This works by bypassing X-Frame-Options and injecting our own "frame ancestor", which would be the current base URL (origin) that is trying to frame, e.g: https://illustro-clock/ or http://localhost:8080/.
  • New example skin: YoutubePlayer has been added. Shows how to use the virtual host feature.
  • All example skins have been modified to use new options.
  • Added Simpleini.h file for UserSettings.ini parsing.
  • Updated WebView2 SDK to latest stable release: 1.0.3650.58.
  • Added new options to the context menu: Downloads View page source Task manager and Skin menu. Note: The names of these options won't be translated when using a different BrowserLocale.
  • Enabled app-region CSS style which allows to set draggable zones through CSS.
Known Issues

Known Issues

  • RainmeterAPI may not be accesible in some websites.
What's next

What's next
After releasing the PR, the focus will be on Scripting support. These features require careful planning to deliver a well thought out implementation.

A kind reminder:
This plugin is still on an Alpha state, which means that many things like options names may change, and other things may be added or removed. This plugin is not suitable for production use as of yet. We of course appreciate you testing and sharing feedback.

A testing build can be found here.

RicardoTM05 added 2 commits January 11, 2026 20:11
Introducing various new options and features
Introducing SkinControl
Introducing external user settings
@RicardoTM05 RicardoTM05 mentioned this pull request Jan 12, 2026
@NSTechBytes
Copy link
Owner

Thanks for the PR. I'm not sure why Rainmeter crashes when unloading the skin while using WebView2 in this version

@Yincognyto
Copy link

Yincognyto commented Jan 12, 2026

First impressions, after only changing both locales in UserSettings.ini to en-CA so that the browser's task manager is in English:

  • features: excellent work, looking forward to wrap up scripting, frames and RainmeterAPI in the future
  • stability: about 85% chances of crashes on unloading the skins in the package (my Earth and BlueMarble don't seem to crash)
  • performance: slightly bigger impact compared to the old WebView plugin, though that varies between executions

Quick question: Is the ExecuteScriptFile / Execute < InlineScript | FilePath > command supposed to be dealt with in the next PR?

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 12, 2026

Which skin(s) crashed?

Yes, that command is part of scripting.

Ok I see the crash, will investigate. Thanks for reporting. I might have forgotten something when cleaning the code.

The crash happens while trying to remove the subclass procedure for Skin Control. It’s been an on and off fight with it since implemented. It’s the last piece on the puzzle to have SkinControl working perfectly.

As workaround for now just to avoid it from crashing just leave one WebView2 skin running while testing. It will only crash when the last skin unloads.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 12, 2026

Please test new package, I updated it on the same post

it stopped crashing for me, also added logs for when the class and the hook are removed. The hook is only installed when the first measure is loaded and removed once the last measure will be removed. The class is set/unset on each skin load/unload

@Yincognyto
Copy link

Yincognyto commented Jan 12, 2026

it stopped crashing for me

It seems to have stopped crashing on skin unload for me too, as far as I tested it (the Clock skin was the quickest to crash for me earlier). I tested in both single and multiple WebView2 skins loaded scenarios, and so far, no crash yet. Would the new system (which seems to be a winner against crashes) add some kind of "performance overload" to the plugin, or is it negligible?

@RicardoTM05
Copy link
Contributor Author

It seems to have stopped crashing on skin unload for me too

Interesting, thanks.

Would the new system (which seems to be a winner against crashes) add some kind of "performance overload" to the plugin, or is it negligible?

I haven't found a fix nor implemented a new system yet, all I did was adding the logs lol. It's a bug that doesn't like being observed. But this got me closer, at least I know where things are happening and have a better clue as of why.

@Yincognyto
Copy link

Yincognyto commented Jan 13, 2026

I haven't found a fix nor implemented a new system yet, all I did was adding the logs lol. It's a bug that doesn't like being observed. But this got me closer, at least I know where things are happening and have a better clue as of why.

The "fix" is because of the delay created by logging, if that's all you did - it happened in other unrelated cases for me. Something doesn't have the time to be freed / released / disposed / garbage collected normally when the skin unloads - my suspicion.


Bugs and inconsistencies:

  • when ContextMenu=0 and SkinControl>0, the skin menu will always trigger when requested, while the browser menu won't
  • when SkinControl=3, scrolling is impossible as it's taken over by zooming, even if ZoomControl=0 and no background meter

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 13, 2026

It's fixed already, will update when I get on the pc later. Edit. Spoke too early.

  • when ContextMenu=0 and SkinControl>0, the skin menu will always trigger when requested, while the browser menu won't

Not a bug, this is normal.

When SkinControl=1
No interaction with webview is possible = SkinMenu (because you are right clicking the skin, not webview).
When SkinControl=2
Interaction with webview, no context menu. When you press CTRL then again, you are interacting with the skin = SkinMenu.
When SkinControl=3
No interaction with webview = SkinMenu. When you press CTRL there's no menu.

The plugin can't magically block the skin menu for the whole skin, it only controls WebView related stuff. The ContextMenu option
only controls which context menu is available inside WebView's context.

This is important to understand:

SkinControl
Allows the user to interact with the meters behind the WebView2 window.


  • when SkinControl=3, scrolling is impossible as it's taken over by zooming, even if ZoomControl=0 and no background meter

Yep, that's because CTRL is pressed and WebView doesn't scroll when CTRL is pressed, even if zoom control is technically disabled, not a bug and there's not much I can do about it.

As a quick test, simply set SkinControl = 0 and ZoomControl = 0 and try ctrl + scrolling, it won't do anything, it won't scroll the page, not because of the plugin, that's how the browser works.

The "fix" would block all CTRL hotkeys instead of only the ability to scroll. If you enable NewWindow, it will also make every link you click open on a new window (because you are ctrl + clicking everything).

Not a bug.

Just ctrl + click the document so it gains keyboard focus, release ctrl and scroll using the up and down arrows. You can also enable caret browsing (F7).
I would never use SkinControl=3 for a browser skin of course, but I would for a skin like the Calendar example.

——

Something that is also important to understand is that WebView and the actual skin are 2 different entities, we basically have a window on top of another window. They don’t share neither mouse nor keyboard focus. That’s why SkinControl exists, to be able to control the focus between both windows by technically disabling the WebView window while keeping it visible to us, but invisible to the mouse. This of course comes with limitations like the aforementioned.

Still the option is great because it covers multiple scenarios, but yeah, it’s not perfect.

The app-region feature, which I just remembered I didn’t mentioned on the post, comes really handy as well (with its limitations of course). I used it on the header of the YouTube player by the way (in case you haven’t notice it yet). Really handy but of course it also have limitations (the browser’s context menu doesn’t work on the area, but the skin menu opens if you right click on it, and more).

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 13, 2026

Alright, should be fixed now. Updated the package on the same post

Turns out it was my bad. The bug was more specific than simply crashing when unloading.
It was crashing when you never press CTRL. Easily reproducible by loading any webview2 skin, do not press ctrl key at any moment, then unload the skin. It doesn't crash if you load the skin, then press ctrl once, then unload it.

I also improved the logic for the config file parsing logic as it was slowing initialization down a little, should perform better now.

Will commit after I'm sure everything's ok.

@NSTechBytes
Copy link
Owner

I hadn’t reviewed all the changes earlier.One question why did you use the external SimpleIni.h library? What is its purpose? Why wasn’t the default Windows API used instead?

@Yincognyto
Copy link

Yincognyto commented Jan 13, 2026

Not a bug, this is normal.

No, it's not normal, that's why I said "bugs and inconsistencies" (my bad, should have used "or" instead of "and", and only used "bugs" because I didn't know if it was intentional before checking the source code myself). I do understand how this works and never mentioned that blocking the skin menu was expected for the whole skin, I referred to the webview area only. My point was more about SkinControl=2 being deprived of page menu in favor of ContextMenu having the last say, than about skin menu, tbh.

Let me explain why they're inconsistencies, and why this can be "better":

  1. ContextMenu=0 is documented as "no context menu", implying it covers both skin and page menus (not just the latter, btw)
  2. even if we overlook that, ContextMenu kind of unintuively overrides / takes precedence over the more complete SkinControl:
  • when SkinControl>1 and ContextMenu=0, you can select on the page but you can't trigger the page menu (hotkey irrelevant)
  • when SkinControl=0 and ContextMenu>1, you can't skin drag but you can very well trigger the skin menu (hotkey irrelevant)

Like 1), 2) happens even considering that SkinControl=0 is supposed to mean "no skin interaction" (including skin menu, btw).

Now, I'm not contesting that it's nice to not have to hold CTRL for one behavior or another, or that it isn't useful, I'm only saying that it makes no sense having that for a functionality that's incomplete (who would want selectable text that he can't copy paste on the page in the first case above, or a skin that can trigger its context menu without being able to be dragged in the second case above - assuming the above option values would be set), or unintuitive (in the case of the Calendar skin, the user has to remember that: a) even though he can skin menu without CTRL, he can't drag without CTRL; b) even though he has to CTRL for dragging, he can skin menu either with or without CTRL). These things all happen in the current implementation.

All this was supposed to be done by "SkinControl" itself, where you'd get the complete package of environmental behavior (that is, both drag and menu for that environment, and not just one of them) either by setting the option to a value, or by toggling behaviors via a hotkey or similar, e.g. full page behavior when X, alternate full page or skin behavior when Y based on the hotkey, full skin behavior when Z (honestly, even though we added them just to have all the combinations, ContextMenu=0 while also SkinControl=0 doesn't make much sense in terms of usage either). Especially since you already added the "Skin Menu" item to the page menu, so now even if SkinControl=2 and ContextMenu=1 (or even only the former) one can access the skin menu without pressing CTRL anyway (well, it's an additional menu, but Windows 11 already does that, so no big deal). To be even clearer to you, Ricardo, SkinControl was working fine with the previous SkinMenu, now the one thing that made it complete and literally everything one would need in terms of "dual control" (i.e. full page control too), even without CTRL, is gone and depends entirely on having ContextMenu=1, since otherwise all you'd get is various skin menus and no page menu.

Not a bug.

This SkinControl=3 point actually makes way more sense than the first point, and I agree. That being said, the user might wonder: "hey, how come I can actually type in a google box when only pressing CTRL to enter the box and not while typing, while I can't do the same when scrolling"? I'm sure there may be a reason for that too, I'm just saying that unfortunately SkinControl=3 also results in an incomplete behavior (just like for the first inconsistencies above), where you can very well "toggle invert" everything (that's credit to you all the way, coming up with the idea on how to do that)... except scrolling. Even if you'd want to use that, you'd always have to keep in mind that, well dang, scrolling "doesn't work". You know better when you say you cannot do much about it, just that I - and probably whoever tries it - will think whether the box typing trick can be used for scrolling to, i.e. without having to press CTRL for the entire duration of that action.


These are just some things you guys can think about if you want. I'm not trying to convince anyone of anything anymore, my only point was that having certain things work only partially in different circumstances (whether it's about the context menu, the skin control, the api, the frames, or the scripting) when in some cases a resolve might be possible, makes something a situation I thought we left behind with the old plugin. It's not your fault, you're trying hard - it must be me cause I want it all and don't accept limitations. Most likely MS fault too, by not providing easy ways to pass control to the host app and others, or not providing them in due time (5 years till done).

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 13, 2026

I hadn’t reviewed all the changes earlier.One question why did you use the external SimpleIni.h library? What is its purpose? Why wasn’t the default Windows API used instead?

I came across it and thought it could be useful, I tried it and liked it for its simplicity, it’s a single 129kb file and saved me some time. But it can be removed of course and the logic replaced with window’s logic if you feel it’s overkill. Not an external library exactly as it doesn’t have dependencies, it’s a single Simpleini.h file

As of why it was causing performance issues before, it was me, not simpleini. I was reading and writing the file on each initialization step instead of only once on environment creation and save the file once WebView was initialized.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 13, 2026

Let me explain why they're inconsistencies, and why this can be "better":

  1. ContextMenu=0 is documented as "no context menu", implying it covers both skin and page menus (not just the latter, btw)

  2. even if we overlook that, ContextMenu kind of unintuively overrides / takes precedence over the more complete SkinControl:

  • when SkinControl>1 and ContextMenu=0, you can select on the page but you can't trigger the page menu (hotkey irrelevant)
    That's correct.
  • when SkinControl=0 and ContextMenu>1, you can't skin drag but you can very well trigger the skin menu (hotkey irrelevant)

Like 1), 2) happens even considering that SkinControl=0 is supposed to mean "no skin interaction" (including skin menu, btw).

Now, I'm not contesting that it's nice to not have to hold CTRL for one behavior or another, or that it isn't useful, I'm only saying that it makes no sense having that for a functionality that's incomplete (who would want selectable text that he can't copy paste on the page in the first case above, or a skin that can trigger its context menu without being able to be dragged in the second case above - assuming the above option values would be set), or unintuitive (in the case of the Calendar skin, the user has to remember that: a) even though he can skin menu without CTRL, he can't drag without CTRL; b) even though he has to CTRL for dragging, he can skin menu either with or without CTRL). These things all happen in the current implementation.

All this was supposed to be done by "SkinControl" itself, where you'd get the complete package of environmental behavior (that is, both drag and menu for that environment, and not just one of them) either by setting the option to a value, or by toggling behaviors via a hotkey or similar, e.g. full page behavior when X, alternate full page or skin behavior when Y based on the hotkey, full skin behavior when Z (honestly, even though we added them just to have all the combinations, ContextMenu=0 while also SkinControl=0 doesn't make much sense in terms of usage either). Especially since you already added the "Skin Menu" item to the page menu, so now even if SkinControl=2 and ContextMenu=1 (or even only the former) one can access the skin menu without pressing CTRL anyway (well, it's an additional menu, but Windows 11 already does that, so no big deal). To be even clearer to you, Ricardo, SkinControl was working fine with the previous SkinMenu, now the one thing that made it complete and literally everything one would need in terms of "dual control" (i.e. full page control too), even without CTRL, is gone and depends entirely on having ContextMenu=1, since otherwise all you'd get is various skin menus and no page menu.

You are defining SkinControl like if it was meant to control all skin-mouse related features all at once, and I get it, it makes sense. But that's not how it works. It simply allows the mouse to interact with the skin. It doesn't cover what happens to the context menu. Even if it did, how would it do it?

Let's say ContextMenu doesn't exist.

SkinControl=0 - disabled/BrowserMenu (already "does" this)
SkinControl=1 - enabled/SkinMenu (already "does" this)
SkinControl=2 - disabled/BrowserMenu CTRL enabled/SkinMenu (already "does" this)
SkinControl=3 - enabled/SkinMenu CTRL disabled/BrowserMenu (already "does" this)

How do we control what happens to the browser's context menu? We just don't? We have to be forced to use JavaScript if we want to display the SkinMenu or the SkinCustomMenu on WebView? Should SkinControl have 7 values?

I'm sorry, you tried to be even clearer to me but I still don't understand. I thought you didn't like SkinMenu either because of the same reason.. And now SkinControl is not working fine because SkinMenu was renamed ContextMenu and was given 2 new values?

I'm interested on your opinion about this too @NSTechBytes, if you don't mind.

Not a bug.

This SkinControl=3 point actually makes way more sense than the first point, and I agree. That being said, the user might wonder: "hey, how come I can actually type in a google box when only pressing CTRL to enter the box and not while typing, while I can't do the same when scrolling"? I'm sure there may be a reason for that too, I'm just saying that unfortunately SkinControl=3 also results in an incomplete behavior (just like for the first inconsistencies above), where you can very well "toggle invert" everything (that's credit to you all the way, coming up with the idea on how to do that)... except scrolling. Even if you'd want to use that, you'd always have to keep in mind that, well dang, scrolling "doesn't work". You know better when you say you cannot do much about it, just that I - and probably whoever tries it - will think whether the box typing trick can be used for scrolling to, i.e. without having to press CTRL for the entire duration of that action.

These are just some things you guys can think about if you want. I'm not trying to convince anyone of anything anymore, my only point was that having certain things work only partially in different circumstances (whether it's about the context menu, the skin control, the api, the frames, or the scripting) when in some cases a resolve might be possible, makes something a situation I thought we left behind with the old plugin. It's not your fault, you're trying hard - it must be me cause I want it all and don't accept limitations. Most likely MS fault too, by not providing easy ways to pass control to the host app and others, or not providing them in due time (5 years till done).

I don't have to be convinced, I just need to understand. I keep without understanding exactly how SkinControl should work. This is what I've come up with that actually worked, and I worked around it's limitations to offer customization to the user. You also link to a WebView2 thread about AllowHostInputProcessing like If it wasn't the very first thing I tried which didn't work. Which by the way wouldn’t work as well as the hook as it would depend on the keyboard focus being always on WebView, as opposed to the Hook which doesn’t depend on keyboard focus at all.

To me the perfect "SkinControl" would be the one that wasn't even an option. Simply have the plugin work flawlessly with the skin like if it was just another meter, same for clickthrough and all other skin settings. Just don't know how to do that.

@NSTechBytes
Copy link
Owner

I think SkinContextMenu would be a clearer name than SkinMenu.

@Yincognyto
Copy link

I'm sorry, you tried to be even clearer to me but I still don't understand.

You're actually very close since your snippet covers all bar the custom skin menu feature, which can be at SkinControl=3:

SkinControl=0 -> SkinControl=0 + ContextMenu=1, merged into SkinControl=0 (full page [drag + menu], not CTRL based)
SkinControl=1 -> SkinControl=1 + ContextMenu=1, merged into SkinControl=1 (full skin [drag + menu], not CTRL based)
SkinControl=2 -> SkinControl=2 + ContextMenu=1, merged into SkinControl=2 (full page | skin [drag + menu], CTRL based)
SkinControl=3 -> SkinControl=1 (full skin drag), along with ContextMenu=3 (full skin custom menu) (not CTRL based)
Longer version:

If you look closely, the rest of the combinations now are either not doing anything (e.g. SkinControl=0 + ContextMenu=0), doing too little (e.g. SkinControl=2 + ContextMenu=0 lacking page menu), not able to perform operations (e.g. SkinControl=3 + ContextMenu=1 and page scrolling), or being redundant / reproducible already in a different way between operations (e.g. the rest).

Heck, even with no skin menu or skin custom menu available in 3 of the values above, you already integrated the "Skin Menu" item into the WebView context menu internally without any JS whatsoever (at the cost of an additional click just like in Win 11), and I bet you can do the same with a "Skin Custom Menu", if you insist in having it - so a skin like the Calendar one doesn't even need ContextMenu=2 anymore since you already have the item in the WebView context menu. Likewise, one can already integrate stuff like Dev Tools or Task Manager in the skin menu or the skin custom menu for the reverse.

Like I already said to you - but of course you don't remember, while you expect me to remember what property you used 3 weeks ago, as a non C++ developer, despite the fact that I was only trying to help - I was completely neutral to the previous SkinMenu, I didn't like it, I didn't hate it, I just didn't care about it, since for me personally SkinControl=2 + SkinMenu=1 was already doing everything I wanted to have and more than just SkinMenu alone - I didn't find it hard to hold CTRL when I needed. I would have had zero problems with the existence or naming of ContextMenu too, if SkinControl=2 wasn't deprived of page (aka browser) menu when ContextMenu=0.

I know that this is the logical behavior given the new circumstances, it just felt like an attack on the - again - only option (whether it's named SkinControl or else) which can have everything about control if combined with ContextMenu like above, instead of taking away from it and essentially crippling it in that particular combination, so it was a defense mechanism from my part. Sure, I still have the almighty SkinControl=2 + SkinMenu=1 one which is ideal for many reasons and understandably quoted by you above, but if you did that, then I expected worse might happen to it later on. To me, that SkinControl or whatever option is untouchable, it's a deal breaker for me, after finally getting it right starting with nstechbytes' Clickthrough which was beautifully developed by you into what's now SkinControl.

You have to understand, Ricardo, that, to borrow from a classic, I have to put myself in the end user shoes because no one else does it. The end user won't really care or know if SkinControl and ContextMenu are different options or are internally based on different approaches, he will see them as one unit giving him the control he needs over the skin or the page as desired. My point is that in the current implementation, even though basically covering all angles like we both initially agreed which is fine, you can get easily lost when using them (e.g. do I need to hold CTRL for this or that, or not?; what was that value doing again?), some combinations simply allow only "drag" or "menu" and not the both expected by the user when using the same technique (for the record, by "page drag" I mean the equivalent of skin drag but on the page, which usually results in selecting text), and some combinations like SkinControl=3 have unfortunate drawbacks that might cause more questions than answers.

Shorter version:

To summarize, I felt that SkinControl=2 + ContextMenu=1 / SkinControl=0 + ContextMenu=1 were threatened by ContextMenu=0 taking features from SkinControl that the previous SkinMenu didn't, I eventually realized the many combinations can be confusing, and saw some of them as incomplete or problematic. If the 2 above combinations are safe I'll be fine, but it might be difficult to explain them satisfactorily to users. I'm not opposed to them, just wary about them. And yeah, the ideal control shouldn't even had to be an option, it should have been provided seamlessly by WebView2.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 14, 2026

I’m just going to give @NSTechBytes more context first because he’s obviously clueless about all our conversations through PM’s.

I think SkinContextMenu would be a clearer name than SkinMenu.

Sorry, SkinMenu is an option that never saw light out of PM’s between Ying and me. It simply used to replace the browser menu with the skin menu. The same that ContextMenu=1 and ContextMenu=2 does right know. At some point it was also Ctrl controlled, but when SkinControl was introduced, SkinMenu needing ctrl was not useful anymore as SkinControl was already “doing” what SkinMenu used to do, it was actually limiting.

And no, it’s not that I coded SkinMenu into SkinControl, it’s only that when SkinControl is enabled the user is clicking the skin instead of webview, so the SkinMenu is what’s available by nature when the user is interacting with the Skin and the BrowserMenu when interacting with WebView.

Just to give more context, my first implementation of SkinControl was WebView based instead of via a hook, and was not as good as this new implementation because it wouldn’t work if WebView didn’t have keyboard focus. Then I “hacked” into it to make it possible but it wasn’t reliable enough, there was a delay. So it was until I managed to implement the hook correctly that I was able to have a better working system that didn’t relied on WebView at all, no keyboard focus issues and had no delay, the real SkinControl option was born.

It wasn’t that I decided to remove the Ctrl based functionality out of the now gone SkinMenu, is that it’s functions relied on the not working correctly system I had just replaced by the hook. But now SkinMenu was naturally opening the SkinMenu because the right click was now happening on the skin while holding Ctrl.

Since SkinMenu was now obsolete I made it into ContextMenu which is not Ctrl controlled, it simply allows to change what context menu pops up on WebView. It also allows to completely disable the context menu. Totally independent of SkinControl (which again, doesn’t control the menu at all).

Why do I think ContextMenu is good?

Details It allows for different combinations. Like the Calendar skin which now feels like a normal skin, there’s no browser menu on that skin, only the SkinMenu and still draggable while holding ctrl.

On the clock and prayers skins there isn’t a browser menu either. But that’s because SkinControl=1, and that renders ContextMenu unusable. Why? When SkinControl=1 there’s no interaction with WebView, and ContextMenu only controls what happens on WebView. Technically, SkinControl=1 is the same as if you had Clickthrough=1 on the previous version.

ContextMenu only applies when SkinControl=0, while NOT holding CTRL when SkinControl=2, and while holding CTRL when SkinControl=3

Again, that behavior is not coded anywhere, since ContextMenu is a WebView option it only applies when interacting with WebView.

Why is it allowed to completely disable the menu when ContextMenu=0?

Details Just because that was naturally what 0 means, ContextMenu=0 means disabled which means no context menu logically. Is it useful? May be.

Why didn’t I simply merged SkinControl and ContextMenu?

Details Again, SkinControl does nothing but toggle Clickthrough on and off. In pseudocode:
SkinControl=0 : Clickthrough=0
SkinControl=1 : Clickthrough=1
SkinControl=2 : Clickthrough=0 - CTRL: Clickthrough=1
SkinControl=3 : Clickthrough=1 - CTRL: Clickthrough=0

The plugin can’t control what happens out of the WebView area nor inside it when Clicktrhough=1 so SkinControl can’t simply replace the SkinMenu with anything because it has no control over that, it doesn’t control any mouse gesture or anything, it simply toggles Clickthrough and nothing else. No, it doesn’t make the skin draggable either. The skin is draggable because you are physically dragging the skin. SkinControl literally means “To Control The Skin”, I guess “ClickthroughControl” would have been a better fit.

It was gonna be called Clickthrough instead but we thought it being called Clickthrough would have been even more confusing since Rainmeter’s clickthrough has only 2 values: 1 and 0.

How does ContextMenu work then?

Details ContextMenu is linked to WebView’s OnContextMenuRequested event, which allows to intercept context menu requests and return the skin menu instead, or even block the context menu. So whenever SkinControl enables Clickthrough there’s obviously no ContextMenuRequested event because the user is not clicking on WebView. That right click is totally handled by Rainmeter. Yes, the user can intercept that by using the RightMouseDownAction on the meter behind WebView that is used as background.

How does exactly SkinControl work?

Details When the plugin is loaded it starts a low level keyboard hook, this hook is global for all skins. It also subclasses each skin window, each skin has their own subclass procedure. When the hook detects a CTRL key press/release, it sends a custom message to all WebView skins. Setting SkinControl on a skin allows that skin to read those custom messages through its subclass procedure. Now the skins know if CTRL is held or not through the custom window messages that arrive to them. When SkinControl=2 the CTRL pressed message enables clickthrough, and the released message disables clickthrough. When SkinControl=3 its the other way around. When SkinControl=0 or 1 the plugin simply disables or enables clickthrough. The hook is still sending the custom messages but the skins simply ignore them.

In short:

  • SkinControl does not control anything about context menus.
  • WebView context menu is controlled by WebView and Rainmeter’s context menu is controlled by Rainmeter.
  • ContextMenu option only works on a WebView context.
  • SkinControl does not control the mouse nor reads clicks.
  • SkinControl does not control dragging.
  • SkinControl does what clickthrough used to do.
  • SkinControl enables/disables clickthrough dynamically by pressing CTRL.
  • The hook only reacts to the CTRL key and nothing else.
  • The subclass window procedure simply listens and reacts to those custom messages sent by the hook.

Why did I add the SkinMenu option to the context menu?

Details I consider that it being a Rainmeter plugin should give access to Rainmeter’s skin menu at all times one way or another.

Now, to answer Yincognito:

NP means Not Possible

SkinControl=0 + ContextMenu=1 : Ok.
SkinControl=1 + ContextMenu=1 : NP.
SkinControl=2 + ContextMenu=1 : Ok.
SkinControl=1 + ContextMenu=3 : NP.
  1. OK: Basically how it works already.
  2. NP: It’s not possible to request the BrowserMenu while interacting with the skin.
  3. OK: It would be exactly how SkinControl=2 works right now, if it’s not that what you meant, then it’s not possible to request the BrowserMenu while interacting with the skin.
  4. NP: It’s not possible to request the SkinCustomMenu while interacting with the skin.

Hopefully after reading how SkinControl works you understand why it is not possible to do what you ask for. The way SkinControl works right now doesn’t allow for it.

I don’t know about you, but at least I don’t know how to do what you are asking for, I have no clue, you are basically asking to drag the skin while interacting with webview and get the BrowserMenu while interacting with Rainmeter, things that if were possible they would be already implemented. However I’m all ears and welcome anyone that proposes a system capable of doing such things.

What I propose:

Details
  • Build/enforce SkinControl=2 functionality into the plugin.
  • Remove SkinControl as an option.
  • SkinControl=3 functionality is gone.
  • Bring Clickthrough option back.
  • Leave ContextMenu option alone.

This would be less customizable but far more consistent. All WebView windows would be, by rule, disabled/unclickable while holding CTRL, this way we make sure that all skins are, by consequence, draggable while holding CTRL.

Collateral:
Any WebView Ctrl + Mouse action won’t work, which means:

  • Ctrl + Scroll wont work to zoom the site.
    Workaround:
    Use Ctrl + Plus and Ctrl + Minus instead.
    The users can also code their own zoom scroll logic using Rainmeter mouse actions and the ZoomFactor option. See BangCommand.ini for an example of zooming using scroll actions, and Calendar.ini for an example of scaling.

  • Ctrl + Click to open links on a new window when NewWindow=1 won’t be possible.
    Workaround:
    Use context menu -> open in new window or middle mouse button click instead.

Those are the only things that I’m aware that wouldn’t work on this system, but there are workarounds for them.

  • All Ctrl + Keyboard actions will continue to work normally.

Why ContextMenu stays?

Without SkinControl “confusing” anyone, everyone will understand that the option is to modify WebView’s context menu.

How are they going to understand that?

We are going to clearly document that pressing ctrl disables all interactions with WebView and nothing else, it doesn’t control menus nor anything like that. To control what happens while ctrl is pressed the user has to use Rainmeter, like I did on the BangCommand.ini skin that when you press CTRL a hint displays below, that’s simply a MouseOverAction on the background meter. Or that Ctrl + Scrolling zooms the site, those are simple MouseScrollActions on the background meter.

Why don’t we use a Mouse Hook instead to actually drag the skin without needing CTRL?

WebView is interactive by nature, there are many elements that can be dragged. Using a mouse hook would make it very hard to decide when it is safe to move the window and when it is not. This is because WebView can’t give us information about anything that’s being rendered on the WebView window without using JavaScript (which is out of the table given that is not reliable on all websites). Without that information we could only take half-informed guesses based on window messages related to things like mouse position, cursor kind being requested, etc. That doesn’t guarantee that we won’t break some page functionality by moving the skin window instead of dragging an actual web element.

@RicardoTM05
Copy link
Contributor Author

Notification: Updated post above.

@Yincognyto
Copy link

Yincognyto commented Jan 14, 2026

I. 1st proposal (@Yincognyto):

  1. OK: Basically how it works already.
  2. NP: It’s not possible to request the BrowserMenu while interacting with the skin.
  3. OK: It would be exactly how SkinControl=2 works right now
  4. NP: It’s not possible to request the SkinCustomMenu while interacting with the skin.
  1. Exactly, this is OK.
  2. I clearly said skin menu and not browser menu here, please read again.
  3. Exactly, this is OK.
  4. The skin itself can already do that, it doesn't even need the plugin for it.

TBH, I only left 4. because you like SkinCustomMenu, otherwise 1. + 2. + 3. are practically enough (4. is reproducible in 2. & 3.). Basically, 1. is all around browser behavior, 2. is all around skin behavior, 3. is CTRL toggling between browser and skin behavior. The 1. would go to SkinControl=0, the 2. would go to SkinControl=1, the 3. would go to SkinControl=2. A simple, effective option. Even if one wanted the skin standard / custom menu while the browser behavior was active, this is already present, credit to you:
Calendar
The screenshot was made on the Calendar.ini skin, while having SkinControl=2 and ContextMenu=1, and not holding CTRL.


II. 2nd proposal (@RicardoTM05):

What I propose:

  • Build/enforce SkinControl=2 functionality into the plugin.
  • Remove SkinControl as an option.
  • SkinControl=3 functionality is gone.
  • Bring Clickthrough option back.
  • Leave ContextMenu option alone.

As much as SkinControl=2 functionality is useful, enforcing it is not. As was already mentioned, this means that:

Any WebView Ctrl + Mouse action won’t work

So, the user won't be able use any CTRL + Mouse events in Javascript, which would break skins relying on that.


III. 3rd proposal (alternative):

Another way to approach this, if the 1st proposal is still not acceptable even after proving it's possible, would be to just remove SkinControl=3 and ContextMenu=0 from the current implementation. This won't fix inconsistencies, but will eliminate what's not working or useful, and alleviate things in that regard. This requires minimal work and will provide "some" context menu in all cases like it's normal to happen while removing the unworking scrolling, but on the other hand it won't change the fact that the "clickthrough" system and the "contextmenu" system are simply not connected with each other in a coherent fashion like the user would expect, which is more or less the root of the problem in this matter and what the 1st proposal is trying to address.


It's hopefully clear how the 1st proposal is coherent, unrestrictive, simple and functional - just what the end user expects.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 14, 2026

I clearly said skin menu and not browser menu #13 (comment), please read again

I read again, you clearly wrote:

SkinControl=1 -> SkinControl=1 + ContextMenu=1, merged into SkinControl=1 (full skin [drag + menu], not CTRL based)

SkinControl=1 = Clickthrough=1
ContextMenu=1 = BrowserMenu
Clickthrough=1 + BrowserMenu = Not possible.

If you can’t click on WebView you can’t request the BrowserMenu.

The skin itself can already do that, it doesn't even need the plugin for it.

Then it doesn’t even make sense that you mentioned it, we are talking about what the plugin can do, and it certainly can display the skin custom menu, only not where you are trying to place it.

What you propose is equally restrictive. Enforcing the BrowserMenu is not a good idea, even if I already added SkinMenu as an item.

On the calendar example you showed it perfectly.
The calendar has an option on the skin menu to change the locale (Toggle Locale), which is now hidden behind the SkinMenu item.

image

The BrowserMenu is not as useful as the SkinMenu on that skin for the simple fact that the browser menu is not modifiable. Using the SkinMenu or the SkinCustomMenu is more useful for most skins because it lets give the end user direct access to custom functions that really matter for the skin (see Clock.ini), not for a browser.
Now you replaced a skin function (Toggle Locale) with Save as, Downloads and Print which are completely useless for the skin, excellent.
Yes, it is still present if you use CTRL but that doesn’t need to be that way, the user in that skin should not have direct access to useless options first and press ctrl to get to the useful ones, when it could simply right click and get to what matters right away.

You want it to be:

  1. All about browser
  2. All about skin
  3. Mixed.

When it could be simply:

  1. No helpers - Clickthrough=0 - For pros that want to implement their own logic through JS. (your Earth skin)
  2. Non-interactive skins - Clickthrough=1 - For basic skins that only serve displaying purposes with no web interactive elements. (Clock.ini, IslamicDate.ini, Weather.ini)
  3. Interactive skins - Ctrl toggle-able clickthrough - For skins that use interactive elements but still want to be able to drag the skin while holding CTRL. (Calendar.ini, YoutubePlayer.ini)

PS. I’m using Clickthrough instead of SkinControl to be clearer on functional meaning, but I'm still taking about SkinControl.

Definitions:

  • An interactive skin is that one that has web elements that can be interacted with.

  • A non-interactive skin is that one that only has web elements for display purposes.

Since Mode 1 is non interactive they will only have access to the SkinMenu/SkinCustomMenu through Rainmeter.

Modes 0 and 2 have access to all context menu types based on their preferences, no restrictions.

Only Mode 2 has ctrl based functionality and restrictions which may or may not affect skin functionality, in case it does then they can move to Mode 0 and implement their own logic through JS as they like, or stay at Mode 2 and simply re-think their logic to not use Ctrl.

This system satisfies everyone, I know you will stay at Mode 0 and use full scripting, I would certainly sit on Mode 2 and most beginners using webview to display simple stuff will sit at Mode 1.

While browsing skins are possible and totally supported, those shouldn't be used to define what should be the standard for everyone. We should be using original skins as the standard, not skins that simply display a website or try to mimic a browser, which again, are totally supported and perfectly valid skin types.


Third proposal:

  • Remove SkinControl=3
    I agree.

  • Remove ContextMenu=0
    I don’t agree unless you give a clear reason why it should not be allowed.

Take into account that removing the ContextMenu is also possible through JS, so I don't see why the plugin should forbid it:

document.addEventListener('contextmenu', function (event) {
    event.preventDefault();
});

And, if you indeed give a good reason why it shouldn’t be allowed, then the option should be renamed again because 0 won’t mean disabled anymore, which will be confusing.

on the other hand it won't change the fact that the "clickthrough" system and the "contextmenu" system are simply not connected with each other in a coherent fashion like the user would expect

ContextMenu and Clickthrough systems are not related, they are not connected. You or the user expect it or not, they are not and they won't be because, in fact, they technically can't be connected through the current implementation. One controls WebView context menus and the other the ability to click on the WebView area. Relating each other is like relating an apple with a pineapple just because both have “apple” in their names.


What do you think @NSTechBytes ?


I think we should forget about SkinControl as a name and use clickthrough as that is apparently less confusing, even though it has 2 values instead of only 1.

@NSTechBytes
Copy link
Owner

I think ClickThrough is fair enough, as adding more options can create confusion for users. We can achieve the SkinControl behavior by using the basic functionality of the plugin.

@Yincognyto
Copy link

Yincognyto commented Jan 15, 2026

SkinControl=1 -> SkinControl=1 + ContextMenu=1, merged into SkinControl=1 (full skin [drag + menu], not CTRL based)
SkinControl=1 = Clickthrough=1 ContextMenu=1 = BrowserMenu Clickthrough=1 + BrowserMenu = Not possible.

Exactly! Sorry, I meant SkinControl=1 -> SkinControl=1 + ContextMenu=2, I was misled by the fact that SkinControl=1 + ContextMenu=1 does precisely the same thing in practice, i.e. give the skin menu, when I wrote it. I know why this happens, but users who don't will find it confusing, redundant and against the docs that say ContextMenu = 1 = browser menu and ContextMenu = 2 = skin menu, yet they do the same skin menu for different ContextMenu values. They'll say that "the browser menu doesn't work when ContextMenu = 1", and "why skin menu is given for both the 1 and 2 values of ContextMenu".

Then it doesn’t even make sense that you mentioned it

I only mentioned it because you added ContextMenu=3 on your own in the first place, even though it was perfectly reproducible from the skin itself, so if anything, it didn't even make sense that you added it. That wasn't the point though, the point was that is possible which is is, despite the NP argument and that "I" was the one mentioning afterwards. Seriously now, this is not about me and you, your options vs my option, your skin vs my skin, we need this to work coherently for everyone.

The calendar has an option on the skin menu to change the locale (Toggle Locale), which is now hidden behind the SkinMenu item.

I already mentioned this, but it's ok, I'll repeat myself for the N-th time - Windows 11 already does this with the "Show More Options" item in its context menus, yet I didn't hear you complain about it, being a happy Windows 11 user, it's only when I propose the exact same thing, based on your own work and brilliant addition of Skin Menu in the browser menu, only then it's an issue. But I'll give you that, you do have an argument here, unlike in other cases, but hey, they can't be all in front, right? I'll again do what I shouldn't do and give you ideas that you can abuse on me later on, just because we're friends, lol: maybe you can also expose the browser menu items to the user so they're free to make a mess out if it and move their own items from the skin menu to the browser menu. This has an additional benefit, at least for me: the browser menu is same theme as Windows aka dark, while the skin menu insists being light cause well, I have no idea why (yes, I know I can force it dark, just saying).

You want it to be:

  1. All about browser
  2. All about skin
  3. Mixed.

When it could be simply:

  1. No helpers - Clickthrough=0 - For pros that want to implement their own logic through JS. (your Earth skin)
  2. Non-interactive skins - Clickthrough=1 - For basic skins that only serve displaying purposes with no web interactive elements. (Clock.ini, IslamicDate.ini, Weather.ini)
  3. Interactive skins - Ctrl toggle-able clickthrough - For skins that use interactive elements but still want to be able to drag the skin while holding CTRL. (Calendar.ini, YoutubePlayer.ini)

I just don't understand you grasping at straws at every word I say - "you want it to be" is precisely "when it could be simply" above - literally the only differences between what you implemented and what I proposed are these, for my proposal:

  • it's a single option, whatever its name is, SkinControl or Clickthrough, at this point you can name it Ricardo and I'll be fine
  • the integrated ContextMenu behavior is aligned and corresponds with what SkinControl / Clickthrough does in the latter

I don't want ContextMenu gone, I simply want it work seamlessly and coherently with Clickthrough in the background, that's it.

This system satisfies everyone, I know you will stay at Mode 0 and use full scripting, I would certainly sit on Mode 2 and most beginners using webview to display simple stuff will sit at Mode 1.

No. I use both Clickthrough=0 AND Clickthrough=2 (the 1st in my Earth cause it's already written, the 2nd once this is done and because it's toggleable by demand being CTRL based). I don't use Clickthrough=1 simply because there is no way to get the (complete) browser behavior in that case, which is what this plugin should be all about, along with skin behavior of course.

  • Remove ContextMenu=0
    I don’t agree unless you give a clear reason why it should not be allowed.

I just gave you the most compelling one: nobody wants no context menu at all. It's either one or the other, as the user desires.

in fact, they technically can't be connected through the current implementation

You keep bringing this even though I proved the exact opposite above. Ok, I wrote SkinControl=1 -> SkinControl=1 + ContextMenu=1 when I should have written SkinControl=1 -> SkinControl=1 + ContextMenu=2, my bad I was misled by your implementation in the first place, but it's not a big deal, since I repeatedly said that I meant complete skin behavior when referring to that choice, aka Clickthrough=1, obviously with the skin menu and not CTRL based, to make it clear what I meant.


So, to summarize:

Clickthrough = 0 -> all about browser (as I said it) = no helpers (as you said it) 
Clickthrough = 1 -> all about skin (as I said it) = non interactive (as you said it)
Clickthrough = 2 -> mixed based on CTRL (as I said it) = interactive (as you said it)

It's the same thing, for the love of God. Just with the internal ContextMenu behavior not exposed as an additional option confusing users and providing unrelated behavior compared to Clickthrough and same behavior for different option values as clearly explained in my 1st paragraph, but aligned with what Clickthrough does, either via your own internal code for ContextMenu or coming it naturally as a consequence of Clickthrough. So, when I'm dragging the skin I also want the skin menu, when I select some text on the browser I also want the browser menu, and when I hold CTRL I can choose between them. I'm ok with the ContextMenu functionality if that helps, I just don't want it behaving differently than Clickthrough itself.

@RicardoTM05
Copy link
Contributor Author

Ok, let's agree to disagree.

I'm not following this conversation, I could go on giving reasons why keeping ContextMenu is preferable.


We all agree on Clickthrough , that's settled.

Clickthrough=[0,1,2]
  • 0 Disabled
  • 1 Enabled
  • 2 Ctrl Toggleable

@NSTechBytes has the last word about what we disagree on: ContextMenu.

@Yincognyto 's

ContextMenu=Removed

@RicardoTM05 's

ContextMenu=[0,1,2,3]
  • 0 No context menu
  • 1 Browser menu
  • 2 Skin menu
  • 3 Skin custom menu

@Yincognyto
Copy link

Yincognyto commented Jan 15, 2026

I think ClickThrough is fair enough, as adding more options can create confusion for users.

So you're ok with only:

Clickthrough = 0 -> browser behavior all the way (browser drag + browser menu)
Clickthrough = 1 -> skin behavior all the way (skin drag + skin menu)
Clickthrough = 2 -> alternate behavior via CTRL (either browser drag + browser menu or skin drag + skin menu)

just make sure we're all on the same page with a single, clear and coherent option?

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 15, 2026

To be perfectly clear, I’ll repeat myself.
There’s no relationship between Clickthrough and any menu, no browser menu, no skin menu, no custom menu.

[Clickthrough] can’t simply replace [any menu] with anything because it has no control over that, it doesn’t control any mouse gesture or anything, it simply toggles [the ability to click on the WebView area] and nothing else

The functionality Ying mentions above that has to do with menus is consequential only, not Clickthrough logic and is not coded anywhere. The only intentionally supported way to change the context menu is through the ContextMenu option.

To test how the plugin would work with ContextMenu removed, use:

SkinControl=[0,1,2]
ContextMenu=1

To test with ContextMenu use:

SkinControl=[0,1,2]
ContextMenu=[0,1,2,3]

PS. ContextMenu=3 requires to have a custom context menu set, here's one for you to drop in:

[Rainmeter]
ContextTitle=Open DevTools
ContextAction=[!CommandMeasure WebView2 "Open DevTools"]
ContextTitle2= Open Task Manager
ContextAction2=[!CommandMeasure WebView2 "Open TaskManager"]
ContextTitle3= Reload
ContextAction3=[!CommandMeasure WebView2 "Navigate Reload"]
ContextTitle4= ---
ContextAction4=[]
ContextTitle5= Skin Menu
ContextAction5=[!SkinMenu]
ContextTitle6= ---
ContextAction6=[]
ContextTitle7= Unload Skin
ContextAction7=[!DeactivateConfig]

@Yincognyto
Copy link

@NSTechBytes has the last word about what we disagree on: ContextMenu.
I think ClickThrough is fair enough, as adding more options can create confusion for users.

We should all agree on this, this is not a plugin for just one of us, but for everyone, and we all want the best for it.

The functionality Ying mentions above that has to do with menus is consequential only

I'm ok with it either way, that why I said "or coming it naturally as a consequence of Clickthrough" earlier.


I would have preferred to come from your ContextMenu functionality, just to avoid all this and please you - hence compromising with the alternate proposal rejected earlier. I have zero intention of antagonizing anyone only because of a ContextMenu option that just doesn't follow what Clickthrough does in terms of consequential or not effect on menus, and has a part in having the same behavior on menus for different values of the option, which was my entire case in this too long and too heated discussion...

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 15, 2026

I would have preferred to come from your ContextMenu functionality, just to avoid all this and please you - hence compromising with the alternate proposal rejected earlier. I have zero intention of antagonizing anyone only because of a ContextMenu option that just doesn't follow what Clickthrough does in terms of consequential or not effect on menus, and has a part in having the same behavior on menus for different values of the option, which was my entire case in this too long and too heated discussion...

I totally understand that you defend your position, as I defend mine. We are on a disagreement and that’s perfectly fine, you don’t have to please me nor I have to please you. We are both looking for the best for the plugin from different points of view and that’s fine. I understand your position: you see Clickthrough=1 and holding Ctrl while Clickthrough=2 shadowing ContextMenu as incoherent, inconsistent. That can raise questions about why is ContextMenu “not working” at all when clickthrough=1 or partially when holding Ctrl.
I say that ContextMenu makes perfect sense and is useful enough to not care about it, that it bringing more to the plugin weights more than questions anyone could have or confusions that could occur.

We both have our opinions and made our decisions, now is NSTechBytes turn.

PS. I also agree that we should all agree on the same, but let’s be human, we can’t agree on everything and that’s fine. We can agree with whatever decision NSTechBytes takes and move on.

@NSTechBytes
Copy link
Owner

If you don’t mind, I’m not in favor of using a ContextMenu because it conflicts with the ClickThrough behavior.
Also, I’m not in a position to add new features while existing issues are still unresolved especially the RainmeterAPI availability.

@NSTechBytes NSTechBytes merged commit 11bc961 into NSTechBytes:main Jan 16, 2026
1 check passed
@NSTechBytes
Copy link
Owner

I’m also considering releasing the final version of the plugin, as it now seems stable enough for release. Some testing is still pending on my side.

RicardoTM, could you please update the README when you have time? You’re familiar with all the recent additions and changes.

@RicardoTM05
Copy link
Contributor Author

I’m also considering releasing the final version of the plugin, as it now seems stable enough for release. Some testing is still pending on my side.

Let me know if you have questions.

RicardoTM, could you please update the README when you have time? You’re familiar with all the recent additions and changes.

Sure, I will be adding to it as I have time.

@Yincognyto
Copy link

Yincognyto commented Jan 16, 2026

I agree with everything Ricardo said - we need people to start using this consistently (with the addendum that we're aware of the YouTube issue with RainmeterAPI and of a potential workaround, and we'll try to find the best solution for it, hopefully "official" if possible as nstechbytes said, and implement it) as its "core" is already in its final & stable form. Maybe suggesting them to already have a version of their work (i.e. skin or skins) using the WebView2 plugin instead of the old WebView one (like I did with all my skins, Earth, BlueMarble, etc.) would be a good idea, as it's just about adding a "2" to the plugin name and potentially set a few options (like e.g. Clickthrough) as desired to do this.

I'm of the firm belief that only actual usage in "real world" scenarios with skins and everything, would allow any user to let us know of any other things (ideas, issues, scenarios, etc) worth considering, if any - and for that, the time off Ricardo mentioned comes really handy, as it allows that for everyone. The scripting / RainmeterAPI can be done "in the background" from a development point of view, of course based on everyone's feedback on what would be needed at least at a minimal level, as anything pertaining to it won't (radically?) change the existing options.

Speaking of scripting, RainmeterAPI and YouTube, I'm not yet sure how we should best inject RainmeterAPI: only in the top window, or in all windows (all descendants, not just direct top window children). On one hand, the former seems the best solution in terms of efficiency, non redundancy and maybe performance, but on the other hand it's only the fact that Ricardo did the latter that allowed me to discover what could be a potential workaround (e.g. using window[N].RainmeterAPI instead of window.top.RainmeterAPI).

By the way, Ricardo, maybe you should send nstechbytes (or even post it somewhere in our GitHub conversation thread) one of your plugin versions that does scripting / all descendant frame injection of RainmeterAPI (so as to avoid you working on adding that on the current version now just for this), only for him to be able to test the window[N].RainmeterAPI workaround on YouTube and see that it works, because as of now I think he only has my report about it and no means of testing / debugging / see why that happens and why it doesn't for the top window, etc. If we're going to try and solve that, we should use all resources (and people) we can, you never know "what hole the rabbit comes out of", so to speak - after all, I only discovered that because I spent time trying all avenues on those versions of yours, and while I am a developer, I'm not even a C++ developer...

P.S. Minor observation on the sample BangCommand.ini file, Ricardo - the "tooltip" below WebView still has the value of 3 info.
P.S.S. I still have to test some things on my own, mainly the Host, UserAgent (partially), Notifications and AssistiveFeatures, as I didn't get the chance to do so with our debate on Clickthrough (whose name change jsmorley might potentially object on, but hey, we're still on alpha stage so all is permitted until it's released as final), but I'm sure they work since Ricardo included skins using those, for conveniency - it's more about seeing what they can do when pushing them left and right and playing with them.

@RicardoTM05
Copy link
Contributor Author

The current version already injects RainmeterAPI on the main document, top and nested frames. This is because it is injected through the AddScriptToExecuteOnDocumentCreated function which already injects to everything.

It’s only ExecuteScript command that only executes scripts on the main document. The other version was executing on every frame as well, which was not the best implementation. I personally liked more using the designated frame event script actions instead of having ExecuteScript triggering on all documents at the same time, iterating on frames is expensive. The script actions were more “organic” as they would trigger at the right times on frame events instead of everywhere at the same time. The only thing missing was being able to choose what frame to execute the scripts on, unfortunately frame recognition is not possible as there’s no information accessible to both the user through html and the plugin that could be used to identify them.

Sure I can publish a version for him to try the workaround. Just know that current options may be missing, have different name or work differently. Will do on the appropriate issue.

We should also take a decision about ExecuteScript by the way before any release.

Should we leave it as ExecuteScript or should we only name it Execute instead?

So, it would be something like:
[!CommandMeasure WebView2 “Execute console.log(‘test’)”]

Then we could have another like:
[!CommandMeasure WebView2 “Execute Frame console.log(‘test on frames’)”]
Although this command would still iterate through all frames but at least the user would use it consciously.

And
[!CommandMeasure WebView2 “Execute File path/to/script.js”]
Or omit the file part and integrate it on both commands above in a way that the commands recognize it’s a file.js and not a script.

I mean, it could work with ExecuteScript too only that it would be longer.

But I digress, what matters right now is the command name.

Ah, thanks for letting me know, I’ll fix it and will commit together with the Readme.md file when done.

@Yincognyto
Copy link

Yincognyto commented Jan 16, 2026

The current version already injects RainmeterAPI on the main document, top and nested frames.

Ah, you're right indeed - no need to post an older version, this one is sufficient to test how e.g. window[0].RainmeterAPI.Bang('[!Log "Test"]'); or window[1].RainmeterAPI.Bang('[!Log "Test"]'); work over window.top.RainmeterAPI.Bang('[!Log "Test"]'); on YouTube - all good (obviously, it's not always the 0th window and not always the 1st window, albeit didn't encounter a case where it would be >1, so I just say window[N] to cover all possibilities). I was misled by some test I made (I think on one of your versions posted / edited in the last reply in the conversation thread), where RainmeterAPI seemed to miss from child frames and couldn't test this. I then thought you left that part for the scripting PR.

But yeah, for example, I can do this:

LeftMouseUpAction=[!CommandMeasure WebView2 """ExecuteScript try {window.top.RainmeterAPI.Bang('[!Log "Test"]')} catch {}; try {window[0].RainmeterAPI.Bang('[!Log "Test"]')} catch {}; try {window[1].RainmeterAPI.Bang('[!Log "Test"]')} catch {};"""]

and print "Test" to the Rainmeter log from a YT page already, which is good enough to test for anyone including NSTechBytes.

It’s only ExecuteScript command that only executes scripts on the main document.

As of now, without more cases to investigate where executing scripts on frames would be really useful, I think it's a safe and wise decision for this PR. Not entirely sure if it applies to every scenario, but I think the user might be able to run the things in his script on the desired frame (probably subject to cross origin security though) just through the window[...][...]... system. My take is that IF the user is already able to run whatever in a frame of his choosing, then the plugin shouldn't necessarily try to do that for him, bar maybe helping out with whatever security system is getting in the way of that.

Should we leave it as ExecuteScript or should we only name it Execute instead?

I personally think just Execute is fine. Either "Execute Script ..." and "Execute File ...", or "Execute ..." where the plugin detects whether it's an inline script or a script file is fine with me (can be variations of that, of course). Just about the only thing I would insist on (for - you guessed it - consistency and coherency) is that the syntax is similar between the two. For example, I would not particularly like "ExecuteScript" for inline scripts, but "ExecuteScriptFile" for script files - in such a hypothetical case, I'd prefer "ExecuteScript" and "ExecuteFile" instead, cause it has the same "syntactical parts", so to speak.

Then we could have another like: [!CommandMeasure WebView2 “Execute Frame console.log(‘test on frames’)”]

Could be, but like I said, IF the user is able to better select the desired frame than the plugin does it (with the plugin ensuring access to every frame at any level, if possible), then let him do it. The way I see it and based on what you explained to me, identifying frames is trickier from the plugin side since WebView2 doesn't provide enough info for that, so maybe the user is able to better do that from JS and such, if he can run his thing in those frames in the first place.

@RicardoTM05
Copy link
Contributor Author

Alright, I’m fine with that. If the user can do it on their own then I agree on not adding further framing logic as JavaScript side is more reliable.

Ok, I think having it simply as Execute is fine.
Like:
[!CommandMeasure WebView2 “Execute console.log(‘test’)”]

And after the scripting update also support:
[!CommandMeasure WebView2 “Execute path/to/file.js”]

It feels more consistent with the other commands syntax.

@NSTechBytes What do you think??

@Yincognyto
Copy link

Yincognyto commented Jan 17, 2026

Sorry to interject before NSTechBytes shares his opinion on the latest subject, but regarding the existing "ExecuteScript" command: just made a quick test, and you can actually use a WebParser (and probably a Quote plugin measure with a file ending char as separator as well) to run even now a script file, regardless of whether you replace newlines with spaces or not which I didn't expect but was curious to see if it worked - which is pretty neat.

Sure, if you change that file you'd have to command the WebParser to update before using it again as a parameter to ExecuteScript from the FinishAction, but it works! Obviously, a dedicated "Execute ...file..." would make it much more comfortable without resorting to such workarounds, but I thought you should know the above, as it's quite nice. I just tested my frame digging script file, and it returned all windows (aka frames) on the W3Schools frame test page flawlessly.

This could make the "Execute ...file..." implementation much easier as you wouldn't have to bother with formatting the contents of the file (I think?)...

Side note, the left side of the W3Schools frame test page doesn't return anything via View Page Source, but it's the same as in the browser, where a View Page Source isn't even given in the context menu, so it's not a plugin issue - just a curiosity to test.

@RicardoTM05
Copy link
Contributor Author

Actually, since the frames logic wouldn't be necessary anymore, I can include the script file logic when committing the Readme.md file if you are ok with that. I already have that logic written so it wouldn't take much time to include it. Then the plugin would release on 1.0 as practically feature complete.

@Yincognyto
Copy link

Yincognyto commented Jan 17, 2026

Actually, since the frames logic wouldn't be necessary anymore, I can include the script file logic when committing the Readme.md file if you are ok with that. I already have that logic written so it wouldn't take much time to include it. Then the plugin would release on 1.0 as practically feature complete.

Me, I'm ok with that, if NSTechBytes is ok with it too. We could present the YT workaround of calling the RainmeterAPI of a suited window[N] for whoever needs it, while we could look for a more "official" way to deal with that (if and when available), as the last piece of the puzzle to have this rock solid. It would simplify things and make this much easier for you.

Just a thought

Just as a last idea on the now removed ContextMenu option that only occured to me now (sorry, some thoughts can occur later): if it's possible to make it enter into effect only if present as an option, the same way the virtual host option reacts (i.e. if ContextMenu option is present, then the actual result table I wrote earlier comes into effect with the interdependency between Clickthrough and ContextMenu; if not present, Clickthrough reacts as if completely alone and exactly as it does now). As long as you'll be the one answering questions on their interdependency from the users and it doesn't get in the way of the current behavior of Clickthrough when the latter is alone, I personally don't have a problem with that. Just an idea, up to you guys to weigh on it, I don't want to restart a controversy, just cover all possibilities of tackling that issue before it's gone forever. If reasonable, fine, if not, also fine.

@RicardoTM05
Copy link
Contributor Author

Just a thought
Just as a last idea on the now removed ContextMenu: if it's possible to make it enter into effect only if present as an option, the same way the virtual host option reacts (i.e. if ContextMenu option is present, then the actual result table I wrote earlier comes into effect with the interdependency between Clickthrough and ContextMenu; if not present, Clickthrough reacts as if completely alone and exactly as it does now).

I’m not sure I understand. That’s how it used to behave, when the ContextMenu option was not present it would behave exactly as the current version behaves right now. Or was there a “side effect” when the option was missing that I’m not aware of?

@Yincognyto
Copy link

I’m not sure I understand. That’s how it used to behave, when the ContextMenu option was not present it would behave exactly as the current version behaves right now. Or was there a “side effect” when the option was missing that I’m not aware of?

No, you're right - it behaved the same because the ContextMenu default was 1 aka the browser menu when missing. I worded my previous reply incorrectly, writing about Clickthrough alone but referring to those 6 cases where it was actually Clickthrough (former SkinControl) that was getting in the way of ContextMenu in terms of expected vs actual results if the latter was considered "independent" as you'd normally want and expect from an option. Sometimes that Clickthrough "override" was desirable if you looked for Clickthrough behavior (e.g. Clickthrough: [1, 2 with CTRL on] and ContextMenu: [1]), but of course in all those said cases it didn't match with what ContextMenu promised to provide on its own (i.e. the "side effects").

Clickthrough naturally got away easily with it since its existence and flexibility made it essential for this kind of control, so ContextMenu took all the blame for it even though technically it was the former that was overriding things in most cases (with the notable exceptions of Clickthrough: [0, 2 with CTRL off] and ContextMenu: 0, when it was actually ContextMenu overriding what Clickthrough was providing on its own - further adding to the perceived "instability"). Testing mostly in BangCommand.ini which contained and allowed changing both options at will, made the matter excessively obvious, even more so if you looked at the tooltip texts you nicely placed as helpers.

But yeah, if on its default of 1 or missing, Clickthrough behaved the same as it is now. I think what I really meant with the above is if there was a reasonable way to communicate that "hey, if you use both you're on your own and the result isn't guaranteed to go one way or another as per each option's own description", it could have been somewhat more acceptable to have both, given the extra that ContextMenu sometimes provided. Too bad the 2 of them together affected the "predictibility" of each... I'm pretty sure even you, after a year or two of settling on one or two particular combinations, things becoming less fresh in your mind, and then starting to often adjust their values, would have been at least surprised by their effect together.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 18, 2026

I think what I really meant with the above is if there was a reasonable way to communicate that "hey, if you use both you're on your own and the result isn't guaranteed to go one way or another as per each option's own description", it could have been somewhat more acceptable to have both, given the extra that ContextMenu sometimes provided.

Well, they are on different categories, while Clickthrough is part of the Window Options category, along with W, H, X, Y and Hidden. ContextMenu was part of the Browser Options category, along with NewWindow, AssistiveFeatures, ZoomControl, etc. That alone should help avoid building any relation between them. Of course these differences are quite more obvious now that the option is called Clickthrough. I certainly don't know how to communicate it as I've failed already, I wouldn't even mention it anymore to avoid any possibility of making someone relate them.

I'm pretty sure even you, after a year or two of settling on one or two particular combinations, things becoming less fresh in your mind, and then starting to often adjust their values, would have been at least surprised by their effect together.

I highly doubt it. I, personally, understand how Clickthrough works and what's its intended use. There is no relationship between that and context menus in my mind. I consider it difficult to relate them actually. But who knows, I have certainly quite bad memory. Still, I doubt it.


Anyways, just to summarize things a little bit for @NSTechBytes, we need answers to these questions so I can commit the readme when done:

  • Should ExecuteScript be renamed Execute? - Ying: sure, Me: sure, NST: ??
    • That name is more consistent with the other commands' names
  • Should the script file functionality be included on the now named Execute command? - Ying: sure, Me: sure, NST: ??
    • I already have it in code, just need to add it and the plugin would be practically feature complete.
  • Is ContextMenu really gone? - Ying: ??, Me: bring it back, NST: ??
    • Ying raised the question if it could come back.

@NSTechBytes
Copy link
Owner

I have no issue with changing from ExecuteScript to ExecuteCommand.
However, I have one question: how would ExecuteFile be useful?
If it is intended for scripting or logic, I think that would be a bad idea, since Rainmeter already provides built-in Lua scripting for that purpose.
If it serves another purpose that I don’t understand, please forgive my confusion.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 18, 2026

I have no issue with changing from ExecuteScript to ExecuteCommand.

Just for clarity:
ExecuteScript -> Execute
Without “Command”

However, I have one question: how would ExecuteFile be useful? If it is intended for scripting or logic, I think that would be a bad idea, since Rainmeter already provides built-in Lua scripting for that purpose. If it serves another purpose that I don’t understand, please forgive my confusion.

The command Execute would accept scripts as strings or paths to .js files.

For example:
As a string:

[!CommandMeasure WebView2 """Execute alert("example"); console.log("script string executed");"""]

As a file:

[!CommandMeasure WebView2 "Execute #@#script.js"]

@Resources\script.js

alert("example");
console.log("script file executed");

It is not a complete script parser, but a way to execute scripts correctly formatted on their own .js file.

I can upload a testing version if you’d like to see it in action.

it is especially useful when injecting longer scripts, as you are no longer limited to one liners, but can write a complete script file and inject it.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 18, 2026

Not sure what the "like" means but here's the testing version:
WebView2_v0.0.8_x64_x86_dll.zip

Simply use on the BangCommand.ini skin:

[!CommandMeasure WebView2 "Execute alert('example');"]

or, create a script.js file and use instead:

[!CommandMeasure WebView2 "Execute #@#script.js"]

@Yincognyto
Copy link

Yincognyto commented Jan 18, 2026

Well, they are on different categories

Exactly, yet they're forced to relate as part of the same plugin. The duo is like this together: functionality = exists, usefulness = exists, predictibility = lacks. The first two are great. The last only exists all around if folks would go "developer technical" about it.

However, I have one question: how would ExecuteFile be useful?
If it is intended for scripting or logic, I think that would be a bad idea

Just to add to Ricardo's explanation about executing script files, it has several benefits:

  • it allows expanding a script on multiple lines, improving readability, especially for longer scripts
  • it allows executing the script without refreshing the skin, if the script file is read before its execution
  • while using script files is possible for local pages you control, this allows the same for online pages
  • it matches Lua which allows the same (i.e. inline and files), but with many more capabilities vs Lua

Think of a more complex animation executed on click or mouse over, as an example. Doing that in a one liner is uncomfortable. I would be curious to know why you thought it was a bad idea. I mean sure, you can use Lua, but can't do as much in Lua as you can with JS, and certainly not necessarily in a web context. This would just bring the abiility to execute JS at the same level to Lua. You tried to do the same, with the unfortunately async window.onInitialize() or window.onUpdate(), and [WebView2:CallJS()], which was great if not for the out of sync return of the first two - hopefully the latter can fill what the former two were doing.

P.S. By the way, besides trying to find an official solution for RainmeterAPI on YouTube as a pending issue, I think the ability to use non UI extensions (like e.g. UBlock Origin) would help immensely with both security and comfortable navigation in the plugin. Ricardo already enabled their usage, but it appears a bit more code and testing would be needed to have that functional. It's certainly possible, if the extension is in an unpacked state. We made some tests before, but we're still missing something to work.

Not sure what the "like" means

I think it's for clarifying and explaining what it meant - I gave you a like for the same reason (I'm slower with likes on GitHub though, I "like to like" things only after the matter is settled and set in stone, so I react "retroactively" in that regard).

@NSTechBytes
Copy link
Owner

Think of a more complex animation executed on click or mouse over, as an example. Doing that in a one liner is uncomfortable. I would be curious to know why you thought it was a bad idea. I mean sure, you can use Lua, but can't do as much in Lua as you can with JS, and certainly not necessarily in a web context. This would just bring the abiility to execute JS at the same level to Lua. You tried to do the same, with the unfortunately async window.onInitialize() or window.onUpdate(), and [WebView2:CallJS()], which was great if not for the out of sync return of the first two - hopefully the latter can fill what the former two were doing.

That’s why I initially thought it was a bad idea, especially since the previous version was rejected. However, I now realize that adding the Execute File is actually a good move.

@Yincognyto
Copy link

That’s why I initially thought it was a bad idea, especially since the previous version was rejected. However, I now realize that adding the Execute File is actually a good move.

Ah, ok - sure thing. The rejection was more of an adjustment to try to keep the things that worked flawlessly and as expected.

@RicardoTM05
Copy link
Contributor Author

Alright, so we all agree on

  • Execute and Execute File

The readme file is almost finished.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 19, 2026

About extensions:

On Sunday I had some time to re-try extensions with great news. I managed to install them. Unfortunately I didn't have time to actually test with real extensions, I tested with an example extension from the docs.

Anyways, I did implement some logic into it. I won't have much time so I would appreciate it if you could test it with real extensions when you guys have time:

WebView2_v0.0.8_x64_x86_dll.zip

Also only tested with a single extension.

To install an extension:

  • Exit Rainmeter
  • Go to UserSettings.ini and set Extensions=true
  • On the new Extensions folder drop a UI-less unpacked extension folder.
  • Launch Rainmeter
  • Done
📁 RainmeterWebView2\
 └── 📁 Extensions\
      └──📁 example-devtools-extension\

To disable\enable an extension

  • Exit Rainmeter
  • Go to Extensions\Extensions.ini
  • Set Enabled=false or Enabled=true
  • Launch Rainmeter
  • Done

To uninstall an extension

  • Exit Rainmeter
  • Go to Extensions\Extensions.ini
  • Set Uninstall=true
  • Launch Rainmeter
  • Manually remove the unpacked extension from the Extensions folder.
  • Done

Logs will be logged when the extension is either installed/uninstalled or enabled/disabled.

Here's the extension I was using to test. It creates an "Example" tab on DevTools.

example-devtools-extension.zip

image

@Yincognyto
Copy link

Yincognyto commented Jan 19, 2026

Brilliant work - this last upload is a keeper, once given the green light! Tested Extensions: Internet Download Manager (IDM) and UBlock Origin (UBO) - Test Results: Success In Both Cases - Side Notes: UI Elements Are Incorrectly DevTools Positioned. I tested everything except Uninstall = true since, well, I love it so much that I don't even want to uninstall the tested extensions.

What I did was to follow the above instructions by @RicardoTM05, and then simply paste (and rename for conveniency) the C:\Users\[User]\AppData\Local\Microsoft\Edge\User Data\Default\Extensions\[ExtensionId]\[ExtensionVersion] folder to the C:\Users\[User]\AppData\Local\Temp\RainmeterWebView2\Extensions folder described in the above instructions (since the manifest.json file must be directly in the individual extension folder from the described Extensions folder). The results...

WebView2 - Extensions - IDM Enabled, UBO Disabled (W3Schools) > notice how the ad at the top of the page is displayed:

WebView2 - Extensions - IDM Enabled, UBO Disabled (W3Schools)

WebView2 - Extensions - IDM Enabled, UBO Enabled (W3Schools) > notice how the ad at the top of the page is not displayed:

WebView2 - Extensions - IDM Enabled, UBO Enabled (W3Schools)

WebView2 - Extensions - IDM Enabled, UBO Disabled (YouTube) > notice how the ad over the page video is displayed:

WebView2 - Extensions - IDM Enabled, UBO Disabled (YouTube)

WebView2 - Extensions - IDM Enabled, UBO Enabled (YouTube) > notice how the ad over the page video is not displayed:

WebView2 - Extensions - IDM Enabled, UBO Enabled (YouTube)

In the last two images above you can also notice how the Download this video panel from IDM is displayed in the DevTools window, instead of top right anchored on the top right corner of the YouTube video from the page. Not a deal breaker anyway.


On the same bright side, about the !Execute comand, RainmeterAPI and YouTube...

Drag example on YouTube, if CTRL on and Clickthrough=0 (1st valid RainmeterAPI is placed in top.api for usage):
function ckh(evt) {if (evt.button  == 0 && evt.ctrlKey) {evt.preventDefault(); evt.stopPropagation(); return false;};};
function pdh(evt) {if (evt.button  == 0 && evt.ctrlKey) {evt.preventDefault(); evt.stopPropagation(); try {atx = evt.screenX - top.screenX + api.ReadFormula('X'); aty = evt.screenY - top.screenY + api.ReadFormula('Y'); top.setPointerCapture(evt.pointerId);} catch {}; isdragevent = true; return false;};};
function pmh(evt) {if (evt.buttons == 1 && isdragevent) {evt.preventDefault(); evt.stopPropagation(); try {api.Bang(`[!Move ${evt.screenX - atx} ${evt.screenY - aty}]`);} catch {}; return false;};};
function puh(evt) {if (evt.button  == 0 && isdragevent) {evt.preventDefault(); evt.stopPropagation(); try {top.releasePointerCapture(evt.pointerId);} catch {}; isdragevent = false; return false;};};
function cmh(evt) {if (evt.button  == 2 && evt.ctrlKey) {evt.preventDefault(); evt.stopPropagation(); try {api.Bang('[!SkinMenu]');} catch {}; return false;};};
function act(win)
{
  if (!api) {try {win.RainmeterAPI.Bang('[]'); top.api = win.RainmeterAPI;} catch {};};
  win.addEventListener('click'      , ckh, {capture: true});
  win.addEventListener('pointerdown', pdh, {capture: true});
  win.addEventListener('pointermove', pmh, {capture: true});
  win.addEventListener('pointerup'  , puh, {capture: true});
  win.addEventListener('contextmenu', cmh, {capture: true});
};
function dig(win) {act(win); for (var i = 0; i < win.length; i++) {dig(win[i]);};};
if (window == top) {var api = 0, isdragevent = false, atx = 0, aty = 0; dig(top);};
console.log('Script file executed!');
The above simplified > "Test" should always be printed at the Rainmeter log when executing the script on YouTube:
function act(win) {if (!api) {try {win.RainmeterAPI.Bang('[]'); top.api = win.RainmeterAPI;} catch {};};};
function dig(win) {act(win); for (var i = 0; i < win.length; i++) {dig(win[i]);};};
if (window == top) {var api = 0; dig(top);}; console.log('Script file executed!'); api.Bang('[!Log "Test"]');

WebView2 - RainmeterAPI - API Variable, Script File (YouTube)


Thanks for the great work, both of you!

@RicardoTM05
Copy link
Contributor Author

Great. Yeah the UIs on DevTools is unexpected, but I guess they did it that way so extensions could have UIs.
Great news on getting to work RainmeterAPI on YouTube!
So now I’m only waiting for @NSTechBytes confirmation.
We could very well say that now the plugin is practically feature complete. (Except for the missing and beloved CustomMenu option)

Among other fixes, the package also contains a fix I’m somewhat proud of.

  • Now app-region correctly displays the Skin Menu when right clicking on it.

It was really tricky to fix but I was successful at the end. You can see on the YoutubePlayer skin that now you can, apart from dragging it without pressing control, Right Click anywhere on the background and the skin menu will pop up. Right clicking on any other element will display the browser menu.
Unfortunately I could only request it on RMB down and not on up. This is because that area returns almost no window messages, so normal mouse messages like WM_RBUTTONDOWN and WM_RBUTTONUP are not sent (their Non-Client NC versions aren’t either). I had to use WM_SETCURSOR to detect HTCAPTION and WM_RBUTTONDOWN to then send a custom message to request the menu. Filtered by the WebView area so it is not triggered when clicking directly on the skin. Just in case you wonder, is not possible to request the browser menu here, the user is clicking on an “app region” which in the context of the plugin, the app is Rainmeter (the skin).
It’s a tricky implementation but is working nicely as far as I’ve tested, I wish it worked on mouse up instead though.

  • Fixed the Keyboard Menu key which used to request both the skin menu and the browser menu. Now it only requests the right menu according to which has focus.

  • Now clicking the skin area will make WebView lose keyboard focus, as other apps do.

  • I didn’t notice they didn’t work, but now fill passwords and autofill options from SkinSettings.ini work correctly.

This was key to fix extensions. Turns out I was calling their APIs from the wrong object lol, including the Extensions API.

Those fixes except for the last one were also available on the previous version I shared, but didn’t mention them as they were still under testing.

@Yincognyto
Copy link

Yincognyto commented Jan 19, 2026

Yeah the UIs on DevTools is unexpected, but I guess they did it that way so extensions could have UIs.

Hmm... dunno, to me it looks like either IDM not getting the correct "window" (which is not really a window in the classic sense) coordinates from WebView2 (runtime or plugin), or not expecting WebView2 instead of the browser. Unfortunately you can't test it unless I send it to you, since it has an app behind it which is not free. Also, in the previous extension tests before, I set IDM to capture downloads from the WebView executable and with the new plugin version I noticed that my clouds video was always downloaded from my Earth skin even without me telling it to do so, but once I unchecked the WebView executable from the app, it ceased to do that as expected, while still showing the panel as usual. By the way, the said panel only appears if you reload the page, it doesn't appear the first time - might be IDM or the plugin. In any case, this is on the right track, and I'll further investigate these glitches, because I'm certain there's a solution for them.

@RicardoTM05
Copy link
Contributor Author

Must be either the extension or WebView2. The plugin can only Install, enable/disable and uninstall extensions. It has no access to the extensions.

The window issue could be though, given that it’s running inside a “nested window”, which could complicate finding it to attach its UI.

@Yincognyto
Copy link

Yincognyto commented Jan 20, 2026

The window issue could be though, given that it’s running inside a “nested window”, which could complicate finding it to attach its UI.

Just checked the positioning again, and it seems the IDM extension is aware of the video dimensions in WebView, since the panel does in fact position itself from around the left edge of the DevTools window, plus the width of the video area. So, if I toggle the width of the WebView2 measure in BangCommand.ini, the panel will move horizontally according to the changed width of the video, but according to the left side of the DevTools window (more or less) instead of the left side of the video in the WebView2 area, so it seems the 1st possibility above is true.

EDIT: Got it with the IDM panel positioning! Well, not in the WebView2 area, where it still displays in the DevTools window, but in a new window, if NewWindow=1, where it displays exactly where it should. So it's indeed about a "proper" window...

The IDM extension positioning in a new window (at the bottom):

WebView2 YouTube IDM

I think this is down to the extension, which assumes an actual window and not an embedded one, since, well, the app was made for typical browsers in the first place. There's probably some place in the extension code where this could be adjusted.

@NSTechBytes
Copy link
Owner

Like Yincognito, everything is working except Uninstall = true.
However, I really like this new addition to WebView2.

P.S. Sorry, I can’t join the discussion because the timing doesn’t match my country’s time zone. I’m usually asleep when the discussions happen.

@RicardoTM05
Copy link
Contributor Author

RicardoTM05 commented Jan 20, 2026

That’s weird, Uninstall works fine for me. Here are more detailed instructions:

  • Exit Rainmeter
  • On Extensions.ini set Uninstall=true and save the file.
  • Launch Rainmeter.
  • On Rainmeter should be a debug log that says WebView2: “Extension Name” extension has been removed.
  • Its entire [section] on Extensions.ini should be automatically removed at this point.
  • Now it is safe to manually remove the extension’s folder from the Extensions\ folder

If you don’t remove the extension’s folder on this step, the extension will be automatically re-installed the next time Rainmeter is launched.

  • Now the extension is correctly uninstalled

To install the extension again simply drop the extension’s folder back to the Extensions\ folder.

Don’t worry, we are all from different time zones, we understand. :)

@NSTechBytes
Copy link
Owner

Edit: There was a typo. It’s working fine now.

@RicardoTM05
Copy link
Contributor Author

Readme.md finished.

New PR -> #14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants