Use window variables to select Style details?

Hi!

I’d like to select particular MiniIcons (for example) using more than
one of the window name, class, visible name, and resource string.
In this particular case, I have mini icons of different shapes
for an xterm session at the shell prompt or one running vim, and
different colours depending on which host is connected to.

The class matches XTerm for all of the xterms, the visible name
matches “VIM” when vim is in use, and I can get the hostname from
the icon name (which I set when starting the xterm). I wish I
could do something like this:

Style “XTerm” MiniIcon mini_xterm_$[w.iconname].xpm
Style “VIM” MiniIcon mini_vim_$[w.iconname].xpm

but this doesn’t work, so I assume I can’t use a variable name in that
spot, or in that way, or the “w” variables aren’t set at that point…

How can I approach this? Is what I want even possible?

Anne.

Perhaps something like this ?

##  Default miniicon
Style XTerm Miniicon mini_xterm.xpm

##  Runs XtermMiniiconFunc for each new window.
Style XTerm InitialMapCommand XtermMiniiconFunc

DestroyFunc XtermMiniiconFunc
AddToFunc   XtermMiniiconFunc
+ I ThisWindow (hostname1) WindowStyle Miniicon mini_host1.xpm
+ I ThisWindow (hostname2) WindowStyle Miniicon mini_host2.xpm
+ I ThisWindow (hostname3) WindowStyle Miniicon mini_host3.xpm

Thanks for introducing me to the InitialMapCommand! Interesting.

But in this case, since I already set the resource name to
“hostname-session” when I fire up the window (with xterm -name
$hostname-session), I’m not sure that your proposal is all that
different from what I have now, which is something like:

Style “pandora-session” MiniIcon mini_xterm_pandora.xpm
Style “quill-session” MiniIcon mini_xterm_quill.xpm

… and so on. Also, it doesn’t address switching the MiniIcon to
a host-specific “vim” icon when vim is in use, then reverting to
the host-specific “xterm” icon when vim exits.

I’m starting to look at what I can get vim to do for me with
“titlestring”; I can probably get “hostname-vim” in there, and then
match on that. I’d still be using enumerations, but at least I’d get
the behaviour I want, I think.

Again it would be cool if it could be done with window variables
instead of enumerations, but I’m starting to suspect that fvwm
syntax simply doesn’t support that.

That “InitialMapCommand” is neat in that the use of a function
allows the use of conditional statements, and the conditional
statements can be multiple - I think that does lead somewhere useful!
But InitialMapCommand is invoked just once “when the window is
initially mapped” - I don’t, offhand, see a way to invoke a function
whenever (for example) the visible name changes.

This is all quite encouraging; thank you!

Anne.

In that situation, the FvwmEvent Module might help. It happily triggers on name changes etc.

##  Uncomment either "visible_name" or "visible_icon_name"
DestroyModuleConfig FvwmEvent: *
*FvwmEvent: Cmd Function
*FvwmEvent: visible_name        SomeFunc
#*FvwmEvent: visible_icon_name  SomeFunc

DestroyFunc SomeFunc
AddToFunc   SomeFunc
+ I Echo * Your stuff here...

##  Start FvwmEvent module
KillModule FvwmEvent
Schedule 1000 Module FvwmEvent

Style lines only apply for windows being mapped, not when attributes about a window change. Although I can see you been directed towards “visible_name” in FvwmEvent as a solution, this is only going to get you so far before you need to rethink your approach, simply because you can’t make any guarantees about the application changing its name.

Furthermore, visible_name is only applicable for a window’s title – and there’s no guarantee about how applications set that, either. You can probably get away with it if it’s XTerm, but as you’re finding out, you’re having to rely on application inside being able to set that. Hence, I’m dubious what point you think setting the window’s resource and hostname is going to achieve – you can always pull these out of FVWM with $[w.].

I would suggest you use State instead on these windows and get those conditions to influence a window’s state, and then you can get FVWM to act accordingly.

– Thomas Adam

First, a big thank you to phleagol for pointing me towards the FvwmEvent module; because I’d been repeatedly restarting the window manager to see the effect of my configuration changes, it hadn’t dawned on me that (under normal circumstances) they would be applied only when the window started up, so I would have set up all my styles only to find out later that they were not applied when the window changed! You’ve saved me a lot of annoyance. :wink:

Thanks also for supplying a code snippet to get me started. Despite having used fvwm for probably close to two decades, my needs have been simple and I’d never tried to use modules before. But I’ve spent the evening playing with this and it’s very cool! I think I’m pretty close to getting it to do what I need.

