It is currently August 8th, 2020, 11:07 pm

OnUnfocusGroup

Report bugs with the Rainmeter application and suggest features.
User avatar
Cariboudjan
Posts: 89
Joined: May 12th, 2019, 8:55 am

OnUnfocusGroup

Post by Cariboudjan »

I'm going to try to be proactive instead of being resentful to the recent change in the 4.4 beta...

Can we include an OnUnfocusGroup option that when paired with OnUnfocusAction, will only trigger OnUnfocusAction when any window or other config not included in OnUnfocusGroup is focused?

For example, configs 1 and 2 are both Group=Group1, while config 3 is Group=Group2. If configs 1 and 2 are clicked on back and forth, it will not trigger any OnUnfocusAction. If 1 or 2 have focus, and config 3 or any other window is selected, it triggers 1 or 2's OnUnfocusAction.

The OnUnfocusGroup creates a cluster of windows that are intended to function together, without triggering their individual OnUnfocusActions when navigating between them. In the below example, config 1 and config 2 belong to the same group (Group1), and each contain an OnUnfocusAction that, if triggered, will deactivate both configs. This is obviously an undesirable behaviour when you want both configs to behave as one cohesive device, like a submenu. Without an OnUnfocusGroup, navigating between submenus would cause everything to deactivate, when you may only want that behaviour when navigating outside of that group.
example.png
An example of where this would be useful is dropdown menu bars where each config opened may contain individual submenus that contain submenus, each belonging to independent configs. Without being able to group the skins together, navigating between submenus would cause all dropdown and submenus to close unintentionally, when you may only want their individual OnUnfocusActions to trigger when a config loses focus to any other config or window not belonging to that group.

example2.png
You do not have the required permissions to view the files attached to this post.
User avatar
Cariboudjan
Posts: 89
Joined: May 12th, 2019, 8:55 am

Re: OnUnfocusGroup

Post by Cariboudjan »

I would very, very appreciate this addition. I would be extremely helpful for many applications, including my own. Without it, it's virtually impossible to create proper menus and submenus with independent configs with normally functioning unfocus behavior...

It's actually legitimately killing me how much time I've put into this project only for a 30 second bug fix to ruin all of my work. The method I was using was really the only functional way to create proper menus and submenus in Rainmeter. Every other suite uses MouseLeaveActions and ActionTimers haphazardly to create some underhanded illusion that it behaves like a normal menu in Windows, and it really hurts that just like that my entire suite is broken beyond repair.
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: OnUnfocusGroup

Post by Yincognito »

Cariboudjan wrote:
April 18th, 2020, 5:54 am
I'm going to try to be proactive instead of being resentful to the recent change in the 4.4 beta...

Can we include an OnUnfocusGroup option that when paired with OnUnfocusAction, will only trigger OnUnfocusAction when any window or other config not included in OnUnfocusGroup is focused?

For example, configs 1 and 2 are both Group=Group1, while config 3 is Group=Group2. If configs 1 and 2 are clicked on back and forth, it will not trigger any OnUnfocusAction. If 1 or 2 have focus, and config 3 or any other window is selected, it triggers 1 or 2's OnUnfocusAction.

The OnUnfocusGroup creates a cluster of windows that are intended to function together, without triggering their individual OnUnfocusActions when navigating between them. In the below example, config 1 and config 2 belong to the same group (Group1), and each contain an OnUnfocusAction that, if triggered, will deactivate both configs. This is obviously an undesirable behaviour when you want both configs to behave as one cohesive device, like a submenu. Without an OnUnfocusGroup, navigating between submenus would cause everything to deactivate, when you may only want that behaviour when navigating outside of that group.

An example of where this would be useful is dropdown menu bars where each config opened may contain individual submenus that contain submenus, each belonging to independent configs. Without being able to group the skins together, navigating between submenus would cause all dropdown and submenus to close unintentionally, when you may only want their individual OnUnfocusActions to trigger when a config loses focus to any other config or window not belonging to that group.
While I'm not against your proposal by any means (quite the contrary), I believe that what you want can be achieved with minimal effort even with the current Rainmeter features.

