[Solved] Environment variables and module configuration

Hi folks,

I am trying to use environment variables (both default and user-defined), mainly to set paths and window sizes and positions. However, as soon as I try to use these within module configuration, I run into trouble. Some things work only after a restart of fvwm, some don’t work at all.

For instance, when I try

*FvwmScript:    Path $.

I get

[FvwmScript][ReadConfig]: <<ERROR>> Can't open the script   '/etc/X11/fvwm'/<nameofscript>

(and fvwm hangs when waiting for the script’s window), whereas

SetEnv Temp $.
*FvwmScript:    Path $[Temp]

works flawlessly.

Similar happens when trying to place/move windows according to size and/or position of other windows, e. g. having

AddToFunc StartFunction
+ I Module FvwmScript MyScript
+ I Wait MyScript
+ I Next (MyScript) Move -0 0
+ I Next (MyScript) SetEnv MyWidth $[w.width]
+ I Next (MyScript) SetEnv MyHeight $[w.height]

then the attempt to place a FvwmButtons instance named SystemPanel using

*SystemPanel: Geometry -0+$[MyHeight]

fails, even though the variable $[MyHeight] expands correctly when Echoed just before this FvwmButtons instance is launched. In this case, everything is OK after a restart.

The latter case will of course be not so important when
this hits the distros, but that a) takes some time and b) doesn’t always help.

Any hints or explanations?

tia,

– owl

EDIT: Added the [Solved] label

You want and mean:

$[FVWM_USERDIR]

Although that will get searched as a matter of course when using:

FvwmScript SomeFile

And note that “$.” is only expanded via a Read command anyway.

This is just a side-effect as to how the token “Geometry” is parsed via FvwmButtons. You want:

Module FvwmButtons -g -0+$[MyHeight] SystemPanel

It will be important of course, now that you understand what’s happening.

– Thomas Adam

I don’t think I want this, since the config file in question is a systemwide one, residing thus somewhere in /etc. This is also why I want to set the FvwmScript path at all, and why

FvwmScript SomeFile

does’t work for me. However, this

is quite new for me, since in the fvwm manpage, “$.” is listed together with all the other variables which I succesfully referenced on several places throughout the config file. Just to be sure that I understood you right: do you really mean that “$.” can only be used within a “Read” command (or its arguments, for that matter)?

I would have guessed this, but tried to ask anyway since I didn’t see it mentioned explicitly anywhere. The idea behind this was to keep the modules’ configuration in one place, including the window’s position. If it isn’t possible - well, OK.

Not that much important. It surely simplifies the config, removing some functions. From my point of view, it still means to reorder my config a bit. The substantial (for me, at least) information here is that variables cannot be used within module configuration.

Thanks for explaining all that!

– owl

So set it then to wherever it’s needed.

Because the location of your script is not in $[FVWM_USERDIR] or the system-wide location FVWM is looking in. Hence why you need to set it yourself manually.

It’s only expanded within a Read command.

It is possible – you just have to evaluate just how highly sectioned everything else. Over-engineering it is stupid.

Yes they can – you were just misunderstanding how “$.” gets expanded. Everything else can be interpolated via $[…]. Please don’t think your problems are indicative of everything. ;)

– Thomas Adam

Allright, things seem to have clarified a bit. And I’ll try not to generalise inadequately, I promise :slight_smile:

thx,

– owl

I have been experimenting again a bit, got around some minor errors etc. For the sake of brevity, I’ll now leave out code examples etc. and start directly with my assumptions (please only small stones if this was wrong :slight_smile:)

It seems that within module configuration, one can only use “static” variables, i. e. those set somewhere else in the config file. The “dynamic” ones (values defined as an expression and evaluated during StartFunction execution, for instance) don’t work, even if their value is guaranteed to be set before the respective module (within the configuration of which they appear) is started.

Is this correct? If so, can you think of a way to circumvent this?

Notes:

  • the problem appears during the first startup only, everything is fine after a restart (sure, since I don’t UnSet the variables in question)
  • if the above isn’t very clear, please drop a line here, I’ll post sample code

thx,

– owl

You’ll need to provide an example of what it is you’re trying to do.

