Window focus on desk/page change?

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

Any solution for 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.

Thanks, for having patience in finding a solution. For me a good exercise to learn and for other users a great function when we do find.

@somiaj: someone already setup functions using infostore to give the last active window focus.
I am sure someone made it. I was also browsing around.

Got another idea when I read @thomasadam Understanding Layers. Would it be possible to fix focused window to a layer and recall it on page return?

Use State, not layer, you can save windows in different states if you didn’t want to use InfoStore

I found an old topic using State and ClickToFocus, Always focusing a window on the current page. Later today I will check.

Last step, is to bind the function.

@noguardkenny: If you use the edge scroll supported by FVWM, add this function to EdgeLeaveCommand for every direction.

This is my current edge scroll, how to bind function SwitchPage ?

EdgeScroll 0 0
EdgeResistance 450
EdgeThickness 1
Style * EdgeMoveDelay 500, EdgeMoveResistance 100

ManPage: *The binding works only if EdgeThickness is set to a value greater than 0.

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

Use FvwmEvent if you want to catch all page changes, instead of using a function to switch pages.

How would you know which page you last were on? I see how everything else can be done with FvwmEvent, but would you store or check the previous page?

You would have to save that in an InfoStore variable since the new_page and new_desk events will only send the desk you moved to. Either that or store info about which window was last focused using State, and in this case you don’t really need to know what the previous page is. Next (CurrentPage, State X) will find the window you want to focus.

This State function works fine for my Xfce friends. I like it. It does the focus on any number of pages. Also, not a problem if it turns the previous window unfocused from an empty page because nobody goes to empty pages without doing anything there.

Has a slightly unstable focus when going drastically from one end of a Desk to another. Not a problem, just a sign of moving between Desks.
The function is simple and easy to understand. I copied it here below, add it at the beginning of your config.

Remember focused window in current page:

SetEnv FocusPage 0

DestroyFunc SavePageFocus
AddToFunc SavePageFocus
+ I All (CurrentPage) State $[FocusPage] False
+ I Current State $[FocusPage] True

Restore previously focused window in current page:

DestroyFunc RestorePageFocus
AddToFunc RestorePageFocus
+ I Current (CurrentPage) Break 1
+ I Next (CurrentPage, State $[FocusPage]) Focus
+ I None (CurrentPage, Focused) Prev (CurrentPage) Focus

DestroyModuleConfig FvwmEvent-FDpg:*
*FvwmEvent-FDpg: Cmd
*FvwmEvent-FDpg: new_page RestorePageFocus
*FvwmEvent-FDpg: new_desk RestorePageFocus
*FvwmEvent-FDpg: focus_change SavePageFocus

Module FvwmEvent FvwmEvent-FDpg

NOTE: This shared code is tested and works well.

It keeps focus on the adjacent page of the next desk but no further distance e.g. from Desk 1 Page 1 0 to Desk 2 Page 0 0. Would be good also to fix this. Desker script in Fvwm Kise has 4 Desks, two pages each. Gets annoying with a focused email window on Desk 1 and going to search for data on an unfocused Desk 3.

It should be possible to include CurrentDesk and CurrentPageAnyDesk.

Don’t use CurrentPageAnyDesk, that is not what you want, add the new_desk event to FvwmEvent and run the exact same function.

Also, the FvwmEvent config is incorrect in the shared code, you need to use *FvwmEvent-Focus for all the configuration options (you were missing the -Focus). And then you launch it with Module FvwmEvent FvwmEvent-Focus.

:1st_place_medal: Thank you @somiaj, the focus works perfectly on all pages and desks.

Note: Doesn’t work if FvwmEvent-Focus is on all configuration options. This I also understood with @thomasadam suggestion: FvwmEvent-Focus: Cmd. -Focus is just any name to differentiate from other FvwmEvent. Only for Cmd.

so that multiple FvwmEvent’s can then be defined for other Events. It might be the case that a user has other events scheduled which would get overriden with the binding to just “FvwmEvent”, as you have it in your example.

Not to confuse -Focus as a command, I edited it to *FvwmEvent-FDpg: Cmd and added option *FvwmEvent: new_desk RestorePageFocus.

My shared code that was posted, I have corrected and tested it. Works well.

That is not how module alias work. Thomas’ suggestion was to use a module alias. In this case you need to configure the alias with *AliasName: ConfigOption, and then launch the module with Module FvwmEvent AliasName. For an example see the default-config and how it uses the EventNewDesk alias for FvwmEvent.

Note this isn’t special to FvwmEvent either. The default-config also uses the alias RightPanel for the FvwmButtons module. All of the options to configure it use *RightPanel for the alias configuration. Because you are setting configurations for the main FvwmEvent module, you won’t achieve the effect Thomas was talking about because you are writing the configuration for just FvwmEvent.

The way you would use an alias in your case is as follows:

DestroyModuleConfig FvwmEvent-FDpg:*
*FvwmEvent-FDpg: Cmd
*FvwmEvent-FDpg: new_page RestorePageFocus
*FvwmEvent-FDpg: new_desk RestorePageFocus
*FvwmEvent-FDpg: focus_change SavePageFocus

Module FvwmEvent FvwmEvent-FDpg

I’m unsure why your test are failing, but I think you are just getting lucky that your code works since you are setting configuration for the main FvwmEvent and not just the alias. And the only thing you are setting for the alias is Cmd which is the default anyways.

@amlug, I am glad that you worked out the solution, though, last part is not correct.

@somiaj is right. I think you are using Fvwm Kise? The Thumbnails script has FvwmEvent that causes a double event which makes the focus work.

With somiaj correction, I will add this function to Kise. :star2:

Good to know. I have corrected the code.

1 Like