Skip to content

Releases: directvt/vtm

v2025.11.07

07 Nov 19:52
21382bd

Choose a tag to compare

GitHub all current

Changes

v2025.10.31

31 Oct 18:50
8d8e157

Choose a tag to compare

GitHub all current

Changes

  • Fix background fill color artifacts in VT2D mode.

v2025.10.29

29 Oct 12:13
a1876e9

Choose a tag to compare

GitHub all current

Changes

  • Improve the accuracy of timer timeouts on input.

v2025.10.28

28 Oct 22:06
2c7d8e2

Choose a tag to compare

GitHub all current

Changes

  • Fix idle spinning on zero timer. #838

v2025.10.27

27 Oct 17:56
f3c0827

Choose a tag to compare

GitHub all current

Changes

  • Fix dtty session closing (dtvt over ssh).
  • Fix console size synchronization on startup.

v2025.10.25

25 Oct 12:46
3fd24bd

Choose a tag to compare

GitHub all current

Changes

  • Make window event subscriptions persistent as the applet moves between windows, the tile manager, etc.
    Example from the previous release:
    <config>
        <events>
            <window>
                <script on="preview: e2::form::upon::changed">
                    local vx, vy, vw, vh = vtm.gate.GetViewport(); 
                    local wx, wy, ww, wh = vtm.applet.GetArea(); 
                    local t, b = vtm.applet.GetTitlesHeight();
                    local centrify_and_colorize = '\\x1b[11:3p\\x1b[97;40m';
                    local varea = ' viewport: coor={ '..vx..', '..vy..' } size={ '..vw..', '..vh..' } ';
                    local warea = ' window: coor={ '..wx..', '..wy..' } size={ '..ww..', '..wh..' } ';
                    local titles = ' title height: '..t..' footer height: '..b..' ';
                    vtm.gate.SetOverlay(1, centrify_and_colorize..varea..'\\n'..warea..'\\n'..titles);
                    vtm.gate.Deface();
                </script>
            </window>
        </events>
    </config>

v2025.10.24

24 Oct 13:14
ddb0854

Choose a tag to compare

GitHub all current

Changes

  • Fix xml reference name resolution.
  • Introduce vtm.gate.GetViewport(), vtm.applet.GetArea(), vtm.applet.GetTitlesHeight() and the window event source.
    <config>
        <events>
            <applet>
                <script>
                    <WindowSource source="window"/>
                    <on="Ctrl+A"|WindowSource />
                    <on="preview: e2::form::upon::changed"|WindowSource />
                    local vx, vy, vw, vh = vtm.gate.GetViewport(); 
                    local wx, wy, ww, wh = vtm.applet.GetArea(); 
                    local t, b = vtm.applet.GetTitlesHeight();
                    local centrify_and_colorize = '\\x1b[11:3p\\x1b[97;40m';
                    local varea = ' viewport: coor={ '..vx..', '..vy..' } size={ '..vw..', '..vh..' } ';
                    local warea = ' window: coor={ '..wx..', '..wy..' } size={ '..ww..', '..wh..' } ';
                    local titles = ' title height: '..t..' footer height: '..b..' ';
                    vtm.gate.SetOverlay(1, centrify_and_colorize..varea..'\\n'..warea..'\\n'..titles);
                    vtm.gate.Deface();
                </script>
            </applet>
        </events>
    </config>

v2025.10.21

21 Oct 10:30
386e3e9

Choose a tag to compare

GitHub all current

Changes

  • Sandbox the Lua environment by removing the os, io, package, and debug Lua libs.
  • Introduce vtm.gear.GetCoord() (getting the current mouse pointer coords).

v2025.10.20

20 Oct 15:32
153e144

Choose a tag to compare

GitHub all current