Essentially, here’s how environment variables work in FVWM. When you use something like:

SetEnv foo some_value

You ideally want these to be more or less at the TOP of your .fvwm2rc file. Due to how FVWM parses its config file, it’s advisable to do this at the start, since FVWM reads it sequentially. If, for instance you reference something in, say, StartFunction via an expanded variable which is unknown and not already declared via SetEnv, it’s going to fail. This is why keeping such SetEnv definitions at the bottom of your .fvwm2rc file is a bad idea.

The reason you’re seeing the behaviour that you are is due to how inheritence works. Take for example, how environment variables are exported by FVWM. To use the example again from above:

SetEnv foo some_value

FVWM will parse this, call a function which will include putenv() which will place the environment variable into FVWM’s environment space. Here’s the key point though: Anything consequently spawned by FVWM will inherit the environment space, including those variables. This includes modules, which is why it’s so important to declare them before such modules which need or reference a SetEnv value to be set, is done so beforehand.

If you’ve got problems, you must provide an example of what it is you’re trying to do. Brevity is no excuse.

– Thomas Adam

Thomas, I did not mean to find excuses for anything. What I was trying to do, was to describe the general idea I am pursuing and the problem I thing I’m having with that - in order to give the people helping me a chance to say whether it generally makes sense or whether I’m totally wrong actually before they have to read config snippets etc. In other words, to save their time (in this case yours so far). If this doesn’t work - sorry for that, I can learn not to repeat it.

And now for my problem itself. What I am trying to do is basically to keep hardwired size/position settings as few as possible and preferably in one place. So amongst other things (some of them already solved thanks to your previous answers), I tried to get some apps start “offscreen” during fvwm startup, “measure” the size of their windows using $[w.height] and the like and set FvwmButtons sizes accordingly. So, for instance, I tried to include

+ I RunPager
+ I RunButtons

in my StartFunction, where RunPager is

[code]+ I Module FvwmPager MyPager 0 1

  • I Wait MyPager
  • I Next (MyPager) SetEnv PagerH $[w.height]
    [/code]

and RunButtons only starts the FvwmButtons instance. The relefant config line is

*MyButtons: (1x2, Frame 1, Size $[ButtonW] $[PagerH], Swallow(UseOld,NoClose) "MyPager" Nop)

where ButtonW is defined at the beginning of the config file straightforwardly (this is the hardwired value I was writing about).

The behaviour of this however is, that on first startup, I get tiny FvwmButtons instance at the right position, but wrong sized - it has a width across the whole screen and a height of only several pixels. After a restart, everything works fine - so I assume basically a timing problem in the sense of what gets parsed and evaluated at which point and what values are available at that point.

Two more hints:

  • an Echo command put between the two function calls is printed correctly, so both variables used in the configuration of MyButtons are available at that point
  • changing the second call in StartFunction to “Schedule 1000 RunButtons” does not help

thx!

– owl

It’s an odd quirk – and it is one of a timing issue, just not immediately obvious. Because of the way the .fvwm2rc file is parsed some of it runs before other parts, hence the fix in this case is to wrap the module definitions in a function, as an example:

DestroyFunc setsizes
AddToFunc setsizes
+ I Exec exec xterm -T foo
+ I Wait foo
+ I Next (foo) SetEnv F $[cw.width]
+ I Next (foo) SetEnv G $[cw.height]

DestroyFunc CB
AddToFunc CB
+ I DestroyModuleConfig b:*
+ I *b: Rows 1
+ I *b: Columns 1
+ I *b: (Frame 1, Size $[F] $[G], Swallow (NoHints, UseOld) 'foo' Nop)
+ I Module FvwmButtons b

DestroyFunc StartMe
AddToFunc   StartMe
+ I setsizes
+ I CB

StartMe

And note that, unlike your example, you’re using $[w.height] – this is wrong, since you really want to know the client height of the window you’re swallowing before it’s reparented. Likewise, the use of ‘NoHints’ to Swallow is also something you should be using.

– Thomas Adam

It took me quite some time until I managed to try it out. So (mainly for those reading this thread after a year or so): yes, it works - and it does solve the problem.

Thanks, Thomas - for the $[cw.<…>] hint as well.

– owl