Compare commits

..
1 Commits
Author SHA1 Message Date
agrynco c0defcbfb2 Release KSwitcher v0.6.66 with tray icon retry 2026-11-12 09:16:38 +02:00
9 changed files with 60 additions and 31 deletions

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.24)
project(KSwitcher VERSION 0.6.65 LANGUAGES CXX RC)
project(KSwitcher VERSION 0.6.66 LANGUAGES CXX RC)
if(NOT WIN32)
message(FATAL_ERROR "KSwitcher uses native Windows APIs")
endif()
Binary file not shown.
+12
View File
@@ -1,5 +1,17 @@
# Latest Windows release
## v0.6.66 — 2026-11-12
If Windows rejects registration of the notification-area icon at sign-in or
after Explorer restarts, KSwitcher retries about once a second until the
icon is registered. Settings become accessible from the icon without
restarting KSwitcher.
**Українською.** Якщо Windows не приймає значок KSwitcher в області
сповіщень під час входу або після перезапуску Провідника, KSwitcher
повторює спробу приблизно щосекунди. Коли значок з’явиться, з нього
можна відкрити налаштування без перезапуску KSwitcher.
## v0.6.65 — 2026-11-12
Use **Settings → Mouse → +** beside **Mouse events** to capture and name a
+1 -1
View File
@@ -1 +1 @@
e60ca342737155dce14a2bb1dd43ec1cef890cf7d9e5efb2e15a5b9629eaf1af KSwitcher-win-x64.zip
fbe11ca4f73acbe97169215c155729dc41a713253c6b7026286430f9bb6f2f34 KSwitcher-win-x64.zip
+24 -24
View File
@@ -1,86 +1,86 @@
{
"files": [
{
"sha256": "2b01c6458fbbf0372e5a1ab6ca1fb8ad6dbb743753f7fe306dfecb2061fc6bf1",
"size": 2190336,
"sha256": "9d268cbb00fb9db3e52bc68994cefb50cee707f9dc1b940d876314ba1b6a06b3",
"path": "KSwitcher.exe"
},
{
"sha256": "22104dfd456b008002eb0d54e6d20d11a86699c9688de1eede6e4a04fc63aa66",
"size": 2129408,
"sha256": "d83fad30539e7b974bb8012859f3fee8143c5e4cc25684643b16e2fc34b97a5e",
"path": "KSwitcher.Config.exe"
},
{
"sha256": "a4df0707e2476d8b1e46debf751c89c7dc76bd36c0935803fdb9542a5a811b12",
"size": 3210240,
"sha256": "29f7846ee4d3c469779b66acf99c90a4173e1e1577020398d6e1dc4eae492e06",
"path": "KSwitcher.Screenshot.exe"
},
{
"size": 4401,
"sha256": "d3c81140cce01c26bf6cbf52aa40e0825e1fa35b9a91d1387170a65d2597082c",
"size": 4401,
"path": "LICENSE"
},
{
"size": 1075,
"sha256": "c0d068392ea65358b798b8c165103560f06e9e3b38c4ab4e2d8810a7b931af86",
"sha256": "61e08da79c44061654015ce6b0c4061c23ee1dd18237fbf09e9bfda3c0ea2831",
"size": 1096,
"path": "json-LICENSE.txt"
},
{
"size": 90358,
"sha256": "435daae289ca64dd9130ed772125de3f3303f1dbb80d1cbf7a9913058ded47ec",
"size": 90358,
"path": "README.md"
},
{
"size": 9900,
"sha256": "6dcb0efabec6898965bbbd31ba68e06276fd0f098ac9a8649bc1f7d7de21d63e",
"size": 9900,
"path": "LAN-PREVIEW.md"
},
{
"size": 682867,
"sha256": "5f267c141c3d6837870e1c098f86b89a113ba300343119432644ead88f720c21",
"sha256": "d0c022b27b9fbc2ff7b6b8bec723cc1adc4eef517202f9ff77eed5d8bea3acb9",
"size": 732485,
"path": "dictionaries/en.txt"
},
{
"size": 20138,
"sha256": "28a9529c7d0bb4dc51f4bf5c116a3d16ef247a052f7591466768ddf563fd1cf5",
"sha256": "0bdfb0201d1803634f268cdff0993b8349d2c70e956a06dbb667c8dd65254ec5",
"size": 20566,
"path": "dictionaries/LICENSE-CC-BY-SA-4.0.txt"
},
{
"size": 2230,
"sha256": "2df17fe4e17d527c67ab57269b07dce59a49c1fb128c429a1408decbb47109ec",
"sha256": "3017bf44d3be9d9dfab21bd6778aa52b7947e61acf9ce2bc86b41d6e949ac311",
"size": 2265,
"path": "dictionaries/README.md"
},
{
"size": 1060364,
"sha256": "9ef922c7699569304a428f6aba0fd13a21341c0d0cb9561f37ef83c41577a28b",
"sha256": "80e6b6a27815973535f7facb636c597eb845dfee45cfabfc4e9b3341b9332849",
"size": 1109134,
"path": "dictionaries/ru.txt"
},
{
"size": 1279,
"sha256": "d6e11a3aaba22a8a7eaba19f778d8a5bd66653ff306810e85a1b0e7fff3a6b86",
"sha256": "98e5b3fe7304e37705c9e5ff48b0b399ccb16e806736d21f09921b99e5f2a408",
"size": 1280,
"path": "dictionaries/sources.json"
},
{
"size": 898248,
"sha256": "caeb097749d4afc84b68ad96b3d7dfb6a6569561cd32ccce0bee94a13b43ba86",
"sha256": "d30e990d6ec2983c04f3644a3c61c6c668e8c542323f5931916fdd55b916eebf",
"size": 940799,
"path": "dictionaries/uk.txt"
},
{
"size": 993,
"sha256": "a34b5161a8315af037e1ec71d816bfc688f7c364141d4ee2347cf0515ef0c82a",
"size": 993,
"path": "tools/README.txt"
},
{
"size": 134656,
"sha256": "6ef5cf64708d62b7fc63c3c793cc99188a513433ff4774cae01dc014f6664376",
"size": 134656,
"path": "tools/StayHere.exe"
},
{
"size": 2796,
"sha256": "ba214e2aca7405e698b3ab21ceb1f41ce088edd996b3e30e4a9d58ff496f9413",
"size": 2796,
"path": "tools/StayHere-README.md"
}
],
"version": "0.6.65",
"version": "0.6.66",
"schema": 1
}
+3 -3
View File
@@ -9,8 +9,8 @@ IDC_SCREENSHOT_PENCIL CURSOR "icons/lucide/pencil.cur"
1 RT_MANIFEST "app.manifest"
201 RCDATA "update.ps1"
1 VERSIONINFO
FILEVERSION 0,6,65,0
PRODUCTVERSION 0,6,65,0
FILEVERSION 0,6,66,0
PRODUCTVERSION 0,6,66,0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
BEGIN
@@ -20,7 +20,7 @@ BEGIN
BEGIN
VALUE "FileDescription", "KSwitcher — native keyboard and clipboard utility"
VALUE "ProductName", "KSwitcher"
VALUE "FileVersion", "0.6.65"
VALUE "FileVersion", "0.6.66"
END
END
BLOCK "VarFileInfo"
+17 -1
View File
@@ -690,6 +690,9 @@ void App::report(const std::wstring &text)
log(text);
PostMessageW(window, ErrorMessage, 0, (LPARAM) new std::wstring(text));
}
constexpr UINT_PTR TrayRetryTimer = 20;
constexpr UINT TrayRetryIntervalMs = 1000;
void App::addTray()
{
NOTIFYICONDATAW icon{sizeof(icon)};
@@ -700,7 +703,15 @@ void App::addTray()
icon.hIcon = (HICON)LoadImageW(instance, MAKEINTRESOURCEW(IDI_KSWITCHER), IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
wcscpy_s(icon.szTip, localBuildTitle(L"KSwitcher — keyboard layouts & clipboard").c_str());
Shell_NotifyIconW(NIM_ADD, &icon);
if (Shell_NotifyIconW(NIM_ADD, &icon))
{
KillTimer(window, TrayRetryTimer);
trayRetryPending = false;
}
else if (!trayRetryPending)
{
trayRetryPending = SetTimer(window, TrayRetryTimer, TrayRetryIntervalMs, nullptr) != 0;
}
icon.uVersion = NOTIFYICON_VERSION_4;
Shell_NotifyIconW(NIM_SETVERSION, &icon);
}
@@ -2637,6 +2648,11 @@ LRESULT CALLBACK App::windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
if(app->lanService&&app->lanService->tickInput(!app->busy&&!app->suspended&&!app->hotkeyCapture))app->resetLanInput();
return 0;
case WM_TIMER:
if (wp == TrayRetryTimer)
{
if (app->trayRetryPending) app->addTray();
return 0;
}
if (wp == MouseClickTimer) { app->flushMouseClicks(); return 0; }
if (wp >= FirstMouseVolumeTimer && wp < FirstMouseVolumeTimer + std::size(MouseButtonNames))
{
+1
View File
@@ -158,6 +158,7 @@ class App
bool (*updateNotifier)(const std::wstring &){};
bool stop{};
UINT taskbarCreated{};
bool trayRetryPending{};
uint64_t transformAttempt{}, previousAttemptVersion{};
ULONGLONG previousAttemptAt{};
HWND previousAttemptWindow{};
+1 -1
View File
@@ -2,7 +2,7 @@
#include "platform.h"
namespace ks
{
inline constexpr wchar_t AppVersion[] = L"0.6.65";
inline constexpr wchar_t AppVersion[] = L"0.6.66";
inline constexpr UINT UpdateMessage = WM_APP + 7;
inline constexpr UINT UpdateCheckIntervalMs = 6 * 60 * 60 * 1000;
inline constexpr UINT UpdateNotificationRetryMs = 5 * 60 * 1000;