diff --git a/CMakeLists.txt b/CMakeLists.txt index d292c2b..5ab6fa3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.24) -project(KSwitcher VERSION 0.6.33 LANGUAGES CXX RC) +project(KSwitcher VERSION 0.6.34 LANGUAGES CXX RC) if(NOT WIN32) message(FATAL_ERROR "KSwitcher uses native Windows APIs") endif() diff --git a/README.md b/README.md index c0a3876..f3e3c34 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,9 @@ Every shape has a round rotation handle above its outline. Drag it to rotate aro hold **Shift** for 15-degree steps. The handle works for toolbar shapes and recognized shapes, including triangles. Resize handles and attached connectors follow the rotation; Ctrl+Z/Ctrl+Y undo and redo it. The square handle still controls outline thickness. +From v0.6.34, endpoint, shape-corner and number-radius handles show the four-direction move cursor. +Thickness handles retain directional resize cursors; rotation retains the hand cursor. Dragging, +snapping and shape constraints are unchanged. **Triangle (G)** is also available directly on the toolbar: drag to create a triangle. Both drawn and recognized triangles have three independent vertex handles instead of bounding-box resize handles. Drag any vertex to reshape the triangle while keeping the other two fixed, even diff --git a/Release/KSwitcher-win-x64.zip b/Release/KSwitcher-win-x64.zip index aca50f2..185d15d 100644 Binary files a/Release/KSwitcher-win-x64.zip and b/Release/KSwitcher-win-x64.zip differ diff --git a/Release/README.md b/Release/README.md index 9911709..9c3d821 100644 --- a/Release/README.md +++ b/Release/README.md @@ -1,16 +1,14 @@ # Latest Windows release -## v0.6.33 — 2026-11-04 +## v0.6.34 — 2026-11-04 ## Changes -- Settings now detects unsaved changes when closing with the window close button, Alt+F4 or Cancel, including accepted auto-correction dictionary and OCR option edits. -- Choose Yes to save, apply and close; No to discard; or Cancel to keep editing (the default). Unchanged or reverted settings close without a prompt. Invalid edits can be discarded, and a failed save keeps the window and draft open. -- Tray and clipboard-history menus now show access letters in the right-hand column, including submenu items. Press the letter without Alt; Alt dismisses an open menu. Existing shortcut hints are preserved. -- Dialog access-key behavior is unchanged: use Alt+letter, with underline visibility following Windows preferences. Windows-wide preferences and global shortcut assignments are unchanged. -- OK in Auto-correction/OCR options still updates the Settings draft; Save or Yes in the close prompt applies it. Snippets and Sync retain their separate save flows. +- Screenshot editing now uses the four-direction move cursor for both endpoints of lines/arrows, bounding-box shape handles and number-radius handles. The cursor no longer suggests that a horizontal or vertical line endpoint is restricted to one axis. +- Object bodies, arrow labels and triangle vertices continue to use the same four-direction cursor. Thickness handles retain directional resize cursors perpendicular to the line; rotation handles retain the hand cursor. +- This changes cursor feedback only. Dragging, snapping, circle proportions, undo/redo, shortcuts, defaults and dialog access-key behavior are unchanged. The v0.6.33 unsaved-settings warning and visible menu access letters remain included. ## Validation -The full `build.ps1 -Stage -Test` run passed: 105 sync checks, shared wheel batching, 483 native regressions, 551 input/UI checks at 96 DPI, screenshot editor UI checks, PNG saving, isolated screenshot registration, 48 updater regressions and updater progress UI checks. All three executable versions and all 12 package manifest file sizes/SHA-256 hashes were verified. New regressions cover unchanged/reverted settings, cancelling closure, discarding invalid edits, saving and applying edits, personal dictionary changes, and visible menu hints including submenus and existing shortcut labels. +The full `build.ps1 -Stage -Test` run passed: 105 sync checks, shared wheel batching, 483 native regressions, 551 input/UI checks at 96 DPI, screenshot editor UI checks (including free-movement cursor feedback across drawing tools and horizontal/vertical thickness cursors), PNG saving, isolated screenshot registration, 48 updater regressions and updater progress UI checks. All three executable versions and all 12 package manifest file sizes/SHA-256 hashes were verified; the package contains no personal data. ## 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. diff --git a/Release/SHA256SUMS.txt b/Release/SHA256SUMS.txt index de147d5..3ae5d31 100644 --- a/Release/SHA256SUMS.txt +++ b/Release/SHA256SUMS.txt @@ -1 +1 @@ -e46d1f6d52aeb58cf96c74db64bd450bc5b828e0a5111673c19a6657fca1d214 KSwitcher-win-x64.zip +c7f004ecd9d0f1032356060191ca3ca9fca458df434d3e5908c5d9b038f95acc KSwitcher-win-x64.zip diff --git a/resources/app.rc b/resources/app.rc index 8381180..4f29ffb 100644 --- a/resources/app.rc +++ b/resources/app.rc @@ -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,33,0 - PRODUCTVERSION 0,6,33,0 + FILEVERSION 0,6,34,0 + PRODUCTVERSION 0,6,34,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.33" + VALUE "FileVersion", "0.6.34" END END BLOCK "VarFileInfo" diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 5a8129c..466a0f2 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -783,12 +783,13 @@ HCURSOR actionCursor(const Capture &c,std::pair hit,bool inside) if(hit.second==MarkPart::Body || hit.second==MarkPart::Label) cursor=IDC_SIZEALL; else if(hit.second==MarkPart::Rotation) cursor=IDC_HAND; else if(hit.second>=MarkPart::Vertex0 && hit.second<=MarkPart::Vertex2) cursor=IDC_SIZEALL; - else if(hit.second==MarkPart::Radius) cursor=IDC_SIZEWE; - else if(hit.second==MarkPart::Start || hit.second==MarkPart::End || hit.second==MarkPart::Thickness) { + else if(hit.second==MarkPart::Start || hit.second==MarkPart::End || hit.second==MarkPart::Radius) + cursor=IDC_SIZEALL; + else if(hit.second==MarkPart::Thickness) { const auto &mark=c.marks[hit.first]; - auto [from,to]=hit.second==MarkPart::Thickness?thicknessSegment(mark):std::pair{mark.from,mark.to}; + auto [from,to]=thicknessSegment(mark); double angle=std::atan2(double(to.y-from.y),double(to.x-from.x)); - if(hit.second==MarkPart::Thickness) angle+=3.141592653589793/2; + angle+=3.141592653589793/2; int axis=(int(std::lround(angle/(3.141592653589793/4)))+8)%4; const LPCWSTR cursors[]{IDC_SIZEWE,IDC_SIZENWSE,IDC_SIZENS,IDC_SIZENESW}; cursor=cursors[axis]; diff --git a/src/update.h b/src/update.h index 8a48a32..8e5fb7b 100644 --- a/src/update.h +++ b/src/update.h @@ -2,7 +2,7 @@ #include "platform.h" namespace ks { -inline constexpr wchar_t AppVersion[] = L"0.6.33"; +inline constexpr wchar_t AppVersion[] = L"0.6.34"; inline constexpr UINT UpdateMessage = WM_APP + 7; inline constexpr UINT UpdateCheckIntervalMs = 6 * 60 * 60 * 1000; inline constexpr UINT UpdateNotificationRetryMs = 5 * 60 * 1000; diff --git a/tests/screenshot_ui.cpp b/tests/screenshot_ui.cpp index 4ecd15a..cb4f4aa 100644 --- a/tests/screenshot_ui.cpp +++ b/tests/screenshot_ui.cpp @@ -454,8 +454,16 @@ int main(int argc, char **argv) c.marks={{{20,20},{120,20},0}}; require(ks::actionCursor(c,{0,ks::MarkPart::Body},true)==LoadCursorW(nullptr,IDC_SIZEALL),"move cursor overrides drawing tool"); require(ks::actionCursor(c,{0,ks::MarkPart::Rotation},true)==LoadCursorW(nullptr,IDC_HAND),"rotation cursor overrides drawing tool"); - require(ks::actionCursor(c,{0,ks::MarkPart::End},true)==LoadCursorW(nullptr,IDC_SIZEWE),"endpoint resize overrides drawing tool"); + for(auto part:{ks::MarkPart::Start,ks::MarkPart::End,ks::MarkPart::Radius, + ks::MarkPart::Label,ks::MarkPart::Vertex0,ks::MarkPart::Vertex1,ks::MarkPart::Vertex2}) + require(ks::actionCursor(c,{0,part},true)==LoadCursorW(nullptr,IDC_SIZEALL), + "freely movable handles use four-direction cursor for every drawing tool"); require(ks::actionCursor(c,{0,ks::MarkPart::Thickness},true)==LoadCursorW(nullptr,IDC_SIZENS),"thickness resize is perpendicular to line"); + c.marks[0].to={20,120}; + require(ks::actionCursor(c,{0,ks::MarkPart::End},true)==LoadCursorW(nullptr,IDC_SIZEALL), + "vertical line endpoint still moves in both axes"); + require(ks::actionCursor(c,{0,ks::MarkPart::Thickness},true)==LoadCursorW(nullptr,IDC_SIZEWE), + "vertical line thickness retains horizontal resize cursor"); } c.marks.clear(); SendMessageW(window,WM_COMMAND,27,0); wchar_t windowTitle[128]{}; GetWindowTextW(window,windowTitle,128);