Hi, recently I did some Fvwm (version 2.4.6) hacking concerning the maintenance of the window order. The basic idea is: always keep the windowlist in most recently focused order. This is already the case if you only use the mouse and the FlipFocus command for focusing. But it is nice to have a command to cycle through the windows. Something like:
Key F11 A M Next (*) Focus Note that we can also make up functions that don't cycle through all windows, but only through a certain subset. E. g. all xterms, all Netscape windows and so on. See the description of AddToFunc in the Fvwm man page for an example. This doesn't work with FlipFocus, but the Focus command spoils the most-recently-focused order of the windowlist. Ideally, the wm should know when we cycled to a window that we want focused, and move it to the start of the list, in contrast to the windows we only had to 'cycle over' to get there. The solution I came up with: use a timeout. If a window is focused longer then a certain amount of time, consider it 'definitely focused' and put it to the front of the windowlist. The FvwmAuto module is an obvious solution for this task. To make this work, I had to do the following changes to Fvwm: 1. The focusing command must have these effects: Mouse and FlipFocus: put window to front of windowlist OK, it works already like this. Focus: don't alter the internal windowlist at all This was not the case, instead the newly focused window was rotated to front of the list. I eliminated this rotation (in function DoSetFocus in focus.c). This doesn't seem to have any bad effects (The displayed windowlist starts with the focused window anyway). 2. I invented a new command "ReshuffleWindows". It puts the window to the front of the internal window list, just as FlipFocus does. In contrast to FlipFocus it works on already focused windows. Now I can write into .fvwm2rc: Module FvwmAuto 2500 "Silent Current (*) ReshuffleWindows" and I can use a key combination to cycle through the windows (via a "Next [...] Focus" command) without altering the window order. Only when I stay at a window for more than 2.5 seconds it becomes No. 1 in the window list. Attached, please, find the patch. It affects the files focus.c, command.h, functions.c and functions.h. Any comments are welcome. I'm not a Fvwm hacking expert, so I hope I haven't screwed anything up. Feel free to use the code anyway you like. Another idea: if we use MouseFocus (I don't), shouldn't we apply the same strategy ? I. e., if we touch a window only briefly, it is not placed at the top of the windowlist. But those are just some thoughts for future develpments. By the way, I also made a somewhat related, but independent patch for the display of the windowlist. I'll put that into a separate mail. Best regards Jochen
diff -u -x *.o -x fvwm2 -x windowlist.c ../fvwm-2.4.6/fvwm/commands.h fvwm/commands.h --- ../fvwm-2.4.6/fvwm/commands.h Wed Mar 6 19:24:03 2002 +++ fvwm/commands.h Tue Mar 12 20:01:47 2002 @@ -133,6 +133,7 @@ void CMD_Refresh(F_CMD_ARGS); void CMD_RefreshWindow(F_CMD_ARGS); void CMD_Repeat(F_CMD_ARGS); +void CMD_ReshuffleWindows(F_CMD_ARGS); void CMD_Resize(F_CMD_ARGS); void CMD_ResizeMove(F_CMD_ARGS); void CMD_Restart(F_CMD_ARGS); diff -u -x *.o -x fvwm2 -x windowlist.c ../fvwm-2.4.6/fvwm/focus.c fvwm/focus.c --- ../fvwm-2.4.6/fvwm/focus.c Tue Jan 1 16:16:15 2002 +++ fvwm/focus.c Tue Mar 12 22:15:38 2002 @@ -58,6 +58,28 @@ !(tmp_win->wmhints->flags & InputHint) || tmp_win->wmhints->input); } +/***************************************************************** + * + * Puts the window to the start of the windowlist. + * + *****************************************************************/ +static void Reshuffle_windows(FvwmWindow *Fw) { + /* Watch out: Fw may not be on the windowlist and the windowlist may be + * empty */ + /* remove Fw from list */ + if (Fw->prev) + Fw->prev->next = Fw->next; + if (Fw->next) + Fw->next->prev = Fw->prev; + + /* insert Fw at start */ + Fw->next = Scr.FvwmRoot.next; + if (Scr.FvwmRoot.next) + Scr.FvwmRoot.next->prev = Fw; + Scr.FvwmRoot.next = Fw; + Fw->prev = &Scr.FvwmRoot; +} + /******************************************************************** * * Sets the input focus to the indicated window. @@ -94,51 +116,11 @@ } /* ClickToFocus focus queue manipulation - only performed for * Focus-by-mouse type focus events */ - /* Watch out: Fw may not be on the windowlist and the windowlist may be - * empty */ if (Fw && Fw != get_focus_window() && Fw != &Scr.FvwmRoot) { if (FocusByMouse) /* pluck window from list and deposit at top */ { - /* remove Fw from list */ - if (Fw->prev) - Fw->prev->next = Fw->next; - if (Fw->next) - Fw->next->prev = Fw->prev; - - /* insert Fw at start */ - Fw->next = Scr.FvwmRoot.next; - if (Scr.FvwmRoot.next) - Scr.FvwmRoot.next->prev = Fw; - Scr.FvwmRoot.next = Fw; - Fw->prev = &Scr.FvwmRoot; - } - else - { - /* move the windowlist around so that Fw is at the top */ - FvwmWindow *tmp_win; - - /* find the window on the windowlist */ - tmp_win = &Scr.FvwmRoot; - while (tmp_win && tmp_win != Fw) - tmp_win = tmp_win->next; - - if (tmp_win) /* the window is on the (non-zero length) windowlist */ - { - /* make tmp_win point to the last window on the list */ - while (tmp_win->next) - tmp_win = tmp_win->next; - - /* close the ends of the windowlist */ - tmp_win->next = Scr.FvwmRoot.next; - Scr.FvwmRoot.next->prev = tmp_win; - - /* make Fw the new start of the list */ - Scr.FvwmRoot.next = Fw; - /* open the closed loop windowlist */ - Fw->prev->next = NULL; - Fw->prev = &Scr.FvwmRoot; - } + Reshuffle_windows(Fw); } } lastFocusType = FocusByMouse; @@ -554,6 +536,14 @@ return; FocusOn(tmp_win, FALSE, action); +} + +void CMD_ReshuffleWindows(F_CMD_ARGS) +{ + if (DeferExecution(eventp,&w,&tmp_win,&context,CRS_SELECT,ButtonRelease)) + return; + + Reshuffle_windows(tmp_win); } void CMD_WarpToWindow(F_CMD_ARGS) diff -u -x *.o -x fvwm2 -x windowlist.c ../fvwm-2.4.6/fvwm/functions.c fvwm/functions.c --- ../fvwm-2.4.6/fvwm/functions.c Wed Mar 6 19:24:03 2002 +++ fvwm/functions.c Tue Mar 12 20:01:45 2002 @@ -208,6 +208,8 @@ CMD_ENTRY("refresh", CMD_Refresh, F_REFRESH, 0), CMD_ENTRY("refreshwindow", CMD_RefreshWindow, F_REFRESH, FUNC_NEEDS_WINDOW), CMD_ENTRY(PRE_REPEAT, CMD_Repeat, F_REPEAT, FUNC_DONT_REPEAT), + CMD_ENTRY("reshufflewindows", CMD_ReshuffleWindows, F_RESHUFFLE_WINDOWS, + FUNC_NEEDS_WINDOW), CMD_ENTRY("resize", CMD_Resize, F_RESIZE, FUNC_NEEDS_WINDOW), CMD_ENTRY("resizemove", CMD_ResizeMove, F_RESIZEMOVE, FUNC_NEEDS_WINDOW), CMD_ENTRY("restart", CMD_Restart, F_RESTART, 0), diff -u -x *.o -x fvwm2 -x windowlist.c ../fvwm-2.4.6/fvwm/functions.h fvwm/functions.h --- ../fvwm-2.4.6/fvwm/functions.h Wed Mar 6 19:24:03 2002 +++ fvwm/functions.h Tue Mar 12 20:01:44 2002 @@ -217,6 +217,7 @@ F_PLACEAGAIN, F_RAISE, F_RAISELOWER, + F_RESHUFFLE_WINDOWS, F_RESIZE, F_RESIZEMOVE, F_SEND_STRING,