It is currently September 8th, 2024, 2:56 am

MouseOver and MouseLeave

Report bugs with the Rainmeter application and suggest features.
User avatar
jsmorley
Developer
Posts: 22716
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

MouseOver and MouseLeave

Post by jsmorley »

I have been working with a skin which replicates the functionality of ObjectDock/RocketDock and have run into an issue which I believe is a bug in the working of the MouseOverAction and MouseLeaveAction event statements and the !RainmeterZpos statement.

After much testing, I make the following observations:

If I use MouseOverAction and MouseLeaveAction to "pop" a skin to the front of other non-Rainmeter windows on MouseOver and back to the bottom on MouseLeave, it works great UNLESS you click with either the left or right mouse buttons anywhere on the skin OR on the Windows desktop. Then the skin is set to "bottom" ZPos on the next MouseLeave and completely ignores MouseOver from then on until the skin is refreshed, and it MUST be refreshed via the context menu for rainmeter.exe - (right click, highlight the skin in the list, then select "Refresh Skin" or use "Refresh All" from the main context menu) Until I do this it goes to the bottom and stays there...

Here is the relevant code:

Code: Select all

[Rainmeter]
Author=Jeffrey Morley
Update=1000
MouseOverAction=!execute [!RainmeterZPos 2]
MouseLeaveAction=!execute [!RainmeterZPos -1]
So, you may well ask, why don't I change the code to this:

Code: Select all

[Rainmeter]
Author=Jeffrey Morley
Update=1000
MouseOverAction=!execute [!RainmeterZPos 2]
MouseLeaveAction=!execute [!RainmeterZPos 0]
So that the skin's ZPos is set to "Normal" when you move the mouse off? This sorta works, but the skin stays in front until you click on the "titlebar" of another window. It isn't enough to click anywhere else on another windows, the rainmeter skin stays on top until you give the other window "focus" by clicking on the titlebar. Not the effect I want. I want the skin to pop forward when moused-over and return to the back when the mouse leaves. Plus it doesn't fix the problem. Instead of being stuck at the back after a mouse click, it now is stuck in "normal" and won't pop forward on MouseOver.

So, how about this?

Code: Select all

[Rainmeter]
Author=Jeffrey Morley
Update=1000
MouseOverAction=!execute [!RainmeterZPos 2]
MouseLeaveAction=!execute [!RainmeterZPos -1][!RainmeterRefresh]
So the skin refreshes every time you move the mouse off? This should do the same thing as using the context menu for rainmeter.exe to refresh the skin. No, it doesn't. There is some difference is what is sent to Rainmeter via the context menu and the bang in a skin. The skin refreshes, but continues to ignore MouseOver events until it is refreshed from the context menu.

Now here is an interesting twist:

Code: Select all

[Rainmeter]
Author=Jeffrey Morley
Update=1000
MouseOverAction=!execute [!RainmeterZPos 2]
MouseLeaveAction=!execute [!RainmeterZPos -1][!RainmeterRefresh *]
This DOES work. Note the difference is [!RainmeterRefresh *] as opposed to [!RainmeterRefresh] which causes Rainmeter to refresh ALL running skins. When I use this command it works exactly as I want, EXCEPT that well... all the skins are refreshed. I don't even really want to have to refresh the "dock" skin on every MouseLeave, but can live with that. I certainly don't want all running skins to refresh every time my mouse leaves the "dock" as that causes skins like weather and time and gmail checkers and everything else to spike the CPU to 100% for a second, and causes distracting screen activity for no reason.

I was hoping that using [!RainmeterRefresh skinname] would work, even though in theory it is effectively the same as [!RainmeterRefresh], but specifying the skin name or defaulting to "current skin" seems to behave the same.

