FVWM: Trying to understand fvwm function execution
I feel like I'm missing some important bits about how fvwm handles functions. I'm trying to write a function that's fed a window name and has following goals. First, it only operates on terminal windows. Then: - if no (terminal) window by that name exists, it should do nothing. - if the currently selected/focused window has that name (and is a terminal window), it should do nothing. - otherwise, it should deiconify, focus, and raise the window, then move the pointer to be inside the window. My current version is: AddToFunc ToWindow + I Current ("XTerm|9term|Gnome-terminal", "$0") Break + I Next ("XTerm|9term|Gnome-terminal", "$0") Iconify False + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus + I Next ("XTerm|9term|Gnome-terminal", "$0") Raise + I Next ("XTerm|9term|Gnome-terminal", "$0") WarpToWindow 80 5 This works but seems unnecessarily repetitive (actually I'm suddenly not convinced that it does nothing if the current window is a terminal window called $0). So I thought I could rewrite it like this (with comments about the logic): AddToFunc ToWindow # do nothing if current window is called $0 + I Current ("XTerm|9term|Gnome-terminal", "$0") Break + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus # if no window is called $0, this stops; otherwise Focus has # made that window the current window. + I TestRc (NoMatch) Break # do the rest of the work + I Iconify False + I Raise + I WarpToWindow 80 5 However, this doesn't work if no such window actually exists; before anything from the function seems to execute (even an 'Echo' statement inserted as the first command in the function), the mouse cursor changes to the 'select a window' cursor. Clearly I'm missing something both about how fvwm executes functions and how it selects windows and handles conditional commands. Do I need to make all commands conditional in this function in order to have things work right, by putting plain 'Current ' in front of the last three lines? (A version with this change seems to do nothing if there's no terminal window by that name, but I feel I'm just sort of writing code by superstition instead of actual understanding at this point.) Thanks in advance. - cks
Re: FVWM: Trying to understand fvwm function execution
On Tue, Feb 07, 2012 at 03:41:22PM -0500, Chris Siebenmann wrote: > I feel like I'm missing some important bits about how fvwm handles > functions. > > I'm trying to write a function that's fed a window name and has > following goals. First, it only operates on terminal windows. > Then: > - if no (terminal) window by that name exists, it should do nothing. > - if the currently selected/focused window has that name (and is a terminal > window), it should do nothing. > - otherwise, it should deiconify, focus, and raise the window, then > move the pointer to be inside the window. > > My current version is: > > AddToFunc ToWindow > + I Current ("XTerm|9term|Gnome-terminal", "$0") Break > + I Next ("XTerm|9term|Gnome-terminal", "$0") Iconify False > + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus > + I Next ("XTerm|9term|Gnome-terminal", "$0") Raise > + I Next ("XTerm|9term|Gnome-terminal", "$0") WarpToWindow 80 5 This is why it's better to do this: Style XTerm State 1 Style 9term State 1 Style Gnome-terminal State 1 DestroyFunc ToWindow AddToFunc ToWindow + I Current (State 1, $0) Break + I Next (State 1, $0) SomeFunction DestroyFunc SomeFunction AddToFunc SomeFunction + I Iconify False + I Focus + I Raise + I WarpToWindow 80 5 So you can see here, by using State, that we've shifted the repetitiveness to the style of the window, and not a pre-condition to all commands we might need to reference a bunch of terminals. > This works but seems unnecessarily repetitive (actually I'm suddenly > not convinced that it does nothing if the current window is a terminal > window called $0). So I thought I could rewrite it like this (with > comments about the logic): > > AddToFunc ToWindow > # do nothing if current window is called $0 > + I Current ("XTerm|9term|Gnome-terminal", "$0") Break > + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus > # if no window is called $0, this stops; otherwise Focus has > # made that window the current window. > + I TestRc (NoMatch) Break > # do the rest of the work > + I Iconify False > + I Raise > + I WarpToWindow 80 5 > > However, this doesn't work if no such window actually exists; before > anything from the function seems to execute (even an 'Echo' statement Context is about how functions run, and the way you have it there, FVWM will need a window context to run in -- that is, a window to operate on. Your use of "$0" implies this to some extent, in that you have a name or something being passed in, but you don't say how. If FVWM doesn't have an operand window, then it will ask for one. This will depend on how you're trying to call this function. This is perhaps the most important piece of information you've failed to provide. > Do I need to make all commands conditional in this function in order > to have things work right, by putting plain 'Current ' in front of the > last three lines? (A version with this change seems to do nothing if > there's no terminal window by that name, but I feel I'm just sort of > writing code by superstition instead of actual understanding at this > point.) No you don't. Consider this: AddToFunc ToWindow + I Current ("XTerm|9term|Gnome-terminal", "$0") Break + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus + I TestRc (NoMatch) Break + I Iconify False + I Raise + I WarpToWindow 80 5 If I bind this to a key like this: Key f A M ToWindow Then press Alt-f, FVWM evaluates the context of the binding. It may well be that the window we're operating on is implied, in which case FVWM won't ask for a window -- and indeed, your implementation of ToWindow doesn't. FVWM processes the commands in order, top-to-bottom. It comes across "Current" and evaluates that in the context of the binding. Of course, there is nothing special about Current, Next, or TestRc, they can run inside a function just fine, and at this point assume no specific window -- but because you have this: + I Iconify False ... if FVWM processes this from your ToWindow function and there is no implied operand window for ToWindow to be running in, it will prompt for a window to run against, because it needs a window. Let me elaborate more on what I mean by operand window, and implied context. Mouse bindings are good for this: Mouse 0 1 A FuncWindowOpsOrClose DestroyFunc FuncWindowOpsOrClose AddToFunc FuncWindowOpsOrClose + H Nop + C Echo Clicked $[w.id] + D Close Pressing any mouse button on button 1 on a window will call FuncWindowOpsOrClose -- and note that here: + D Close I do not need: + D ThisWindow Close Nor do I need: + D Current Close It's because the binding happens on a window already. Once you have a window you're hooked on it though. So really, establishing a binding to one window can happen outside the function before invoking it, and that's precisely what I did with my original suggestion to you above:
Re: FVWM: Trying to understand fvwm function execution
| On Tue, Feb 07, 2012 at 03:41:22PM -0500, Chris Siebenmann wrote: | > My current version is: | > AddToFunc ToWindow | > + I Current ("XTerm|9term|Gnome-terminal", "$0") Break | > + I Next ("XTerm|9term|Gnome-terminal", "$0") Iconify False | > + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus | > + I Next ("XTerm|9term|Gnome-terminal", "$0") Raise | > + I Next ("XTerm|9term|Gnome-terminal", "$0") WarpToWindow 80 5 | | This is why it's better to do this: | | Style XTerm State 1 | Style 9term State 1 | Style Gnome-terminal State 1 | | DestroyFunc ToWindow | AddToFunc ToWindow | + I Current (State 1, $0) Break | + I Next (State 1, $0) SomeFunction Oh that's clever. I hadn't even thought of using states that way, and it makes everything much more modular (I don't have to hunt down N places to add things to if I decide that rxvt is also a terminal). Clearly I need to think more about ways to use States. Thank you! | > This works but seems unnecessarily repetitive (actually I'm suddenly | > not convinced that it does nothing if the current window is a terminal | > window called $0). So I thought I could rewrite it like this (with | > comments about the logic): | > | > AddToFunc ToWindow | > # do nothing if current window is called $0 | > + I Current ("XTerm|9term|Gnome-terminal", "$0") Break | > + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus | > # if no window is called $0, this stops; otherwise Focus has | > # made that window the current window. | > + I TestRc (NoMatch) Break | > # do the rest of the work | > + I Iconify False | > + I Raise | > + I WarpToWindow 80 5 | > | > However, this doesn't work if no such window actually exists; before | > anything from the function seems to execute (even an 'Echo' statement | | Context is about how functions run, and the way you have it there, FVWM will | need a window context to run in -- that is, a window to operate on. Your | use of "$0" implies this to some extent, in that you have a name or | something being passed in, but you don't say how. | | If FVWM doesn't have an operand window, then it will ask for one. This will | depend on how you're trying to call this function. This is perhaps the most | important piece of information you've failed to provide. Sorry, my lack of clarity. This is being invoked (more or less) as echo "Function ToWindow \"$win\"" | FvwmCommand -c (and for testing I have been just doing the 'Function ...' inside a FvwmConsole.) | > Do I need to make all commands conditional in this function in order | > to have things work right, by putting plain 'Current ' in front of the | > last three lines? (A version with this change seems to do nothing if | > there's no terminal window by that name, but I feel I'm just sort of | > writing code by superstition instead of actual understanding at this | > point.) | | No you don't. Consider this: | | AddToFunc ToWindow | + I Current ("XTerm|9term|Gnome-terminal", "$0") Break | + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus | + I TestRc (NoMatch) Break | + I Iconify False | + I Raise | + I WarpToWindow 80 5 [...] | It may well be that the window we're operating on is implied, | in which case FVWM won't ask for a window -- and indeed, your | implementation of ToWindow doesn't. FVWM processes the commands in | order, top-to-bottom. It comes across "Current" and evaluates that in | the context of the binding. Of course, there is nothing special about | Current, Next, or TestRc, they can run inside a function just fine, | and at this point assume no specific window -- but because you have | this: | | + I Iconify False | | ... if FVWM processes this from your ToWindow function and there is no | implied operand window for ToWindow to be running in, it will prompt | for a window to run against, because it needs a window. I guess my lack of understanding this: when I invoked ToWindow with Function ToWindow "nosuchwindow" I expected the 'Next' to fail and then the TestRc to succeed and abort the function before FVWM reached 'Iconify False' and needed a window to operate on. Instead nothing seems to be run at all before FVWM asks for a window -- I can put an unconditional 'Echo' in as the first + I in ToWindow, invoke 'Function ToWindow "nosuchwindow"', and if I then clicked on the root window, no Echo output showed up at all. (If I did select a window, things seemed to work as expected.) | Once you have a window you're hooked on it though. So really, establishing | a binding to one window can happen outside the function before invoking it, | and that's precisely what I did with my original suggestion to you above: | | DestroyFunc ToWindow | AddToFunc ToWindow | + I Current (State 1, $0) Break | + I Next (State 1, $0) SomeFunction | | DestroyFunc SomeFunction | AddToFunc SomeFunction | + I Iconify False | + I Focus | + I Raise | + I WarpToWindow 80 5 | | So can you not see now,
Re: FVWM: Trying to understand fvwm function execution
On Tue, Feb 07, 2012 at 07:42:01PM -0500, Chris Siebenmann wrote: > Yes, I think I understand. Calling 'Next ... SomeFunction' (or I assume > any successful conditional window selection command) sets the window > binding in effect for SomeFunction, and if Next cannot find such a > window it will not run SomeFunction at all. Do I have that right? Yes. -- Thomas Adam -- "Deep in my heart I wish I was wrong. But deep in my heart I know I am not." -- Morrissey ("Girl Least Likely To" -- off of Viva Hate.)