A few friends of mine using Xfce, now trying Fvwm. They are asking why the window is not focused when page is changed, this what Xfce does with ClickToFocus. For example, on page 0 0 Xterm is on top (focused), and Thunar is unfocused. On page 0 1, Firefox is focused, and Zoom and Featherpad are unfocused. The previous focus remains as such when going back and forth.
How does Fvwm remember the focus on each page? Did some search but many links are not working with possible solutions.
I’m not sure I understand your question correctly. I think FVWM has one focus that is shared between all pages by default, and does not remember focus. Are you sure they are not just hovering the window, which makes it focused? There are a few configs that likely implement a function to remember what was focused on which page. Maybe they are using such a config.
If you are asking for how to make it remember focus, I think this might work:
DestroyFunc SwitchPage
AddToFunc SwitchPage
+ I Current InfoStoreAdd lastFocusPage$[page.nx]$[page.ny] $[w.id]
+ I GotoPage $0 $1
+ I Test (EnvIsSet infostore.lastFocusPage$[page.nx]$[page.ny]) \
WindowId $[infostore.lastFocusPage$[page.nx]$[page.ny] Focus
This is a function that takes two parameters. These are the same as GotoPage takes in, and can be found on the manpage.
This function first takes the ID the current focused window, and adds it to a variable for the current page. It then goes to the specified page and checks if there has been set a variable for this page, and if it has focus this window. If you want the window to also be raised you can switch out Focus for Raise in the last line.
For this to work, you will have to call this function whenever you switch pages. If you use key bindings, just put this function instead of GotoPage or Scroll. If you use the edge scroll supported by FVWM, add this function to EdgeLeaveCommand for every direction.
GotoPage is supports going to relative pages with GotoPage 1p 0p for going to the right, while also supporting using absolute page coordinates like GotoPage 1 0.
If this code doesn’t work, please tell me. While I have tested the concepts used in this code, I haven’t tested this specific code.
I am using Fvwm and Xfce. Also combining Fvwm scripts with Xfce, which works well. Didn’t think about this focus difference.
What @amlug means when the window is focused on each page without hovering or pointing with the cursor. This screenshot on Xfce with an enlarged panel/pager shows that the top window is automatically focused when changing the page. This feature would be great to have a script or command that does it.
Not familiar with InfoStoreAdd, I have to check step by step. String $[page.nx]$[page.ny] works fine by adding space and quote: "$[page.nx] $[page.ny]" but cannot read $[w.id].
Testing with two FvwmConsole:
This works fine InfoStoreAdd FWind 0x560000e (id of FvwmConsole 1)
and to focus console 1 WindowId $[infostore.FWind] Focus (run on FvwmConsole 2)
Doesn’t work with $[w.id], something is missing InfoStoreAdd FWind $[w.id] (FvwmConsole 1) WindowId $[infostore.FWind] Focus (FvwmConsole 2)
What rasat says is correct. It requires you to use current to get the the currently focused window. I don’t know why. Maybe it needs to be hovered for it to work without, maybe it is something else entirely, but current must be used for $[w.id] to return anything
Thanks for the next step. This works well between two pages going back and forth. Requires two functions, at startup and another with a key function.
Startup:
Current InfoStoreAdd $[page.nx] $[page.ny]
Key function (alt-g)
DestroyFunc GoFPage
AddToFunc GoFPage
+ I GotoPage $0 $1
+ I WindowId $[infostore.FocusID] Focus
+ I Current InfoStoreAdd FocusID $[w.id]
Silent Key g A M GoFPage
HowTo
After startup on Page 0 0.
Open one app or more.
Press alt-g
Go to one new page e.g. Page 1 0, and click / focus one window.
Now, alt-g goes back and forth between page 0 0 and 1 0. Works well.
Quite ok using two pages, but not with multiple pages and desks. I don’t think there is a function to remember the focused window IDs on multiple pages, the aim of this function. I am using 8 pages with no fixed pattern between them.
The function I made should be capable of both x and y direction of pages
This line stores the window id of a variable with a name based on page number.
On page 0 0, this variable would be called lastFocusPage00 in my code. This should work with any number of pages in both the x and y direction.
As for supporting multiple desks. I’m sure there are command expansions for that too and if there is, it should be easy to extend to support that too
It works well for GoToPage because of the universal variable $0 $1 GotoPage $0 $1, but not for WindowId. It gives a wrong ID number by adding the page numbers (11 digits instead of 9 digits).
Example window focus on Page 1 0 Wrong output: WindowId 100x6002575 Focus
I tested on FvwmConsole, this works: WindowId 0x6002575 Focus
Limited SOLUTION with separate variables for Page and ID:
+ I Current InfoStoreAdd lastFocusPage $[page.nx] $[page.ny]
+ I Current InfoStoreAdd FocusID $[w.id]
+ I GotoPage $0 $1
+ I WindowId $[infostore.FocusID] Focus
Best SOLUTION would be with universal variables $0 $1 $2 but something is missing with $2.
+ I Current InfoStoreAdd lastFocusPage $[page.nx] $[page.ny] $[w.id]
+ I GotoPage $0 $1
+ I WindowId $2 Focus
From the looks of it you are separating lastFocusPage, $[page.nx] and $[page.ny] with a space. These are not supposed to be separated, and will not work as I intended if they are separated. My solution stores the window ID in different variables depending on the page you are on.
With your bottom solution, you would have to pass the ID of the window to be focus and this would just be unnessecarily complicated.
$0 is the first parameter passed, $1 is the second and $2 is the third and so on
Your wrong window ID comes from the page numbers being handled as input to InfoStoreAdd. What you want is for the page numbers to be expanded as part of the variable name instead. This is why there shouldn’t be spaces inbetween lastPageFocus, $[page.nx] and $[page.ny]. Spaces might work if you use quotes, but I haven’t tested this
I don’t think variable names can have spaces, and you can only store a single value in an infostore variable, that is why creating a variable for each page/desk works.
I’ve seen this problem solved before, I don’t know if it was in the forms or not, but someone already setup functions using infostore to give the last active window focus when switching between pages.
You would need to make one for every direction.
Here is an example:
EdgeLeaveCommand North SwitchPage 0p -1p
EdgeLeaveCommand South SwitchPage 0p 1p
EdgeLeaveCommand West SwitchPage -1p 0p
EdgeLeaveCommand East SwitchPage 1p 0p
EdgeLeaveCommand takes the direction you leave, and the function to call. This function is then activated once the time specified by EdgeMoveDelay has gone by.
My code will have the same problem as this. If there isn’t any window in the page, the old window will retain its focus. If you want to remove the focus from the old window no matter if there is a window in the page you are going to, you could use a function for this.
I recently made a function to remove window focus from a window, then call another function and it is as follows:
DestroyFunc RemoveFocusAndCall
AddToFunc RemoveFocusAndCall
+ I Current InfoStoreAdd lastFocus $[w.id]
+ I Style $[infostore.lastFocus] NeverFocus
+ I $0 $[1-]
+ I Style $[infostore.lastFocus] ClickToFocus
It stores the window ID in a temporary called lastFocus. It then sets the style of this window to NeverFocus, which removes its focus. The next line, + I $0 $[1-], takes the first user input which is supposed to be a function, and calls it with the rest of the parameters starting from $1.
An example usage would be as follows:
RemoveFocusAndCall SwitchPage 0p -1p
or with EdgeLeaveCommand:
EdgeLeaveCommand North RemoveFocusAndCall SwitchPage 0p -1p
I think these should work together, but there is no guarantee as I haven’t used these in junction myself. From looks of it these shouldn’t be incompatible, but if you get problems try this instead:
DestroyFunc RemoveFocusAndCall
AddToFunc RemoveFocusAndCall
+ I Current InfoStoreAdd lastFocus $[w.id]
+ I Style $[infostore.lastFocus] NeverFocus
+ I Style $[infostore.lastFocus] ClickToFocus
+ I $0 $[1-]
These removes focus, then reverts the ClickToFocus style before calling the function