One question... Is anyone sure of the format for the [!RainmeterRefresh skinname] command? What exactly should be the format of "skinname" is it just the name of the skin (in this case it's "JMDock")

[!RainmeterRefresh JMDock]

or

[!RainmeterRefresh JMDock.ini]

or

[!RainmeterRefresh "C:\Program Files\Rainmeter\Skins\JMDock\JMDock.ini"]


or

[!RainmeterRefresh Skins\JMDock\JMDock.ini]

or some variant thereof? I want to be sure I am executing the refresh command correctly before I give up on it.

Here is what my gut is telling me is the root of the problem. it has to do with window "focus". In other words, which window element Windows sees as being "currently active". If you give "focus" to a skin (like JMDock) by clicking on it, then Windows seems to ignore the ZPos commands from Rainmeter until you give the "focus" to some other window. In effect Windows thinks the skin is already "on top" because it has focus, so even though Rainmeter puts it to the bottom, Windows thinks it's still on top and ignores requests to move it. Once you give the "focus" to some other window (by clicking on the titlebar, then Windows sees the new window as being "active" and thus presumably on top, and the Rainmeter skin goes back to behaving as expected.

Not sure how to fix this, but one approach would be a bang which could transfer the Windows "focus" to another skin or another window or at least tell Windows to "lose focus" on the current skin. In other words, a bang to make a specified window "active" and ensure Windows gets the message...

Code: Select all

[Rainmeter]
Author=Jeffrey Morley
Update=1000
MouseOverAction=!execute [!RainmeterZPos 2]
MouseLeaveAction=!execute [!RainmeterZPos -1][!RainmeterLoseFocus]
or

Code: Select all

[Rainmeter]
Author=Jeffrey Morley
Update=1000
MouseOverAction=!execute [!RainmeterZPos 2]
MouseLeaveAction=!execute [!RainmeterZPos -1][!RainmeterGiveFocus skinname]
User avatar
jsmorley
Developer
Posts: 22716
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: MouseOver and MouseLeave

Post by jsmorley »

Problem with that of course is that Rainmeter.exe creates NO actual window which can be given "focus" with WinAPI calls like "WinActivate("Rainmeter", "")" so it gets strange...
User avatar
jsmorley
Developer
Posts: 22716
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: MouseOver and MouseLeave

Post by jsmorley »

Ok.. Answered my own question about how to use !RainmeterRefresh to refresh just one skin...

It's

MouseLeaveAction=!execute [!RainmeterZPos -1][!RainmeterRefresh JMDock\JMDock]

So it is "relative" directory naming, using "Skins" as the starting point, and then the name of the skin without the ".ini" at the end.

It works to refresh the skin, but still doesn't solve the problem. ONLY [!RainmeterRefresh *] seems to work in this instance... :|
User avatar
jsmorley
Developer
Posts: 22716
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: MouseOver and MouseLeave

Post by jsmorley »

Ok, now you guys will get a chance to shake your head and laugh at me...

I found a work around that fixes the problem for me (although I could never distribute the skin this way)

To recap, when I click on the "dock" skin which is looking for MouseOver and MouseLeave to pop forward and backward on the windows "stack", it stops responding (something hideous to do with Windows "focus" and the fact that Rainmeter skins are not really "windows") to MouseOver until I

1) Refresh the skin using the context menu either of rainmeter.exe or the skin
or
2) Left-click on a DIFFERENT Rainmeter skin on my desktop

For some reason either of these will reset things to work correctly again.

Ok, So number one is just out of the question, as it adds so much effort to using the dock that it isn't worth it. Number 2 isn't terrible, but I don't want to remember to do that every time I empty the recycle bin on the dock or use the dock to open a folder or application. Just so unintuitive and painful that it also makes the dock unusable.

Now the work-around... Don't laugh!

I used AutoIt3 to create a little Windows executable which does one thing. Gets the current cursor position, single-clicks on the X,Y coordinates of one of my other skins, and then returns the mouse to the current position. Fortunately, the WinAPI for controlling the mouse has a setting to move the mouse "instantly", so you never even see it happen.

Here is the entire AutoIt3 script I compiled into "MouseClick.exe":

Code: Select all

$pos = MouseGetPos()
MouseClick("left", 15, 9, 1, 0)
MouseMove($pos[0], $pos[1], 0)
The "MouseClick" command is MouseClick("WhichMouseButton", XPos, YPos, NumberOfClicks, Speed)

Now I use it in my skin like this:

Code: Select all

MouseLeaveAction=!execute [!RainmeterZPos -1]["C:\Program Files\Rainmeter\Skins\JMDock\MouseClick.exe"]
Voila! Works like a champ, takes pretty much zero CPU, and is completely transparent to me so it doesn't offend my sensibilities... ;-)

AutoIt3 is just a GREAT tool folks. It can be used to create Windows apps as simple or as complex as you want, has a GREAT help facility, a really good "editor" for creating the scripts you compile into .exe files, and is free... It is a fantastic tool for creating "helper" apps for Rainmeter.

http://www.autoitscript.com/autoit3/downloads.shtml

Be sure to get both AutoIt3 and the "Script Editor" just below it. You can just use Notepad+ or UltraEdit or whatever, but the companion script editor has a lot of features which makes it the best way to create AutoIt scripts. (like command completion, context sensitive help etc)

This is a temporary work around for this problem until hopefully someone on the dev staff has time to dig into this issue a bit.
sgtevmckay

Re: MouseOver and MouseLeave

Post by sgtevmckay »

I find nothing to scoff at here.
Great work and innovation.

Can we get you to work something up regarding this app and your findings in the 3rd Party Plugins and Helper Apps?

I would appreciate it.

Thanks
User avatar
davidosomething
Posts: 1
Joined: June 26th, 2010, 5:57 am

Re: MouseOver and MouseLeave

Post by davidosomething »

hey jsmorley, has there been any update on the focus thing besides using the autoit hack?

I want to have a similar behavior for my twitter skin, that on mouseover it gets On Top
and on mouseleave it goes back to desktop/bottom
but the tweets themselves may get clicked on

alternatively, would adding a Leftmousedown skin's z-index to -1 do the trick?
my skin is only using leftmouseup for now