Closed Asthestarsfalll closed 5 months ago
Hm.... do you have a concrete example ?
Maybe showing the output of hyprctl -j clients
at the different stages ?
I recently added a feature to add any window to an existing scratchpad, but there are no options at the moment to have an "empty" scratchpad and it's hard for me to imagine how it would work...
I see something like:
but I'm not sure it matches what you have in mind...
For example, we use a chat app called QQ. There will be a login interface: After I login, it will destory and a new window will be created:
I see something like:
- open scratchpad with no command (still recorded but does nothing)
- "attach" the new window => detects that the scratchpad was empty & make this window the main app of the scratchpad
but I'm not sure it matches what you have in mind...
Yes, it is.
can you send either the full information or filter on the concerned client ? class & title were not what I was looking for... I understood there are two different windows, I would like to check other properties, including pid.
Sure.
Thank you! I can try something like this, tell me if you feel that it would work (You may need to test an experimental branch of pyprland to provide feedback if/when I implement it):
New option like "multi_window=true" would change the behavior as follows:
Which leads me to one question: isn't pyprland trying to start "QQ" multiple times and fail at it with the current implementation ? (once the login window has been dismissed)
New option like "multi_window=true" would change the behavior as follows:
When a scratchpad window has been closed and the scratchpad is requested to be shown
- check if there is another window with the same PID, waiting for it ~1s
- if found, use this as the scratchpad window
- else proceed as of today: start the program again
It looks good to me.
Which leads me to one question: isn't pyprland trying to start "QQ" multiple times and fail at it with the current implementation ? (once the login window has been dismissed)
No, it will be silent. But I remeber in the previous version of pyprland it would raise error that cannot find the target window.
May I also ask for the pypr's logs (launch pypr with --debug /tmp/pypr.log) when you call the scratchpad again after the login window has been closed ? (or include everything and I'll try to figure it out)
It seems that the dispatch is now functioning properly, but QQ is still not being displayed. At the lower version (I upgraded both pyprland and QQ, so I don't know what's the reason), pyprland will directly give a error message about cannot find the window.
scratchpads - run_toggle('qq',) // command.py:189
scratchpads - visibility_check: ('1', 'eDP-1') == ('1', 'eDP-1') // __init__.py:423
scratchpads - qq is visible = True (but True) // __init__.py:443
scratchpads - Hiding qq // __init__.py:683
scratchpads - dispatch movewindowpixel -326 0,address:0x55efce183cb0 // ipc.py:131
scratchpads - dispatch movetoworkspacesilent special:scratch_qq,address:0x55efce183cb0 // ipc.py:131
scratchpads - run_toggle('qq',) // command.py:189
scratchpads - visibility_check: ('1', 'eDP-1') == ('1', 'eDP-1') // __init__.py:423
scratchpads - qq is visible = False (but False) // __init__.py:443
scratchpads - Showing qq // __init__.py:533
scratchpads - clients // ipc.py:89
scratchpads - monitors // ipc.py:89
scratchpads - dispatch ['moveworkspacetomonitor special:scratch_qq eDP-1', 'movetoworkspacesilent 1,address:0x55efce183cb0', 'alterzorder top,address:0x55efce183cb0'] // ipc.py:131
scratchpads - dispatch resizewindowpixel exact 326 464,address:0x55efce183cb0 // ipc.py:131
scratchpads - clients // ipc.py:89
scratchpads - dispatch movewindowpixel exact 806 531,address:0x55efce183cb0 // ipc.py:131
scratchpads - dispatch focuswindow address:0x55efce183cb0 // ipc.py:131
scratchpads - run_toggle('qq',) // command.py:189
scratchpads - visibility_check: ('1', 'eDP-1') == ('1', 'eDP-1') // __init__.py:423
scratchpads - qq is visible = True (but True) // __init__.py:443
scratchpads - Hiding qq // __init__.py:683
scratchpads - dispatch movewindowpixel 0 0,address:0x55efce183cb0 // ipc.py:131
scratchpads - dispatch movetoworkspacesilent special:scratch_qq,address:0x55efce183cb0 // ipc.py:131
scratchpads - run_toggle('qq',) // command.py:189
scratchpads - visibility_check: ('1', 'eDP-1') == ('1', 'eDP-1') // __init__.py:423
scratchpads - qq is visible = False (but False) // __init__.py:443
scratchpads - Showing qq // __init__.py:533
scratchpads - clients // ipc.py:89
scratchpads - monitors // ipc.py:89
scratchpads - dispatch ['moveworkspacetomonitor special:scratch_qq eDP-1', 'movetoworkspacesilent 1,address:0x55efce183cb0', 'alterzorder top,address:0x55efce183cb0'] // ipc.py:131
scratchpads - dispatch resizewindowpixel exact 326 464,address:0x55efce183cb0 // ipc.py:131
scratchpads - clients // ipc.py:89
scratchpads - dispatch movewindowpixel exact 806 531,address:0x55efce183cb0 // ipc.py:131
scratchpads - dispatch focuswindow address:0x55efce183cb0 // ipc.py:131
scratchpads - run_toggle('qq',) // command.py:189
scratchpads - visibility_check: ('1', 'eDP-1') == ('1', 'eDP-1') // __init__.py:423
scratchpads - qq is visible = True (but True) // __init__.py:443
scratchpads - Hiding qq // __init__.py:683
scratchpads - dispatch movewindowpixel 0 0,address:0x55efce183cb0 // ipc.py:131
scratchpads - dispatch movetoworkspacesilent special:scratch_qq,address:0x55efce183cb0 // ipc.py:131
pyprland - event_activewindowv2('55efce169a90',) // command.py:189
pyprland - active_window = 0x55efce169a90 // pyprland.py:44
scratchpads - event_activewindowv2('55efce169a90',) // command.py:189
layout_center - event_activewindowv2('55efce169a90',) // command.py:189
pyprland - event_activewindowv2('55efce169a90',) // command.py:189
pyprland - active_window = 0x55efce169a90 // pyprland.py:44
scratchpads - event_activewindowv2('55efce169a90',) // command.py:189
layout_center - event_activewindowv2('55efce169a90',) // command.py:189
Ok, I guess this is because the process is still running, so pyprland isn't restarting it. There is at the moment no additional check regarding the client window, it's assumed to not have changed...
If I understand it well, in your scenario there is always at least one window we can "link", do you confirm ?
I'll try to implement something, would be great if you can test when I push it on git...
If I understand it well, in your scenario there is always at least one window we can "link", do you confirm ?
yes!
I'll try to implement something, would be great if you can test when I push it on git...
You can push code to a test branch, and I will test it once I have time!
Ok, I believe we didn't get something in your scenario, after a code review + writing a test app to simulate your case, it should raise an error + show a notification when you try to show again.
It means the original window is still available... so I'll ask you a more detailed info, please provide pypr's log for the full session (after a fresh start of the window manager + pypr) + the result of hyprctl -j clients | jq '.[] | select(.class=="QQ")'
and execute the following:
One more thing, having a binding such as:
bind = $mainMod, S, togglefloating,
when you "show" the client, but it's not visible, can you try triggering this to see if it appears in the current workspace as a tiled window ?
I believe it can be a problem with the coordinates... but I need a full picture of a single scenario to better understand what's going on :)
Are you using preserve_aspect ? Can you provide the config for the QQ scratchpad ? :)
One more thing, having a binding such as:
bind = $mainMod, S, togglefloating,
when you "show" the client, but it's not visible, can you try triggering this to see if it appears in the current workspace as a tiled window ?
The login window cannot be set to tiled
At the lower version (I upgraded both pyprland and QQ, so I don't know what's the reason), pyprland will directly give a error message about cannot find the window.
I reproduce this ! This will happen when I enable multi monitors. THe traceback is:
ERROR:scratch:client_info of 5588bc402d30 must be a dict: None
This could be a bug in Pyprland, if you think so, report on https://github.com/fdev31/pyprland/issues
Not a dict: None
Traceback (most recent call last):
File "/usr/lib/python3.11/site-packages/pyprland/command.py", line 195, in _run_plugin_handler
await getattr(plugin, full_name)(*params)
File "/usr/lib/python3.11/site-packages/pyprland/plugins/scratchpads/__init__.py", line 450, in run_toggle
await asyncio.gather(*(asyncio.create_task(t()) for t in tasks))
File "/usr/lib/python3.11/site-packages/pyprland/plugins/scratchpads/__init__.py", line 563, in run_show
await self._show_transition(scratch, monitor, was_alive)
File "/usr/lib/python3.11/site-packages/pyprland/plugins/scratchpads/__init__.py", line 606, in _show_transition
await scratch.updateClientInfo() # update position, size & workspace information (workspace properties have been created)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/pyprland/plugins/scratchpads/objects.py", line 118, in updateClientInfo
raise AssertionError(f"Not a dict: {client_info}")
AssertionError: Not a dict: None
Are you using preserve_aspect ? Can you provide the config for the QQ scratchpad ? :)
[scratchpads.qq] animation = "fromLeft" command = "linuxqq" position = "42% 30%" class = "QQ" size = "17% 43%" margin = 0 lazy = true
Ok, I believe we didn't get something in your scenario, after a code review + writing a test app to simulate your case, it should raise an error + show a notification when you try to show again.
It means the original window is still available... so I'll ask you a more detailed info, please provide pypr's log for the full session (after a fresh start of the window manager + pypr) + the result of
hyprctl -j clients | jq '.[] | select(.class=="QQ")'
and execute the following:
- toggle QQ scratchpad => should show
- login => should disappear
- toggle QQ scratchpad => should "break"
- repeat last toggle operation, just in case we capture something interesting...
error.log
normal.log
the result of hyprctl -j clients | jq '.[] | select(.class=="QQ")
:
Before login:
after login:
Then it will not change when I pypr toggle qq.
And I also reproduce the error in single monitor. I think this because there is a little gap between the login window destory and new window create. So if I toggle pypr during the period, It will raise error.
What I'm very surprised with, is that if there was no window with the "correct" address, it should ALSO throw this error... there is current absolutely no code (that I know!) which handles that kind of unexpected case, and I tested it yesterday on an app.
It makes me doubt this will be detected on your system... I need to know if the client address of the first window is still available later (which is what would make sense when you don't get an error). To achieve this, just note the address of the login / first client window:
Then, later on, type something like:
hyprctl -j clients | jq '.[] | select(.address=="0xXXXX")'
Replacing "0xXXX..." with the address* of the initial client window....
@fdev31, Hi, I don't know is it still avilable, It will quit when I stop the whole process of QQ.
Ok, I think it starts to make sense, QQ main window stays, but get a pid = -1 and no title or class anymore... hence when the scratchpad thinks the window is still fine. Do you confirm this understanding ?
It almost sounds like a bug in QQ.
I can try to find a solution for that too but it looks very "qq" specific...
Ok, I think it starts to make sense, QQ main window stays, but get a pid = -1 and no title or class anymore... hence when the scratchpad thinks the window is still fine. Do you confirm this understanding ?
Yes
I can try to find a solution for that too but it looks very "qq" specific...
So for more general, can we implement a method to catch an existing window? So that I just need to login, then add it to scratch pad.
Yes, I could automatically attach new windows to the same scratch, the new windows seemed to preserve the pid. The only challenge I see here is detecting the "dead" client window, having a trigger for it which isn't using additional API calls to not slow down anything.
having a pid==-1 seems to be a decent test, but this may be detected with a delay... I'll do some experiments over the weekend when I have time.
Oh, I mean just manully toggle pypr to add a window to scratchpad like the title of this issue. Automatically detecting the dead window seems not cost-effective for its narrow scenario.
Oh so you can find your way with the current attach command, if that works "okay" it's good :) I may still try to push some code with tricks if they are not impacting the overall complexity too much... in short if it fits well in the code I'll make experiments that you can test to see if it improves the user experience... I'll update this ticket accordingly to let you know if I abandon the idea or if I come with something in the future...
Thank you for your efforts!
I pushed some experimental option which sounds generic and may address your scenario, try setting multi = true
on this scratchpad using the latest git version, hoping it helps!
Hi, It almost works, but it seems there should be a full address:
After I change this, the QQ window can be dispatched between workspace:
But the position of window are not handled correctly.
But it works well for my typora, which will pop a menu and not handle properly in the pervious version:
I don't know why the position isn't changed in case of QQ... I guess this is because the original process & window are still here so every other are only "attached", but they still should slide in some way...
Thank you for reporting the address issue, I just pushed the fix.
We can try to improve it even further but it may lead to too much specific code & complexity... are you satisfied with the current version or do you think there is still something that can be done to try to improve the QQ scenarios?
We can try starting again generating full logs & dumps with the current version on QQ and try to figure what is still wrong with it. The position should be at least a bit changed when you toggle it.
We can try to improve it even further but it may lead to too much specific code & complexity... are you satisfied with the current version or do you think there is still something that can be done to try to improve the QQ scenarios?
I think simple is better. So I just write a script to do this:
addr=$(hyprctl -j clients | jq '.[] | select(.class=="'$1'") | .["address"]' | sed 's/"//g')
hyprctl dispatch focuswindow address:"$addr"
hyprctl dispatch centerwindow
Once I move it into the workspace, pypr will work well with QQ. But it seems there's no animation of multi window. And I think multi should be disabled by default for its search costs
You might be interested in https://github.com/hyprland-community/pyprland/wiki/fetch_client_menu - I think it can also fit the requirement... if not, I'm happy to improve it by supporting the "centerwindow" call for instance... (I could use this if I detect a floating window).
About the search cost, I managed to not do additional IPC call for it if I recall, so it should not be noticeable... My main worry is that maybe for some scenarios this is not a good thing to have, but I imagine it's more useful than it's annoying...
You got the Typora app working out of the box, which is good, not everybody will dig the advanced options to fix such app...
You might be interested in https://github.com/hyprland-community/pyprland/wiki/fetch_client_menu - I think it can also fit the requirement... if not, I'm happy to improve it by supporting the "centerwindow" call for instance... (I could use this if I detect a floating window).
It seems fetch_client_menu do not works well with scrtachpads. The chosen client will disappear from the menu, and no window will show. But I am busy with my ungraduate design and paper. So I will dig this functionality after them done.
About the search cost, I managed to not do additional IPC call for it if I recall, so it should not be noticeable... My main worry is that maybe for some scenarios this is not a good thing to have, but I imagine it's more useful than it's annoying...
You got the Typora app working out of the box, which is good, not everybody will dig the advanced options to fix such app...
I agree with you. It's a great exprience to use out of the box.
Hi, I just update hyprland to 0.39.0. allow_special_worspace
works as expect. And need to set smart_focus
to False, I think this should be written in wiki.
And the animation of special workspace is abnormal. It looks like the special workspace are closed and reopened. This maybe a bug of Hyprland
What do you experience wrong with smart focus when you enable special workspaces?
EDIT: I also experienced the flickering, I don't think it's in pyprland, I guess this is because this feature is a bit fragile since scratchpads are heavily relying on special workspaces and from experience they are a bit less stable than standard workspaces.
Le dim. 28 avr. 2024 à 19:20, Asthestarsfalll @.***> a écrit :
Hi, I just update hyprland to 0.39.0. allow_special_worspace works as expect. And need to set smart_focus to False, I think this should be written in wiki.
And the animation of special workspace is abnormal. It looks like the special workspace are closed and reopened. This maybe a bug of Hyprland
— Reply to this email directly, view it on GitHub https://github.com/hyprland-community/pyprland/issues/87#issuecomment-2081561139, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAB2IHWR5QCRY6HQ6BZSS2DY7UVT7AVCNFSM6AAAAABGU2KK6SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAOBRGU3DCMJTHE . You are receiving this because you were mentioned.Message ID: @.***>
What do you experience wrong with smart focus when you enable special workspaces?
Just cannot keep the special workspace open. I don't know what will smart_focus do.
EDIT: I also experienced the flickering, I don't think it's in pyprland, I guess this is because this feature is a bit fragile since scratchpads are heavily relying on special workspaces and from experience they are a bit less stable than standard workspaces.
Yes, the focuswindow still does not work well with sepcial workspace.
Just cannot keep the special workspace open. I don't know what will smart_focus do.
You mean, when you hide a scratchpad when a special workspace was open, then it hides the special workspace at the same time ?
If so, this is something I can try to improve, for instance disabling smart focus in that case...
You mean, when you hide a scratchpad when a special workspace was open, then it hides the special workspace at the same time ?
yes. And I want to know what is the behavior of smart focus. There'is no document about this.
So, this is because it's a bit complicated and subject to changes/refinements... the explanation is rather long to fit in the wiki under this option, and I consider this a topic to be worked on, not optimal at the moment with some corner cases not well handled as you noticed.
First, it's useful only for multi-monitor scenarios, so I could change the defaults according to that.
The problem with monitors is the following:
So the scratchpads plugin is constantly keeping track of the window which was focused before the scratchpad was first displayed or refocused. When you hide the scratchpad, after a tiny delay, it will force the focus back on this tracked client window.
There are few cases where this is auto-disabled, but it's quite heuristic.
I wanted to experiment with different solutions, but in my tests using the focused monitor or workspace (instead of focused client) didn't work well while it sounded optimal.
Hope that clarifies!
I'm really open for suggestions & experiments here, I was even considering opening for multiple heuristics (say changing smart_focus from a boolean to a string with the name of the "smart" heuristic ;P)
I don't see the issue with special workspaces, would you mind sharing the relevant configuration items + a video of the problem so I better understand how it's produced?
Please try the last push, keeping the smart focus on :)
EDIT: it wasn't good enough, I reverted, we need to focus specific client else the "recovered" focus is random :(
I tested and if there is a focused client window in the special workspace it works as expected here, not for you ?
I don't see the issue with special workspaces, would you mind sharing the relevant configuration items + a video of the problem so I better understand how it's produced?
Sorry, I have no proper app to record my screen due to the dependencies of hyprland-git. xdg-desktop-portal-hyprland-git
cannot work.
In fact, I use single monitor at most time. When I enable smart_focus, then I show scratchpads in a special workspace, nothing abnormal. But when hiding the scratchpads, it will "close" the special workspace, and lost the focus.
I believe this is a bug of Hyprland. If you are using verison of 0.39.0, you may reproduce it by the following procedure:
hyprctl dispatch focuswindow address:......
.Then you will see the special workspace "close", and lost your focus. But in fact it just hide, if you toggle this speical workspace again, it will truly close.
It may be fixed by this commit. But I cannot verify it util the new version publish.
Then you will see the special workspace "close", and lost your focus. But in fact it just hide, if you toggle this speical workspace again, it will truly close.
Looks like an issue with your Hyprland version, I can't reproduce this problem... using v0.39.1
Ok, I worked around some bug and hit the same behavior as you over special workspaces and can now explain:
.1 Hyprland sends an invalid address when showing a scratchpad, which was masking the other bug .2 Hyprland blinks when we show the scratchpad for no obvious reason, as a side effect, it will send an event telling that some window BELOW the special workspace is focused, which is messing up the focus tracking
As a workaround, once a scratchpad is displayed over a special workspace, focus at least once/shortly another window.
The latest git version may improve things a bit.
The latest git version may improve things a bit.
I use the latest commit, but it can not detect pypr daemon.
And it's running? If yes try killing and restarting
Did you figure your problem? Check #98, it might be of interest for you.
Now smart focus can work well with scratchpads in speical workspace!
Some applications have a launch or login window and then it will invocate a new runing window and destroy itself. This will cause pyprland to miss the new window. So can we add a existed window to a scratchpad? The config can be
Use empty command to mark the scratchpad will take any exited windows.
For the first time, the pyprland toggle tmp will add the avtivate window to scratchpad tmp, and hide it. Then the behavior will be as same as normal command util the window are killed.