FelixKratz / SketchyBar

A highly customizable macOS status bar replacement
https://felixkratz.github.io/SketchyBar/
GNU General Public License v3.0
5.62k stars 86 forks source link

Weird behaviour with mouse detection #368

Closed zcag closed 1 year ago

zcag commented 1 year ago

Problem

Item receives 'mouse.exited' before the mouse actually leaves the bar completely. This happens in the last 4 pixels of the bar. Causing the popup to close before my mouse gets to it.

Item is subscribed to events mouse.entered mouse.exited mouse.exited.global and sets popup.drawing on for $SENDER = *entered and off otherwise.

I have the bar with height=64 and y_offset=0. Any more and it spills under my notch, and less gets under, so it's the exact height. topmost is off, which is a part of the problem. Also yabai is turned off to make sure it's not messing with anything. Don't need it's external_bar option as i have a notch on my screen and it pushes windows away already.

Demonstration https://user-images.githubusercontent.com/3230608/235687708-d8e23299-1504-4b10-80a9-802bc1ee9941.mp4

With the item background.y_offset=4 background.color=0xffff0000 to show the exact location of the problem, and to prove that mouse is in fact still located in the bar:

Demonstration https://user-images.githubusercontent.com/3230608/235690144-81f85a23-46af-46bd-a5f2-1753f76f61cb.mp4

This happens with windows that have the usual macos style borders, so kitty with hide_window_decorations yes don't have this for example.

My shitty workaround was setting external_bar of yabai to something bigger to have a gap between sketchybar and windows, then painting the top of my wallpaper to match the bar color so the gap is not noticable.

Setting y_offset for popups so they sit higher don't work either. When mouse goes over from item to popup, it receives mouse.exited and mouse.entered briefly, causing this glitch:

Glitch https://user-images.githubusercontent.com/3230608/235691134-576bb162-5679-4cb5-b480-593d21826f5a.mp4

I think this is caused by macos giving some leeway for mouse operations so it reports the mouse event earlier then usual, in the second vid (second 6) you can see that i can actually click the finder window when the mouse is in the last few pixels on the bar..

Possible workarounds

1) Use topmost=on. This comes with the annoying problem of not being able to reach the original menu bar to use the app menu items. If we could have a way to draw over everything except menu bar it would be golden. Or just have an event that we can subscribe to so we hide the bar on menu bar show (best option imho).

2) Don't report mouse.exited when the mouse exited to enter same item's popup and prevent the loop of receiving exited and entered continiously 3) Maybe have $INFO for mouse.exited to report the newly entered item, or just bar if mouse was exited to empty space. So we can decide not to close the popup. edit: I was assuming a behaviour that doesn't exist, so these makes no sense now..

4) Ability to use background rect (or some other value) for triggering mouse events, so we can make the trigger area higher or lower at will, so we can make the trigger shorter (ex. 60px trigger area from top with a 64px bar)

For option 1 i think we need to have it anyways regardless of this specific issue. I don't understand the purpose of it when you have the bar at the top and your menu bar on auto-hide. So if it's easy enough to implement it could be nice to have it. Option 2 also seems like a bug to be fixed, since in sketchybar popup and it's item considered to be the same items (in context of events), so it seems like it shouldn't fire mouse.exited.

Let me know if these are not in your scope at the moment, and i can try to have a go at fixing it. Coming from high level languages (or just being incompetent lol) source of this repo is very alien to me every time i try to inspect some stuff, but it could be a good chance to learn.

Edit:

Minimal config ```bash args=( --bar height=64 # should be set to exact height of the notch color=0xff0000ff --add item bar_item left --add item popup_item popup.bar_item --subscribe bar_item mouse.entered mouse.exited.global mouse.exited --set popup_item width=300 --set bar_item width=300 background.color=0xffff0000 popup.background.color=0xff000000 popup.height=100 ) sketchybar ${args[@]} \ script='sketchybar --set bar_item popup.drawing=$([[ $SENDER = *entered ]] && echo on || echo off)' ```
zcag commented 1 year ago

About the issue where the popup flickering when it's over the bar (with popup.y_offset=-x): looks like in https://github.com/FelixKratz/SketchyBar/blob/master/src/event.c#LL266C12-L266C27 handler checks if the mouse coords are on the bar (it is, but also on popup), and assumes the mouse left the item (since wid of the event doesn't match the item, because of popup). if that makes sense.

Changing the line to

|| (!bar_manager_get_item_by_point(&g_bar_manager, point, adid) && bar_manager_get_bar_by_point(&g_bar_manager, point))

or

 || (!bar_manager_get_popup_by_point(&g_bar_manager, point) && bar_manager_get_bar_by_point(&g_bar_manager, point))

fixes the issue, but now global.exit fires late for some reason, when i leave the popup with my mouse to outside, it only goes away after a second or so.

Also, found another workaround for now, setting topmost=on and using the app menu bar on context menufeature of BTT. Bit overkill to get the app just for this feature but yeah..

FelixKratz commented 1 year ago

I think the popup flickering problem is fixed on current master.

The other problem is connected to the way window events are handled internally on macOS, as you have already pointed out: The windows with a "regular" decoration have a slightly larger "hitbox" than their visual appearance (and their snapping bounds). The main problem here is that sketchybar is ordered below all windows and thus also ordered last in the event responder chain. The only viable solution for this is to order sketchybar above all windows instead. Currently topmost is the only way to change the window level. I agree, that there should probably be a way to order sketchybar between the windows and the original menu bar (which is technically very easy to do).

One way to achieve this would be to add a new key to the topmost property, e.g. topmost=window, would only make it the topmost window, but not draw over the original bar.

zcag commented 1 year ago

I think the popup flickering problem is fixed on current master.

so fast, just tried and it works, thanks a lot! ❤️

Currently topmost is the only way to change the window level. I agree, that there should probably be a way to order sketchybar between the windows and the original menu bar (which is technically very easy to do).

That's very good to hear, and it'll also fix notifications going behind the bar too

FelixKratz commented 1 year ago

I have added the new option to the bar domain, now you can have --bar topmost=window.

zcag commented 1 year ago

Very cool, I've been looking to have this for some time. Thanks a lot!