Personally, I would approach this by creating a variable (ideally, this variable would be "global" to all skins, but even if all the skins use the same .inc file having the same variable, that variable is still not truly global, i.e. multiple instances of that variable, possibly having different values, will be used in each of those skins) holding the skin group's "ID" (or number, if you like) that the mouse was clicked on, or 0 otherwise (to cover the possibility of clicking outside all of the skins). Since the variable isn't truly global, as explained above, its (current) value would need to be "transmitted" to the rest of the skins on click, via a Config (or rather, Config group) specific !SetVariable (or rather !SetVariableGroup) bang. Then, in the OnUnfocusAction, rather than directly deactivating certain config groups, you'd !UpdateMeasure some Config specific version of a measure (such versions should be present in all the skins, or possibly included via an @Include option in all the skins) that will check whether the variable's value (i.e. the ID of the clicked skin) equals the ID of the group that the current skin belongs to (this can also be stored in a variable of some kind). If it does, don't do anything, but if it doesn't, then proceed with deactivating the group that the current skin belongs to - since the said skin was unfocused by a clicked skin that doesn't have the same ID (i.e. belonging to a different group).

So, until the devs consider your proposal (or if they don't), you could implement this approach. I think that if done correctly, it will yield the desired result - correct me if I'm wrong. ;-)

EDIT: Obviously, the initial value of the variable should be the same as the ID of the group the skin belongs to, so that the skins won't be deactivated on activation / load.
User avatar
jsmorley
Developer
Posts: 21218
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: OnUnfocusGroup

Post by jsmorley »

Give us a bit to look at this.
User avatar
Cariboudjan
Posts: 89
Joined: May 12th, 2019, 8:55 am

Re: OnUnfocusGroup

Post by Cariboudjan »

Yincognito wrote:
April 18th, 2020, 11:07 am
While I'm not against your proposal by any means (quite the contrary), I believe that what you want can be achieved with minimal effort even with the current Rainmeter features.

Personally, I would approach this by creating a variable (ideally, this variable would be "global" to all skins, but even if all the skins use the same .inc file having the same variable, that variable is still not truly global, i.e. multiple instances of that variable, possibly having different values, will be used in each of those skins) holding the skin group's "ID" (or number, if you like) that the mouse was clicked on, or 0 otherwise (to cover the possibility of clicking outside all of the skins). Since the variable isn't truly global, as explained above, its (current) value would need to be "transmitted" to the rest of the skins on click, via a Config (or rather, Config group) specific !SetVariable (or rather !SetVariableGroup) bang. Then, in the OnUnfocusAction, rather than directly deactivating certain config groups, you'd !UpdateMeasure some Config specific version of a measure (such versions should be present in all the skins, or possibly included via an @Include option in all the skins) that will check whether the variable's value (i.e. the ID of the clicked skin) equals the ID of the group that the current skin belongs to (this can also be stored in a variable of some kind). If it does, don't do anything, but if it doesn't, then proceed with deactivating the group that the current skin belongs to - since the said skin was unfocused by a clicked skin that doesn't have the same ID (i.e. belonging to a different group).

So, until the devs consider your proposal (or if they don't), you could implement this approach. I think that if done correctly, it will yield the desired result - correct me if I'm wrong. ;-)

EDIT: Obviously, the initial value of the variable should be the same as the ID of the group the skin belongs to, so that the skins won't be deactivated on activation / load.
So Config 1 and 2 both contain identical variable A. When 1 or 2 are focused, send variable A to all skins. Then when unfocused, check if newly focused window also contains A. If true, do nothing. If false, deactivate config group A. And if clicked outside of Rainmeter, it returns no variable, deactivating everything except the primary bar.