As it happens, though, the applications I’m interested in are xterm at a tcsh prompt, xterm running vim, and firefox; with the first two, I can control the window name change, and with the last, I’m satisfied with the app’s behaviour in this respect.

I’m putting various pieces of information into the window’s icon name and title precisely so I can use them in my fvwmrc to select icons and set labels. I suspect I didn’t understand your question. :frowning:

I’ll keep that idea in mind if a simpler approach doesn’t do the trick. But if I understand correctly what you’re suggesting, I think I’d generate too many states, because I’d need a state for each hostname/app combo, and I have dozens of them.

I’m going to learn the syntax of the conditional commands in functions, and if the syntax is insufficient to express what I want, I might just set a style by PipeReading out to a Perl script, to which I can feed the $[w.] fields I need to make my colour and icon selections.

The good part of all this is that I’m having fun learning how to make fvwm jump through hoops, and I’m grateful to you folks for your extremely useful input! Thanks again,

Anne.

You’re welcome! Merry xmas porcupine.

Just a quick report; the following works (in conjunction with my using vim’s “titlestring” to make sure the string I want is in the window’s visible_name):

DestroyModuleConfig FE-Styles: *
*FE-Styles: Cmd Function
*FE-Styles: visible_name        ChangeMiniIcon

DestroyModuleConfig FE-Sounds: *
*FE-Sounds: Cmd "Exec aplay"
*FE-Sounds: visible_name        /home/a/anne/.sounds/bell-1.wav

DestroyFunc ChangeMiniIcon
AddToFunc   ChangeMiniIcon
+ I Echo Window $[w.id] visible_name=$[w.visiblename]
+ I ThisWindow ("*-vim *") Echo "...is a vim window on $[w.iconname]"
+ I ThisWindow ("*-vim *") WindowStyle MiniIcon mini_vim_$[w.iconname].xpm
+ I ThisWindow (!"*-vim *") Echo "...is NOT a vim window $[w.iconname]"
+ I ThisWindow (!"*-vim *") WindowStyle MiniIcon mini_xterm_$[w.iconname].xpm

# Start FvwmEvent modules
KillModule FvwmEvent FE-Styles
Schedule 1000 Module FvwmEvent FE-Styles
KillModule FvwmEvent FE-Sounds
Schedule 1000 Module FvwmEvent FE-Sounds

(The sounds and Echo commands are temporary for debugging.)

I’m going to refine this some more, but I have proof of concept. :slight_smile:

Again, thank you, and happy holidays!

Anne.

Don’t start Modules like this. Use StartFunction for anything which is going into your configuration file. There’s no need to Schedule this at all.

– Thomas Adam

I’m puzzled; why won’t it match the way I think it does for negations? I re-read the manpage yet again, and it states that “Each window name can begin with ‘!’, which prevents command if any of the window name, icon name, class or resource match”, which seems like what I want, and it was working, based on the Echo commands I had in there.

Now it’s flakey again - the Echoes show the Right Thing, but the mini icons don’t always get set. I think I’m going to end up working around all this (see below).

Fuss is perhaps a big word :wink:, but…

The expression “*-vim *” matches on the window’s visiblename (or name, which in the case of all of the windows I’ve checked with xprop, is the same as the visiblename). Perhaps I’ve caused confusion and should have referred to the name. Perhaps there are situations where the two differ, though I haven’t seen any in my modest set-up.

Okay, I defer to your greater knowledge of best practice; I’ve moved
all my module start-ups to StartFunction. Thank you.

Meanwhile, now that I understand what modules can do, I’ve taken the next logical step and written one of my own, using FVWM::Module. Now I can grab a lot of info about the window using a call-out to “xprop -notype -id $window_id”, and perform arbitrary actions based on any match I wish, using the full power of Perl regexps. I find that easier to code.

I have a proof of concept - at the moment I just cycle the BorderColorset and HilightBorderColorset through four arbitrary colours whenever the visiblename changes, and I log what I found out and calculated about the window upon that event. But I can probably set pretty much all I want (border and title colours, icons and mini icons) from this script, and simplify my fvwm config files in consequence.

I do wonder, though, if there’s an easier way to grab the window properties from Perl, ideally through a subroutine call to an fvwm-supplied Perl module. Parsing xprop’s output is kind of ugly.

Anne.

There is. Look at Fvwm::Event::dump() for example.

– Thomas Adam

That seems to supply:

DUMP: M_VISIBLE_NAME
   win_id       0x1200022
   frame_id     0x080058f
   ptr          40991568
   name         "quill     (anne)     /home/a/anne/.x/fvwmrc/modules "

