2009/9/8 Michael Talbot-Wilson <div3uni...@view.net.au>: > I'm starting the xterm in .xinitrc rather than .fvwm/config because I > want it to survive the death of the window manager.
Bear in mind that when the window is recaptured across restarts, all that will do is reparent the window, and leave it as-is. > DestroyFunc StartFunction > AddToFunc StartFunction > + I Module FvwmAnimate > > DestroyFunc InitFunction > AddToFunc InitFunction > + I exec xsetroot -solid SteelBlue > + I Module FvwmPager OnePager * > + I Module FvwmPager FourPager 0 3 > + I GotoPage 1 2 > + I exec xlogo -render -fg blue -bg yellow -xrm "*Page: 0 1 2" This is not quite right for several reasons: I'm going to give you more information here than you wanted since this question comes up so often that i get tired of answering it. So this is one for the archives... When you run FVWM it does this in terms of config reading: SetRCDefaults() -> Read $(fvwm-config -d)/ConfigFvwmDefaults -> System-wide or $HOME/.fvwm2rc file. SetRCDefaults() is just a function that sets up the *bare* minimum for interacting FVWM, it provides a menu a set of limited bindings, and hopes for the best. If you pass FVWM a config which is empty, perhaps via: fvwm -f /dev/null ... you can see for yourself what that looks like. Then, as part of SetRCDefault, the file $(fvwm-config -d)/ConfigFvwmDefaults is loaded -- this expands to (on my machine): /usr/local/share/fvwm/ConfigFvwmDefaults This file is crucial. It defines a load of common functions (which tend to act as callbacks) for various things: * "WindowListFunc" -- used when an item is selected from the WindowList. * "EWMHActivateWindowFunc" -- used when an EWMH-window requires handling. * "UrgencyFunc" -- the function that's run if an XClient demands attention -- such as pidgin chat windows. This file also defines a set of bindings for interacting with the menu (that is, fvwm_menu) defined earlier in the SetRCDefaults() function, as well as some rudimentary bindings. Nothing more though. Take a look for yourself. After this comes either what was passed in as a file to look for via the "-f" flag, or then one of predefined list of system-wide config files FVWM expects to find, or one in $HOME -- and indeed, FVWM config files are looked for in $HOME/.fvwm/ before anywhere else. So you can gather now, what the purpose of a .fvwm2rc file is -- it's either going to augment functionality found in $(fvwm-config -d)/ConfigFvwmDefaults, or more likely replace it with functionaality the user wants. So... now that's covered, we now look at how your ~/.fvwm2rc file is read [1]. FVWM does nothing special. It will start at the top and read its instructions in line-by-line until it reaches the end. Depending on what it reads in, it will either execute that line on the spot, or collate line(s) together to run at a certain point. This explains why a typical ordering is suggested for your .fvwm2rc file: SetEnv (Ugh!) Colorsets Style lines Bindings Functions Since, for example, if a Style line used a variable from SetEnv, it would have to come after the env var was declared, as FVWM would be unable to interpolate it out for the specific style line, resulting in a parsing error of that line. I said earlier that FVWM will and can collate lines to run -- there's two instances on *initialisation* where this is true: InitFunction StartFunction In that order. Hence, now that you realise how FVWM parses its file, why it's possible to do this: DestroyFunc StartFunction AddToFunc StartFunction + I Beep Style foo !Icon AddToFunc StartFunction I Beep ... AddToFunc is cumulative when used in successive calls with a known function. So you can build up (in this case) StartFunction, and because it's run after processing the whole file, you know you're not going to lose anything by doing it this way. So, InitFunction if it's defined is called first. Then StartFunction. So you might ask what's the difference, and why should you care. Well, here's the rub: *INITFUNCTION IS CALLED ONCE -- AT INIT TIME WHEN FVWM FIRST STARTS. STARTFUNCTION IS CALLED AT INIT AND RESTART.* So you can see now that you only need one function for your purposes, as you can add checks to StartFunction to tell it to do one thing if FVWM is initialising, and another if it's not (i.e., presumably at restart). So to go back to your original example of the functions you had: > DestroyFunc StartFunction > AddToFunc StartFunction > + I Module FvwmAnimate > > DestroyFunc InitFunction > AddToFunc InitFunction > + I exec xsetroot -solid SteelBlue > + I Module FvwmPager OnePager * > + I Module FvwmPager FourPager 0 3 > + I GotoPage 1 2 > + I exec xlogo -render -fg blue -bg yellow -xrm "*Page: 0 1 2" You would now define the one function as the following: DestroyFunc StartFunction AddToFunc StartFunction + I Module FvwmAnimate + I Test (Init) Exec exec xsetroot -solid SteelBlue + I Module FvwmPager OnePager * + I Module FvwmPager FourPager 0 3 + I Test (Init) GotoPage 1 2 + I Test (Init) Exec exec xlogo -render -fg blue -bg yellow -xrm "*Page: 0 1 2" There's a couple of things to note here: * Modules do not get treated specifically as wanting to start just at initialisation time because you most likely don't want this (one exception to this though would be FvwmBanner perhaps) -- when FVWM restarts modules die because FVWM closes the pipes it was using to communicate with them, so having them load up regardless of whether it's at init time or not makes sense. * The test for working out whether FVWM (at the time it reads the StartFunction) is in Init, is done via: + I Test (Init) * Unrelated to anything I've mentioned so far, you'll note I am using: Exec exec foo As opposed to: Exec foo ... this is so that we don't leave the shell around that FVWM used to span "foo" in the first place. The double "Exec exec" takes care of that for us. The process looks like this with just "Exec foo": FVWM ---> (shell) -> foo But since "Exec" spawns a command via $SHELL, then what you end up with is a "dead" (shell) process once "foo" has loaded. So to get rid of that, just (from (shell) replace it with "foo" outright: FVWM ---> foo This is why the case is important for: "Exec exec" -- the second *exec* will be the shell builtin. > AddToFunc RestartFunction > + I InitFunction Knowing what you do now, you should realise you don't need this. > AddToFunc SessionInitFunction > + I InitFunction Generally a "bad" idea -- especially if your InitFunction spawns terminals. > AddToFunc SessionRestartFunction > + I RestartFunction See above. OK. So now on to your original question. Here's what you have currently: DestroyFunc InitFunction AddToFunc InitFunction + I exec xsetroot -solid SteelBlue + I Module FvwmPager OnePager * + I Module FvwmPager FourPager 0 3 + I GotoPage 1 2 + I exec xlogo -render -fg blue -bg yellow -xrm "*Page: 0 1 2" But, you've already started your "login" xterm in ~/.xinitrc. At the time InitFunction runs several things could be happening here: 1. Applications are still starting up; including your "login" window. 2. The application you expected to start **AFTER** "GotoPage 1 2" is already mapped. Oops. You can see the problem, right? You have a race-condition here. You don't know at the point FVWM is running along with starting up everything else when things will come together. There is only one way you can do this reliably: + I Schedule 5000 Next (login) MoveToPage 0 1 2 I say "reliably" loosely here. The Schedule command is here to give the window a chance to load, and ensure it really has done before FVWM tries the condition command asksed on it. Because you're starting this application out of band from FVWM's own start-up, expecting FVWM to be able to do anything with the window, because it might not be mapped or if it is then move it, means you can't do things like this: Style login StartsOnPage 0 1 2 ... nor can you do something like this: AddToFunc StartFunction + I None (login) Exec exec xterm -T login + I Wait login + I Next (login) MoveToPage 0 1 2 (Well, you could, but you run the risk of doubling-up your original window, especially if it is just about to start when this does -- you'd get two). Also bear in mind that I have assumed in all of the above that you don't need to switch to the page "0 1 2" in question -- you generally don't, c.f. SkipMapping -- but before that was introduced, one of the older idioms of making applications appear on the right page was to do just this: + I GotoPage 0 0 + I Exec xterm -T foo + I Wait foo + I GotoPage 0 1 + I Exec xterm -T foo2 + I Wait foo2 + I GotoPage 00 ... and so it goes on. Generally though no longer used. Given the caveat of using "Wait" which really will hang FVWM as it waits for a given window, it would get annoying if one of the commands you were running which was meant to spawn a window didn't -- or it had a different name as it transitioned from the time it was mapped to the point the correct XAtom of the client was consulted to match the given string used with "Wait" for example, but I digress. You originally mentioned wanting this "login" window to survive the window manager. Why not cheat? DestroyFunc ExitFunction AddToFunc ExitFunction + I Test (Quit) Restart xterm -T login I'm done now. -- Thomas Adam [1] I keep referring to ~/.fvwm2rc or ~/.fvwm/config -- they're the same thing -- some user's FVWM config file. I am just an old enough user of FVWM to still recall it as ~/.fvwm2rc.