It might just be crazy enough to work. 🤔
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: OnUnfocusGroup

Post by Yincognito »

Cariboudjan wrote:
April 18th, 2020, 1:48 pm
So Config 1 and 2 both contain identical variable A. When 1 or 2 are focused, send variable A to all skins. Then when unfocused, check if newly focused window also contains A. If true, do nothing. If false, deactivate config group A. And if clicked outside of Rainmeter, it returns no variable, deactivating everything except the primary bar.

It might just be crazy enough to work. 🤔
Yeah, something like that. Basically use this transmitted "A" variable to check if the unfocused skins are from the same group as the focused /clicked one, and deactivate them only if they're not. The only problem I could see with this approach is if somehow the unfocus event in those skins happens before the click or focus one in the other skin - in this (likely, if I think about it) case, the "A" variable will get its proper value only after the unfocus happens. But then, I'm sure things can be tweaked to cancel this possible scenario, for example by sending the variable (or variables) from the unfocused skins to the focused one and make the comparison and deactivation from the latter one.

In any case, this should work. It depends on the order in which these events happen, but as I said above, the solution is basically to reverse the direction in which the variable(s) "travel" between skins.

P.S. Best thing that you can do is try this on a small, simplified scale - just with the 3 skin scenario you used in your initial post. No need to do anything else in the skins, just put a dummy meter in each one and test this process. It should be simple enough to try it, but if you can't for some reason, I can do it for you. Or, as I said, wait for the devs to add the requested feature. Even if you don't wait for them and make this attempt, you have nothing to lose, only to learn and probably succeed as well... ;-)

P.S.S. Obviously, don't forget about adding DynamicVariables=1 where needed (or everywhere, for that matter). You wouldn't want forgetting about this little detail to hinder your test.
User avatar
Cariboudjan
Posts: 89
Joined: May 12th, 2019, 8:55 am

Re: OnUnfocusGroup

Post by Cariboudjan »

No. It wouldn't work. It wouldn't be able to know that a skin or window outside of that group has been clicked and perform the appropriate action. It would be able to know if skins inside of that group are the same, but as soon as the Windows Taskbar or Notepad++ is clicked, there would be no way for any skin to process that.

If the unfocusaction only sends "A", and it relies on the focusaction of the other skin to process if it belongs to the same group, this would be useless when clicking outside of any group entirely since there is no focusaction outside of Rainmeter. Only unfocusactions which, as I said, are useless on their own.

I mean maybe? If I use a separate config, a String Measure, an IfMatch, and IsFullscreen plugin? Maybe? I guess it might work? I'm doing this on loose-leaf right now.
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: OnUnfocusGroup

Post by Yincognito »

Cariboudjan wrote:
April 19th, 2020, 6:04 am
No. It wouldn't work. It wouldn't be able to know that a skin or window outside of that group has been clicked and perform the appropriate action. It would be able to know if skins inside of that group are the same, but as soon as the Windows Taskbar or Notepad++ is clicked, there would be no way for any skin to process that.

If the unfocusaction only sends "A", and it relies on the focusaction of the other skin to process if it belongs to the same group, this would be useless when clicking outside of any group entirely since there is no focusaction outside of Rainmeter. Only unfocusactions which, as I said, are useless on their own.

I mean maybe? If I use a separate config, a String Measure, an IfMatch, and IsFullscreen plugin? Maybe? I guess it might work? I'm doing this on loose-leaf right now.
So, you're saying that this will work inside Rainmeter, but it won't when clicked outside of it? Hm...I somehow doubt it won't work when clicked outside Rainmeter, since despite onfocusactions not being available outside Rainmeter, the unfocusactions of all the skins still are (so in theory, there is a way of detecting the focus outside Rainmeter, albeit not through itself, but indirectly through the unfocus of every Rainmeter skin). Let me see what I can do - there has been too much theory in these posts and not enough practice, and the best way of seeing if this approach works is to actually try it.