… which is not nearly as much information as I get from xprop, but I know
that fvwm is tracking a lot more info than that about the window. Is one of
win_id, frame_id, or ptr a reference to an object or a data structure that I
can dereference or query to get at, for example, WM_CLASS and WM_ICON_NAME?

Anne.

No, they are not references. M_VISIBLE_NAME only provide 4 arguments, but other event types do provide more arguments, as you can see here…

fvwm-perllib man events

That aside, the WindowList tracker provides perhaps the most complete info for any given window, including class_name and icon_name. To read more…

fvwm-perllib man FVWM::Tracker::WindowList fvwm-perllib man index

That does seem interesting, but I’ve spent the evening trying in vain to make that work. I think I’m missing a fundamental insight somewhere.

I’ve been assuming I could just add the use of the WindowList tracker to my current module, which uses FVWM::Module, registers a bunch of handlers, and enters the event loop. When I try to create a tracker by calling “track” on the FVWM::Module object before telling it to enter the event loop, things just stop working at all.

Am I supposed to entirely replace the use of the FVWM::Module “addHandler” and “eventLoop” with “observe” calls to an FVWM::Tracker::WindowList object?

Anne.

Perhaps windowlist tracker is not the simplest solution for your situation. Sorry about that. But if we avoid the tracker, and stick with just the event_loop, then class and names can be gathered with something like this…

#!/usr/bin/perl
#  Get name and class for all windows then dump and exit.

use strict ;
use warnings ;
use lib `fvwm-perllib dir` ;
use FVWM::Module ;
use Data::Dump qw( dump ) ;

my $modname = "FvwmTest" ;
my $module = new FVWM::Module(
        Name => $modname, 
        Mask => M_WINDOW_NAME | M_RES_CLASS | M_END_WINDOWLIST,
        Debug => 0, 
        ) ;

my $ww  ;

$module->addHandler(M_WINDOW_NAME, sub {
    my ($module, $event) = @_ ;
    my $wid = $event->args->{win_id} ;
    $ww->{$wid}->{name} = $event->args->{name} ;
}) ;

$module->addHandler(M_RES_CLASS, sub {
    my ($module, $event) = @_ ;
    my $wid = $event->args->{win_id} ;
    $ww->{$wid}->{class} = $event->args->{name} ;
}) ;

# $module->addHandler(M_RES_NAME,       sub { ... }) ;
# $module->addHandler(M_ICON_NAME,       sub { ... }) ;
# $module->addHandler(M_VISIBLE_NAME,    sub { ... }) ;

##  Terminate FVWM::Module after windowlist completed. Just for this test...
$module->addHandler(M_END_WINDOWLIST, sub { $module->terminate }) ;

$module->send("Send_WindowList") ;
$module->event_loop ;

##  dump info after windowlist has finished.
dump $ww ;

Not a problem; I don’t need the simplest solution, but I do need a working solution. As I mentioned earlier, I do have a working solution that involves calling xprop, but that’s an extra process exec for every event, and parsing the output is somewhat ugly. Of greater concern is that I have to be a bit careful how hard I pound on the window system: at one point I was running my handler on “enter window” and “leave window” events as well, and that put fvwm into a wild loop - I had to ssh into my desktop from another host to kill the malfuncioning module.

But unless I badly misunderstand your code, you’re simply gathering information already supplied in the event object passed as a parameter to the handler. The problem I’m trying to solve is gathering additional information that I know is available to the window system and to fvwm, but is not contained in the event object. I need that information not about all windows each time, but just about the window whose event I’m processing. I’m given the window ID; is there a way within the FVWM modules ecosystem to use that window ID to obtain all information about that window?

Anne.

I’d say the windowlist tracker. That seems to be its purpose. But only a limited range of information is available. For example, is a certain window titled or untitled? The tracker does not tell us.

I mostly use the windowlist tracker instead of using event_loop, and it works just fine. But I recall attempting to use the windowlist tracker and event_loop together, and being surprised by some problem. But that was a long time ago, and I didn’t investigate further.

Not sure. Someone else may know.

Well, I didn’t feel like figuring out a whole new module, so I added caching to my existing code. Now I call xprop just once for any given window, and I update the values of interest in the cache based on the incoming event data for any event of interest. This also gave me the opportunity to determine whether an event actually changed anything of interest to me for determining the style of a window, and if not, I don’t issue a new WindowStyle command.

Now I can not only do what I wanted to do in the first place, which was to set particular MiniIcons, but I can make all of the Window styles very responsive to my actions. This is great!

Thanks for all the pointers, phleagol and thomasadam!

Anne.