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.

Reply via email to