Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5de5b791bf | ||
|
|
c109408a98 | ||
|
|
90b2e0841f | ||
|
|
6621a49022 | ||
|
|
a2b88f247c | ||
|
|
684ca1b3cc | ||
|
|
524a836cc0 | ||
|
|
00c9cb0ee4 |
No files matched your search
+55
-1
@@ -1,10 +1,24 @@
|
|||||||
cmake_minimum_required(VERSION 3.24)
|
cmake_minimum_required(VERSION 3.24)
|
||||||
project(KSwitcher VERSION 0.6.38 LANGUAGES CXX RC)
|
project(KSwitcher VERSION 0.6.46 LANGUAGES CXX RC)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
message(FATAL_ERROR "KSwitcher uses native Windows APIs")
|
message(FATAL_ERROR "KSwitcher uses native Windows APIs")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
add_executable(StayHere WIN32 utilities/StayHere/main.cpp)
|
||||||
|
add_executable(StayHereTest WIN32 utilities/StayHere/main.cpp)
|
||||||
|
target_compile_definitions(StayHereTest PRIVATE STAYHERE_TEST_INSTANCE)
|
||||||
|
set_target_properties(StayHere PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tools")
|
||||||
|
foreach(utilityTarget StayHere StayHereTest)
|
||||||
|
target_compile_definitions(${utilityTarget} PRIVATE UNICODE _UNICODE _WIN32_WINNT=0x0A00)
|
||||||
|
target_link_libraries(${utilityTarget} PRIVATE user32 shell32 gdi32 wtsapi32)
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(${utilityTarget} PRIVATE /utf-8)
|
||||||
|
set_property(TARGET ${utilityTarget} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
else()
|
||||||
|
target_link_options(${utilityTarget} PRIVATE -municode -static -static-libgcc -static-libstdc++)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
add_library(kscore src/core.cpp src/platform.cpp src/autostart.cpp src/autocorrect.cpp src/storage.cpp src/ocr.cpp src/richtext.cpp src/update.cpp src/sync.cpp)
|
add_library(kscore src/core.cpp src/platform.cpp src/autostart.cpp src/autocorrect.cpp src/storage.cpp src/ocr.cpp src/richtext.cpp src/update.cpp src/sync.cpp)
|
||||||
target_include_directories(kscore PUBLIC src PRIVATE vendor)
|
target_include_directories(kscore PUBLIC src PRIVATE vendor)
|
||||||
target_compile_definitions(kscore PUBLIC UNICODE _UNICODE WIN32_LEAN_AND_MEAN NOMINMAX _WIN32_WINNT=0x0A00)
|
target_compile_definitions(kscore PUBLIC UNICODE _UNICODE WIN32_LEAN_AND_MEAN NOMINMAX _WIN32_WINNT=0x0A00)
|
||||||
@@ -30,6 +44,15 @@ target_link_libraries(KSwitcherScrollTests PRIVATE kscore)
|
|||||||
target_link_libraries(KSwitcherTests PRIVATE kscore)
|
target_link_libraries(KSwitcherTests PRIVATE kscore)
|
||||||
add_executable(KSwitcherIntegration tests/integration.cpp src/screenshot_launcher.cpp src/screenshot_activation.cpp src/app.cpp src/screenshot_notifications.cpp src/screenshot.cpp src/configuration.cpp src/ui.cpp resources/app.rc)
|
add_executable(KSwitcherIntegration tests/integration.cpp src/screenshot_launcher.cpp src/screenshot_activation.cpp src/app.cpp src/screenshot_notifications.cpp src/screenshot.cpp src/configuration.cpp src/ui.cpp resources/app.rc)
|
||||||
target_link_libraries(KSwitcherIntegration PRIVATE kscore)
|
target_link_libraries(KSwitcherIntegration PRIVATE kscore)
|
||||||
|
# Opt-in interactive fixture: requires an installed Far Manager.
|
||||||
|
add_executable(KSwitcherFarSnippetTests WIN32 tests/far_snippets.cpp src/screenshot_launcher.cpp src/screenshot_activation.cpp src/app.cpp src/screenshot_notifications.cpp src/screenshot.cpp src/configuration.cpp src/ui.cpp resources/app.rc)
|
||||||
|
target_link_libraries(KSwitcherFarSnippetTests PRIVATE kscore)
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(KSwitcherFarSnippetTests PRIVATE /utf-8)
|
||||||
|
set_property(TARGET KSwitcherFarSnippetTests PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
else()
|
||||||
|
target_link_options(KSwitcherFarSnippetTests PRIVATE -municode -static -static-libgcc -static-libstdc++)
|
||||||
|
endif()
|
||||||
add_executable(KSwitcherInputTests tests/input.cpp src/screenshot_launcher.cpp src/screenshot_activation.cpp src/app.cpp src/screenshot_notifications.cpp src/screenshot.cpp src/configuration.cpp src/ui.cpp resources/app.rc)
|
add_executable(KSwitcherInputTests tests/input.cpp src/screenshot_launcher.cpp src/screenshot_activation.cpp src/app.cpp src/screenshot_notifications.cpp src/screenshot.cpp src/configuration.cpp src/ui.cpp resources/app.rc)
|
||||||
target_link_libraries(KSwitcherInputTests PRIVATE kscore)
|
target_link_libraries(KSwitcherInputTests PRIVATE kscore)
|
||||||
target_compile_definitions(KSwitcherInputTests PRIVATE KS_SCREENSHOT_RESOURCES)
|
target_compile_definitions(KSwitcherInputTests PRIVATE KS_SCREENSHOT_RESOURCES)
|
||||||
@@ -66,6 +89,29 @@ else()
|
|||||||
target_link_options(KSwitcherOcrTests PRIVATE -static -static-libgcc -static-libstdc++)
|
target_link_options(KSwitcherOcrTests PRIVATE -static -static-libgcc -static-libstdc++)
|
||||||
endif()
|
endif()
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
add_executable(KSwitcherHistoryHostTests tests/history_host.cpp)
|
||||||
|
target_link_libraries(KSwitcherHistoryHostTests PRIVATE kscore psapi)
|
||||||
|
set_target_properties(KSwitcherHistoryHostTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/history-host-fixture-$<CONFIG>")
|
||||||
|
add_dependencies(KSwitcherHistoryHostTests KSwitcher KSwitcherScreenshot)
|
||||||
|
add_custom_command(TARGET KSwitcherHistoryHostTests POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:KSwitcher>" "$<TARGET_FILE_DIR:KSwitcherHistoryHostTests>/KSwitcher.exe"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:KSwitcherScreenshot>" "$<TARGET_FILE_DIR:KSwitcherHistoryHostTests>/KSwitcher.Screenshot.exe"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E touch "$<TARGET_FILE_DIR:KSwitcherHistoryHostTests>/.local-dev")
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(KSwitcherHistoryHostTests PRIVATE /utf-8)
|
||||||
|
set_property(TARGET KSwitcherHistoryHostTests PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
else()
|
||||||
|
target_link_options(KSwitcherHistoryHostTests PRIVATE -static -static-libgcc -static-libstdc++)
|
||||||
|
endif()
|
||||||
|
add_executable(KSwitcherClipboardSnapshotTests tests/clipboard_snapshot.cpp)
|
||||||
|
target_link_libraries(KSwitcherClipboardSnapshotTests PRIVATE kscore psapi)
|
||||||
|
add_dependencies(KSwitcherClipboardSnapshotTests KSwitcherScreenshot)
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(KSwitcherClipboardSnapshotTests PRIVATE /utf-8)
|
||||||
|
set_property(TARGET KSwitcherClipboardSnapshotTests PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
else()
|
||||||
|
target_link_options(KSwitcherClipboardSnapshotTests PRIVATE -static -static-libgcc -static-libstdc++)
|
||||||
|
endif()
|
||||||
add_executable(KSwitcherImageCaptureTests tests/image_capture.cpp)
|
add_executable(KSwitcherImageCaptureTests tests/image_capture.cpp)
|
||||||
target_link_libraries(KSwitcherImageCaptureTests PRIVATE kscore)
|
target_link_libraries(KSwitcherImageCaptureTests PRIVATE kscore)
|
||||||
add_dependencies(KSwitcherImageCaptureTests KSwitcherScreenshot)
|
add_dependencies(KSwitcherImageCaptureTests KSwitcherScreenshot)
|
||||||
@@ -88,6 +134,14 @@ add_test(NAME dictionary-regressions COMMAND KSwitcherDictionaryTests)
|
|||||||
set_tests_properties(dictionary-regressions PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
set_tests_properties(dictionary-regressions PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
add_test(NAME sync-regressions COMMAND KSwitcherSyncTests)
|
add_test(NAME sync-regressions COMMAND KSwitcherSyncTests)
|
||||||
add_test(NAME native-regressions COMMAND KSwitcherTests)
|
add_test(NAME native-regressions COMMAND KSwitcherTests)
|
||||||
|
add_executable(KSwitcherUtilitiesTests tests/utilities.cpp)
|
||||||
|
if(MSVC)
|
||||||
|
set_property(TARGET KSwitcherUtilitiesTests PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
else()
|
||||||
|
target_link_options(KSwitcherUtilitiesTests PRIVATE -static -static-libgcc -static-libstdc++)
|
||||||
|
endif()
|
||||||
|
add_test(NAME utilities-regressions COMMAND KSwitcherUtilitiesTests)
|
||||||
|
add_test(NAME stayhere-lifecycle COMMAND powershell -NoProfile -ExecutionPolicy Bypass -File "${CMAKE_CURRENT_SOURCE_DIR}/tests/stayhere.ps1" -Executable "$<TARGET_FILE:StayHereTest>")
|
||||||
add_test(NAME scroll-regressions COMMAND KSwitcherScrollTests)
|
add_test(NAME scroll-regressions COMMAND KSwitcherScrollTests)
|
||||||
add_test(NAME input-regressions COMMAND KSwitcherInputTests)
|
add_test(NAME input-regressions COMMAND KSwitcherInputTests)
|
||||||
add_test(NAME screenshot-ui-regressions COMMAND KSwitcherScreenshotUITests)
|
add_test(NAME screenshot-ui-regressions COMMAND KSwitcherScreenshotUITests)
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ Ctrl+Alt+Delete and Win+L; these cannot be assigned.
|
|||||||
|
|
||||||
Keyboard and mouse input forwarded by Microsoft Mouse Without Borders follows the same input
|
Keyboard and mouse input forwarded by Microsoft Mouse Without Borders follows the same input
|
||||||
path as a local keyboard/mouse, including shortcuts, recent-word conversion and snippets.
|
path as a local keyboard/mouse, including shortcuts, recent-word conversion and snippets.
|
||||||
|
On the sending computer, KSwitcher ignores keyboard events consumed by another keyboard hook
|
||||||
|
(including Mouse Without Borders forwarding). The receiving computer still processes delivered
|
||||||
|
input normally, so both computers can run KSwitcher without starting duplicate snippet operations.
|
||||||
KSwitcher marks its own generated input so copy/paste, selection, modifier releases and shell-mask
|
KSwitcher marks its own generated input so copy/paste, selection, modifier releases and shell-mask
|
||||||
keys cannot trigger recursive commands or overwrite the recorded typing run. Other injected input
|
keys cannot trigger recursive commands or overwrite the recorded typing run. Other injected input
|
||||||
is accepted, including key-up events and VK-only keyboard events. Unicode packets do not provide
|
is accepted, including key-up events and VK-only keyboard events. Unicode packets do not provide
|
||||||
@@ -274,10 +277,24 @@ thumbnails and source labels aligned with the scaled fonts and spacing.
|
|||||||
of the complete expected text. Browser/editor compatibility depends on its handling of simulated input.
|
of the complete expected text. Browser/editor compatibility depends on its handling of simulated input.
|
||||||
- Selection conversion and verified recent input (physical scan codes, 2-second typing-run boundary).
|
- Selection conversion and verified recent input (physical scan codes, 2-second typing-run boundary).
|
||||||
- Same-process clipboard ownership plus verified WebView2 descendants, including the Teams fix.
|
- Same-process clipboard ownership plus verified WebView2 descendants, including the Teams fix.
|
||||||
|
Clipboard synchronizers such as Mouse Without Borders may republish a copy only when
|
||||||
|
KSwitcher first observed it owned by the target application and the selection text and
|
||||||
|
editor selection metadata remain identical. Unobserved or altered foreign copies are rejected.
|
||||||
|
Snippets normally require accessibility verification of their selected trigger and pasted text,
|
||||||
|
even with logging disabled. If verification is unavailable or the paste differs, expansion
|
||||||
|
stops without running cursor or Enter actions. Clipboard changes during paste also cancel actions.
|
||||||
|
Far Manager uses its native Alt+Shift+Arrow selection, Ctrl+Insert copy and Shift+Insert
|
||||||
|
paste commands instead: both the trigger and inserted text must match verified clipboard
|
||||||
|
copies from Far. Cancellation restores the full temporary selection, not one cursor step.
|
||||||
|
Far supports nonempty single-line replacements up to 4096 caret steps, including
|
||||||
|
`{cursor}` and verified `{enter}` actions. Empty or multiline replacements are rejected
|
||||||
|
before selection; pasting a newline could execute a command before it can be verified.
|
||||||
- Teams recent-word conversion uses a single word-selection command and validates the copied range.
|
- Teams recent-word conversion uses a single word-selection command and validates the copied range.
|
||||||
If the editor's word boundary differs from the recorded typing, it falls back to paced character
|
If the editor's word boundary differs from the recorded typing, it falls back to paced character
|
||||||
selection: Teams can coalesce a burst of Shift+Left events into just one character.
|
selection: Teams can coalesce a burst of Shift+Left events into just one character.
|
||||||
- Clipboard snapshot/restoration with concurrent-copy, foreground and input-version checks.
|
- Clipboard snapshot/restoration with concurrent-copy, foreground and input-version checks.
|
||||||
|
A snapshot interrupted by a concurrent clipboard publication is retried up to three total
|
||||||
|
attempts before selection starts, provided the foreground and input context remain unchanged.
|
||||||
A silently dropped copy is retried up to three total attempts while the clipboard and input
|
A silently dropped copy is retried up to three total attempts while the clipboard and input
|
||||||
context remain unchanged. Temporary transaction contents are excluded from Windows clipboard
|
context remain unchanged. Temporary transaction contents are excluded from Windows clipboard
|
||||||
history and cloud synchronization. Paste is not blindly retried: with manual paste readback
|
history and cloud synchronization. Paste is not blindly retried: with manual paste readback
|
||||||
@@ -525,6 +542,30 @@ OpenBao administrator setup:
|
|||||||
and UI integration, so another service can be added without replacing the synchronization logic.
|
and UI integration, so another service can be added without replacing the synchronization logic.
|
||||||
Protocol and conflict regressions run with `build.ps1 -Test` or CMake's `sync-regressions` test.
|
Protocol and conflict regressions run with `build.ps1 -Test` or CMake's `sync-regressions` test.
|
||||||
|
|
||||||
|
## Portable utilities
|
||||||
|
|
||||||
|
The tray menu's **Utilities** submenu lists `.exe` files in a `tools` folder beside
|
||||||
|
`KSwitcher.exe`, sorted by filename. For example, place `StayHere.exe` at
|
||||||
|
`tools/StayHere.exe` and choose **Utilities → StayHere** to launch it manually.
|
||||||
|
The folder is rescanned whenever the menu opens; no configuration or restart is needed.
|
||||||
|
Only files directly in `tools` are listed (not subfolders, shortcuts, or KSwitcher's
|
||||||
|
own executables beside the main program). Utilities start with `tools` as their working
|
||||||
|
directory and are never started automatically. Their lifetime is independent of KSwitcher.
|
||||||
|
An absent or empty folder displays a disabled placeholder; launch errors are reported.
|
||||||
|
From v0.6.45, the release includes `tools/README.txt`, so extracting the ZIP or
|
||||||
|
installing an update creates the folder. Add your own trusted portable executables;
|
||||||
|
StayHere is bundled from v0.6.46, and settings synchronization does not transfer
|
||||||
|
utility files. Updates preserve personal utilities and refresh bundled StayHere and
|
||||||
|
documentation. Repository development scripts
|
||||||
|
are not included in the portable tools folder.
|
||||||
|
|
||||||
|
Choose **Utilities → StayHere** to start the bundled activity utility. It starts
|
||||||
|
enabled; left-click its tray icon to pause/resume or right-click for Exit. While
|
||||||
|
enabled it prevents automatic sleep and, after three minutes without input, sends
|
||||||
|
F15 on its 15-second check. It does not move the mouse, bypass locking, start with
|
||||||
|
KSwitcher automatically, or directly control Teams status. Locked/disconnected
|
||||||
|
sessions do not receive simulated activity. See `tools/StayHere-README.md`.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
The easiest reproducible local route uses the pinned portable w64devkit toolchain:
|
The easiest reproducible local route uses the pinned portable w64devkit toolchain:
|
||||||
@@ -648,6 +689,7 @@ Run `./package.ps1 -PublishRelease` after building and testing to refresh the tr
|
|||||||
.\build.ps1 -Test # Pure/native regression checks; does not touch the user's clipboard
|
.\build.ps1 -Test # Pure/native regression checks; does not touch the user's clipboard
|
||||||
.\build.ps1 -Ocr # Render a synthetic image, decode it with WIC and recognize it with Windows OCR
|
.\build.ps1 -Ocr # Render a synthetic image, decode it with WIC and recognize it with Windows OCR
|
||||||
.\build.ps1 -Integration # Interactive, isolated test editor; avoid input for about 10 seconds
|
.\build.ps1 -Integration # Interactive, isolated test editor; avoid input for about 10 seconds
|
||||||
|
.\build.ps1 -Far # Explicit integration test using an isolated Far Manager profile
|
||||||
.\tests\configuration.ps1 # Separate-process settings tests; close KSwitcher first
|
.\tests\configuration.ps1 # Separate-process settings tests; close KSwitcher first
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -720,8 +762,14 @@ Consecutive duplicates use SHA-256 fingerprints inside the encrypted history ind
|
|||||||
|
|
||||||
Moving OCR isolates its temporary memory rather than reducing the combined processing peak. A controlled three-run comparison retained about 0.8 MiB less private RAM in the caller after recognition; combined peak RAM was about 55.6 MiB before and 56.6 MiB with the helper. Results depend on the image, OCR engine and system.
|
Moving OCR isolates its temporary memory rather than reducing the combined processing peak. A controlled three-run comparison retained about 0.8 MiB less private RAM in the caller after recognition; combined peak RAM was about 55.6 MiB before and 56.6 MiB with the helper. Results depend on the image, OCR engine and system.
|
||||||
|
|
||||||
### History previews and Escape — v0.6.38
|
### Pinned history checkbox — v0.6.42
|
||||||
|
|
||||||
History initializes RichEdit only for HTML/RTF previews. Plain text keeps Unicode and line breaks without RTF conversion; empty history and image-only previews do not load RichEdit unnecessarily. Plain and formatted text previews share the existing bounded text-preview cache.
|
Check **★ Pinned only** beside the history search box to show only pinned entries; uncheck it to show all entries. The checkbox sits on the left, immediately followed by the search box; its right edge stays aligned with the history list when resizing. The text search applies within that filter. Unpinning an item removes it from the pinned view immediately. The checkbox state and search are remembered after closing and reopening history. **Clear history…** still deletes the entire history after confirmation, including entries hidden by the filter.
|
||||||
|
|
||||||
Esc clears hidden rows/caches and cancels obsolete queued preview work, while retaining the selected/top entry for reopening. Already-needed RichEdit controls are cleared and reused. Clipboard contents, paste formatting, OCR, settings and shortcuts are unchanged. A local isolated comparison saved approximately 0.48–0.72 MiB private working set after Esc depending on content; this is not a fixed application footprint or a guarantee that all UI memory returns to the startup level.
|
### History process and clipboard memory — v0.6.40
|
||||||
|
|
||||||
|
History opens in a separate, short-lived instance of **KSwitcher.exe**. **Esc** closes it even when focus is on the window or an action button, releasing Windows UI allocations with the process. The resident keeps keyboard hooks, clipboard capture and history storage. Search and the pinned-only filter are preserved in encrypted view state. Each fresh opening selects and reveals the newest matching entry; background refreshes preserve the selected record while browsing. If a full-text item viewer is still open, the helper stays alive until the last viewer closes. Pin/delete, formatted/plain paste and OCR remain available; settings and default shortcuts are unchanged.
|
||||||
|
|
||||||
|
Image thumbnails are decoded in **KSwitcher.Screenshot.exe**, returning only bounded preview pixels. Image clipboard backup/restore also uses that helper and encrypted temporary files, with clipboard-sequence checks before restoring. Selection reads avoid loading image formats. Keep all three executables together; no fourth executable is required. Paste allows a brief foreground handoff after history closes while preserving cancellation checks. UI Automation remains in the resident.
|
||||||
|
|
||||||
|
A live development-build test measured **4.37 MiB before history and 4.35 MiB after two open/Esc cycles**, compared with an earlier roughly 8–9 MiB plateau. A same-image clipboard-backup benchmark retained **12.78 MiB before versus 0.05 MiB after**. These measure private working set, not a guaranteed total footprint. Include all helpers when measuring active use: combined memory can be higher while history is open. No forced working-set trimming is used. Existing screenshots and shortcuts remain applicable. The v0.6.38 approach of retaining a hidden history window/RichEdit control is superseded by process termination.
|
||||||
Binary file not shown.
+9
-10
@@ -1,22 +1,21 @@
|
|||||||
# Latest Windows release
|
# Latest Windows release
|
||||||
|
|
||||||
## v0.6.38 — 2026-11-04
|
## v0.6.46 — 2026-11-05
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
- Clipboard history loads RichEdit only when an HTML/RTF preview actually needs it. Empty history, plain text and image-only previews no longer initialize it unnecessarily.
|
- Bundle **tools/StayHere.exe** and **tools/StayHere-README.md**. Start the activity utility from **Utilities → StayHere**; it does not start automatically with KSwitcher.
|
||||||
- Plain text previews retain Unicode and line breaks without converting the text to RTF. Plain and formatted preview payloads share the existing bounded text-preview cache.
|
- StayHere starts enabled. Left-click its tray icon to pause/resume or right-click for Exit. While enabled, it prevents automatic display/system sleep and checks inactivity every 15 seconds; after three minutes without input it sends F15. It does not move the mouse, bypass locking, install autostart or directly control Teams presence. Locked/disconnected sessions receive no simulated activity.
|
||||||
- Esc still clears hidden history rows and preview caches while preserving the remembered selection/top item. Closing or replacing a search now cancels obsolete preview work before loading/decoding where possible, and discards completed stale results.
|
- Include StayHere source and reproducible GCC/CMake builds. CLI status/pause/resume/exit parsing tolerates launcher whitespace. Normal updates replace bundled StayHere and documentation while preserving personal utilities. A running old instance continues until exited; relaunch to use the updated executable.
|
||||||
- A RichEdit control that was needed for formatted text is cleared and reused, not repeatedly destroyed/recreated. This avoids additional initialization on reopening. Settings, shortcuts, stored clipboard contents, formatting on paste and OCR behavior are unchanged.
|
- Retain all v0.6.45 Far snippet, Utilities and tools-folder changes and the v0.6.44 newest-history-selection fix.
|
||||||
|
- Correct the Far test fixture's working directory: a long temporary path could scroll the command line and invalidate absolute cursor-coordinate assertions. Application snippet behavior is unchanged in this release.
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
Staged build and tests cover dictionary equivalence for 140,939 words, 105 sync checks, wheel batching, 315 native checks, 561 input checks, screenshot UI/PNG/notification registration, 48 updater checks and updater progress UI. Added checks for plain previews without RichEdit, retained HTML rendering, lazy control creation and cleanup through Esc. Isolated real-window tests also verified formatted previews after reopening.
|
Passed isolated StayHere start/status/pause/resume/exit checks, Utilities regressions, dictionary equivalence (140,939 words), 105 sync checks, shared wheel tests, 319 native checks, 574 input checks, screenshot UI/save/registration, 54 updater checks and updater progress UI. The updater replaced a running isolated StayHere executable successfully. Final package manifests and downloaded assets are checked before completion. Real-Far spot checks confirmed expansion, caret placement and markers; the uninterrupted full interactive run remains outstanding because unrelated foreground changes cancel it. No additional Far application-code change is shipped in v0.6.46.
|
||||||
|
|
||||||
A controlled local comparison measured 0.72 MiB less private working set after Esc for empty history, 0.66 MiB for plain text, 0.48 MiB for formatted text and 0.53 MiB for images. These are isolated test-process comparisons, not the application's total RAM or a guaranteed reduction on another computer. The reported 7 MiB plateau on a different laptop was not reproduced. No working-set trimming was used; closing the history window does not promise an exact return to startup memory.
|
|
||||||
|
|
||||||
## Upgrade
|
## Upgrade
|
||||||
Choose **Update** in the tray menu. Legacy v0.3.0–v0.4.1 clients first receive the v0.4.2 compatibility bridge, then the current full release. v0.2.3 and earlier require manual installation.
|
Choose **Update** in the tray menu. Legacy v0.3.0–v0.4.1 clients first receive the v0.4.2 compatibility bridge, then the current full release. v0.2.3 and earlier require manual installation.
|
||||||
For manual installation, exit KSwitcher, close screenshot editors and extract the entire ZIP into its installation folder. Keep personal `data/` and customized dictionaries.
|
For manual installation, exit KSwitcher, close its configurator and screenshot editors, and extract the entire ZIP into its installation folder. Keep personal `data/`, customized dictionaries and your own tools. Find `tools/StayHere.exe` beside the executable actually running.
|
||||||
|
|
||||||
Download **KSwitcher-win-x64.zip** with **SHA256SUMS.txt**. Keep all three executables together. The package contains no personal settings, credentials or clipboard history.
|
Download **KSwitcher-win-x64.zip** with **SHA256SUMS.txt**. Keep the three KSwitcher executables together; history uses another instance of KSwitcher.exe. StayHere runs independently. The package contains no personal settings, credentials or clipboard history.
|
||||||
|
|
||||||
Publish stable `release-vX.Y.Z` tags matching the executable version. Keep `v0.4.2` as the last legacy tag.
|
Publish stable `release-vX.Y.Z` tags matching the executable version. Keep `v0.4.2` as the last legacy tag.
|
||||||
@@ -1 +1 @@
|
|||||||
f430767d440581018e6adb33c153fb332318fa1eee5a162ddf32690d0b5a3391 KSwitcher-win-x64.zip
|
e6d26d59b18559ad226359b35cd403c68326384f8e1918d31b368cbd1110f6b9 KSwitcher-win-x64.zip
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
param([switch]$Test, [switch]$Integration, [switch]$Ocr, [switch]$Stage)
|
param([switch]$Test, [switch]$Integration, [switch]$Ocr, [switch]$Stage, [switch]$Far)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
$root = $PSScriptRoot
|
$root = $PSScriptRoot
|
||||||
$compiler = Join-Path $root '.tools\w64devkit\bin\g++.exe'
|
$compiler = Join-Path $root '.tools\w64devkit\bin\g++.exe'
|
||||||
@@ -16,6 +16,12 @@ Push-Loca | |||||||