Also, let's just leave IsFullScreen out of this for a moment. I know it's part of your process / scenario, but it's better to approach this in small steps: first see if my idea works, and only then check how IsFullScreen can be included in the process with minimal (or zero) negative impact.
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: OnUnfocusGroup

Post by Yincognito »

Cariboudjan wrote:
April 19th, 2020, 6:04 am
No. It wouldn't work. It wouldn't be able to know that a skin or window outside of that group has been clicked and perform the appropriate action. It would be able to know if skins inside of that group are the same, but as soon as the Windows Taskbar or Notepad++ is clicked, there would be no way for any skin to process that.

If the unfocusaction only sends "A", and it relies on the focusaction of the other skin to process if it belongs to the same group, this would be useless when clicking outside of any group entirely since there is no focusaction outside of Rainmeter. Only unfocusactions which, as I said, are useless on their own.

I mean maybe? If I use a separate config, a String Measure, an IfMatch, and IsFullscreen plugin? Maybe? I guess it might work? I'm doing this on loose-leaf right now.
Check the attached "skin" (or rather "skin collection") - I made it based on your scenario from the first post. The "Config" skin is there just to ease reloading "Config1" to "Config6" for further tests ("Config1" to "Config2" = 1st group; "Config3" = 2nd group; "Config4" to "Config6" = 3rd group); you load them by clicking on "Config", and then play with them and see how they behave. When, due to the nature of the tests, no skin from "Config1" to "Config6" will be loaded, you can load them all again by clicking on "Config". There is a small glitch when you click too fast on "Config" after the other skins have been deactivated, but I won't bother checking the source of the issue, since it doesn't really affect how "Config1" to "Config6" (i.e. the actual skins you want to work with) behave. Plus, I'm sure it's trivial to fix the glitch anyway.

I guess you know enough Rainmeter code to understand what's going on and how it all works, but if you still don't quite get something, feel free to ask. Hopefully, it's what you need - it deactivates the previously focused group on unfocus, and all the groups if clicked outside them, using an adjustable !Delay bang to give the focus event actions time to "catch up" with the unfocus event ones.
Test_1.0.0.rmskin
P.S. There may be some "leftovers" from the previous attempts in the code (like logging variables' values, that kind of stuff). You can, of course, remove them, or further improve the code.
You do not have the required permissions to view the files attached to this post.
User avatar
Cariboudjan
Posts: 89
Joined: May 12th, 2019, 8:55 am

Re: OnUnfocusGroup

Post by Cariboudjan »

May have gotten it. I modified your skin a bit to fix a few bugs. I'll post it once I'm done.

Well, there's this bug: Won't deactivate the group if the submenus are opened unless clicked first. Hence why UnfocusActions are useless unless the skin has focus first, which it doesn't if the submenus are opened without being clicked on.
GIF 4-19-2020 11-01-28 PM.gif
So I added a little variable to monitor whether the "Main Menu" config has focus. (!SetVariable 1 when focused, 0 when unfocused). Works great.
GIF 4-20-2020 2-39-24 AM.gif
Then this happened. Not sure if it's a Rainmeter thing or a Windows thing, but if the desktop has focus (By clicking on the Show Desktop button), and then the "Main Menu" is clicked on, it will give focus immediately to the newly opened "Submenu 1" config, which causes the menus to immediately deactivate. May have discovered a new bug. Interestingly I tested this with the November version of the Rainmeter beta and the problem doesn't occur (It just causes different kinds of bugs). Not sure if this is a consequence of the recent change to LeftMouseDownAction...

I had to take a video of it with my phone because opening any other window Such as Gifcam "fixes" it.



Here is the rmskin. I don't think I'm going to continue with this method. It causes way too many inconsistencies. I made a method using IsFullscreen, 2 variables, and single string measure that seems to work 101% of the time.

:(
Test2_0.rmskin
You do not have the required permissions to view the files attached to this post.