Changes

  • Introduce visual overlays for Lua script output.
    <script="vtm.desktop.SetOverlay(0, 'desk_fg');" on="..."/> <!-- Set foreground visual overlay for all connected users. -->
    <script="vtm.desktop.SetOverlay(-1, '\t\tdesk_bg');" on="..."/> <!-- Set background (index<0) visual overlay for all connected users. -->
    <script="vtm.gate.SetOverlay(0, 'e[42mgate_fg');" on="..."/> <!-- Set foreground visual overlay for current user. -->
    <script="vtm.gate.SetOverlay(-1, '\t\t\e[44mgate_bg');" on="..."/> <!-- Set background (index<0) visual overlay for current user. -->
    <script="vtm.desktop.SetOverlay(0, '');" on="..."/> <!-- Remove (due to empty string) foreground visual overlay for all connected users. -->
  • With the kbmodifier active, draw a visual red 'B' mark near the right side of the viewport (example in architecture.md).
     <desktop>
       <SetMark="vtm.gate.SetOverlay(0, kbmodifier[vtm.gate] and '\\n\e[11:2p\e[41mB' or ''); vtm.gate.Deface();"/> <!-- `SetMark` macro. If the kbmodifier is active, draw a visual red "B" mark near the right side of the viewport. -->
       <script="kbmodifier[vtm.gate] = not kbmodifier[vtm.gate];" | SetMark  on="Ctrl+B"/> <!-- Emulate tmux-like prefix key. Store the mode state value in the `kbmodifier` table using a unique vtm.gate (user's console) value for each user. -->
       ...
     </desktop>
    image

v2025.10.19

19 Oct 11:42
479293f

Choose a tag to compare

GitHub all current

Changes

  • Make tmux-like prefix emulation multi-user aware (example in architecture.md).

    Keyboard hacking

    It is possible to emulate the tmux-like keyboard prefix approach by using a global variable in the Lua-scripting runspace. As an example, the following configuration adds the keyboard shortcut Ctrl+B as a toggle for an additional keyboard mode (coupled with a user-defined variable named kbmodifier - a table of Boolean values ​​unique to each connected user: kbmodifier[vtm.gear]) that allows windows to be moved directly using the arrow keys:

    • ~/.config/vtm/settings.xml:
      <config>
          <events>
              <gate>
                  <script="if kbmodifier == nil then kbmodifier = {}; end;" on="release: e2::form::upon::started"/> <!-- Initialize `kbmodifier` table if it is not initialized. -->
              </gate>
              <desktop>
                  <script="kbmodifier[vtm.gear] = not kbmodifier[vtm.gear]; log('kbmodifier[', vtm.gear, ']=', kbmodifier[vtm.gear]);" on="Ctrl+B"/> <!-- Emulate tmux-like prefix key. Store the mode state value in the `kbmodifier` table using a unique vtm.gear (keyboard/mouse device) value for each user. The expression `log(...);` is for debugging purposes only (the output is visible in the `Log Monitor`). -->
                  <script="" on="Alt+Z"        /> <!-- Unbind existing FocusTaskbar binding.    -->
                  <script="" on="Ctrl+PageUp"  /> <!-- Unbind existing FocusPrevWindow binding. -->
                  <script="" on="Ctrl+PageDown"/> <!-- Unbind existing FocusNextWindow binding. -->
              </desktop>
              <applet> <!-- Key bindings for the application window. -->
                  <KeyFilter=prerun prerun="if (not kbmodifier[vtm.gear] and vtm.gear.Bypass()) then return; end; "/> <!-- `KeyFilter` macro. Do nothing if `kbmodifier[vtm.gear]` is false. Calling vtm.gear.Bypass() always returns true. -->
                  <script=KeyFilter | MoveAppletLeft         on="LeftArrow"                                  /> <!-- The ` | ` operator concatenates script fragments/macros. If for some reason the keyboard event is not processed by anyone, it will then return and fire on this object, so the KeyFilter's script is also reused at the beginning of the `script="..."`. -->
                  <script=KeyFilter | MoveAppletRight        on="RightArrow"                                 /> <!-- The `prerun` attribute (inherited from KeyFilter) contains a Lua script that will be executed during pre-polling to filter out key events. -->
                  <script=KeyFilter | MoveAppletUp           on="UpArrow"                                    /> <!-- When `kbmodifier[vtm.gear]` is true, you can move windows using the arrow keys. -->
                  <script=KeyFilter | MoveAppletDown         on="DownArrow"                                  /> <!-- Macros like `MoveApplet...` are defined in the default configuration. You can list them with `vtm -l`. -->
                  <script=KeyFilter | MoveAppletTopLeft      on="LeftArrow+UpArrow    | UpArrow+LeftArrow"   /> <!-- Simultaneous key presses should also be processed if supported. -->
                  <script=KeyFilter | MoveAppletBottomLeft   on="LeftArrow+DownArrow  | DownArrow+LeftArrow" /> <!-- It is convenient to specify multiple keyboard shortcuts in one definition separated by `|`. -->
                  <script=KeyFilter | MoveAppletTopRight     on="RightArrow+UpArrow   | UpArrow+RightArrow"  />
                  <script=KeyFilter | MoveAppletBottomRight  on="RightArrow+DownArrow | DownArrow+RightArrow"/>
                  <script=KeyFilter | IncreaseAppletWidth    on="Ctrl+RightArrow"                            />
                  <script=KeyFilter | DecreaseAppletWidth    on="Ctrl+LeftArrow"                             />
                  <script=KeyFilter | IncreaseAppletHeight   on="Ctrl+DownArrow"                             />
                  <script=KeyFilter | DecreaseAppletHeight   on="Ctrl+UpArrow"                               />
                  <script=KeyFilter | FocusPrevWindow        on="PageUp"                                     />
                  <script=KeyFilter | FocusNextWindow        on="PageDown"                                   />
                  <script=KeyFilter | FocusTaskbar           on="preview: -Esc"                              /> <!-- Focus taskbar on Esc unpress. The `on="Esc"` combination is busy in bindings like `"Esc+..."`. -->
              </applet>
          </events>
      </config>