Skip to content

Update v1.1.0: Drag to Delete - #7324

Merged
m417z merged 1 commit into
ramensoftware:mainfrom
iMAboud:main
Nov 13, 2026
Merged

m417z merged 1 commit into
ramensoftware:mainfrom
iMAboud:main

Conversation

@iMAboud

@iMAboud iMAboud commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Mod authorship

This mod was created by:

    • The submitter, without AI assistance
    • The submitter, with AI assistance
    • Claude
    • ChatGPT
    • Gemini
    • Another AI (please specify):
    • Other (please specify):

Changelog

  • Placement modes: Added Follow cursor, Nearby, and Top.
  • Ctrl+Z undo: Added native Shell undo via IFileOperation.
  • System icon option: Added sharp native Windows Recycle Bin icon.
  • Optional shadow: Added toggleable ShowShadow setting.
  • Distance auto-hide: Target fades out when dragging far away.
  • Fullscreen Z-order fix: Stays visible over fullscreen background windows.
  • Search drag support: Recycles Everything & Power Tools search items.
  • Desktop Shell items: Added support for CFSTR_SHELLIDLIST desktop selections.
  • Virtual item filtering: Safely ignores non-filesystem virtual items.
  • Dynamic monitor DPI: Automatically updates scaling across different monitors.

@windhawk-reviewer windhawk-reviewer Bot added the waiting-for-author The author's turn: request an AI review, or respond to one that was posted. label Nov 12, 2026
@windhawk-reviewer

Copy link
Copy Markdown

Thanks for the pull request! This repository uses a two-stage review: an AI review that you run yourself, followed by a human review.

To get started, comment /ai-review. Once you're happy with the result, comment /ready-for-reviewer to hand it over to a human reviewer.

See the pull request review process for the full details.

@iMAboud

iMAboud commented Nov 12, 2026

Copy link
Copy Markdown
Contributor Author

/ai-review

@windhawk-reviewer windhawk-reviewer Bot added waiting-for-ai-review An AI review was requested and is being prepared. and removed waiting-for-author The author's turn: request an AI review, or respond to one that was posted. labels Nov 12, 2026
@windhawk-reviewer

Copy link
Copy Markdown

Submission review

Note: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding.

Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it.

Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them.


No blocking issues — looks good to merge. Moving the overlay and the deletion worker into the desktop-shell explorer.exe and having the other Explorer processes only hook DoDragDrop and post to it is a sound design. The worker thread's COM init/uninit is paired on that thread, and both threads are joined in Wh_ModUninit.

Optional improvements

Minor polish — none of this affects users, so it's your call.

  • README is out of date. The README (lines 12–20) still has a single sentence. It doesn't mention the placement modes, the auto-hide, the icon options or Ctrl+Z undo. If the GIF shows the original top-of-screen target, it no longer matches the new default (follow). A short feature list and a note on the new default would help users who update.
  • Placement math is written three times. The offset, edge-flip and clamp logic is repeated in WM_UPDATE_DRAG_STATE (lines 931–959), FollowCursor (lines 771–787) and RepositionFollowTargetAfterAutoHide (lines 809–823), with small differences: the first one clamps with ifs and skips Y clamping in top mode, the other two use std::clamp. One helper like POINT ComputeTargetOrigin(POINT cursor) would keep the three in sync. You could also parse Placement / IconSource into enums in ReadSettings, so the 25 ms timer path doesn't compare std::wstrings on every tick.
  • Small redundancies. At lines 982–984, SetWindowPos(hWnd, HWND_TOPMOST, …) is immediately followed by RestoreDragOverlayZOrder(hWnd, true), which with force makes the same SetWindowPos(HWND_TOPMOST) call again. Also, #include <windows.h> (line 70) isn't needed, because Windhawk already includes it ahead of the mod.

Functionality notes

Non-critical observations and ideas about the feature behavior itself.

  • Default behavior changes for existing users. Placement defaults to follow (lines 24, 116), so everyone updating from 1.0.0 gets a moving target instead of the top-of-screen one, unless they change the setting. The changelog only says the modes were "added". If the change is intended, consider saying so in the changelog/README. Otherwise, keep top as the default.
  • Delete confirmation and dialog ownership. v1.0.0 passed FOF_NOCONFIRMATION, and the new flags (lines 649–650) don't. Recycling now follows the user's "Display delete confirmation dialog" Recycle Bin setting. That's arguably correct, but please confirm it's intentional. No IFileOperation::SetOwnerWindow is called, so that confirmation, the nuke warning and error dialogs open unowned from the worker thread and can end up behind the Explorer window. Also, the undo record is added in the shell process, so it's worth checking that Ctrl+Z works from a folder window running in a separate process ("Launch folder windows in a separate process").
  • Overlay can get stuck visible. The overlay now lives in another process than most drag sources. If the source process exits mid-drag, or the mod is unloaded from it during a drag, the "drag ended" message (lines 1147–1153) is never posted. The overlay then stays visible, with the 25 ms timer running, until the next drag. A cheap watchdog in the WM_TIMER handler would cover this: start the hide animation when neither mouse button has been down for a few ticks (GetAsyncKeyState).
  • Follow mode near screen corners. When the cursor reaches a corner, both offsets can flip (lines 779–780), and the target then glides along a path that passes through the cursor (38% of the remaining distance per tick). FollowCursor stops moving once the target is within the capture radius (lines 767–768), and with the default distances that can leave the target under the cursor, so a release meant for whatever is under it would recycle the files instead. Worth testing near the top-right corner, e.g. by letting the target move around the cursor instead of through it.
  • Start Everything copy-only drags. Start Everything's search window starts its drags with DROPEFFECT_COPY only (start-everything.wh.cpp). The mod accepts COPY in that case and recycles the originals (lines 497–504). IsStartEverythingSearchDrag also matches when that window is just the foreground window (line 483), so a copy-only drag started from somewhere else while it's in the foreground would be recycled too. Checking only the window under the cursor at drag start would limit it to drags that really come from the search window.
  • Z-order re-raise. Every ~150 ms during a drag (lines 998–1001), the target re-raises itself above any overlapping topmost window. That can fight with other topmost windows, such as a video player or another overlay. It's only during drags, so this is just an FYI.
  • System icon after a DPI change. g_hRecycleIcon is rendered at the drag-start monitor's DPI (line 968). If the target follows the cursor onto a monitor with a different DPI, the icon is stretched by DrawIconEx.

Code overview

For the maintainer: a map of the mod and what it touches outside its own process. Descriptive only — anything that needs a change is listed above. Line numbers refer to the mod source at commit 677b6f3. 🟢 added / 🟡 updated / ⚪ unchanged, compared to the currently merged version.

Code regions

  • 🟡 Line 1–10: metadata — version bump, adds -luuid
  • ⚪ Line 12–20: README (one sentence + GIF)
  • 🟢 Line 22–68: settings block — placement mode, shadow, icon source/size, distances, auto-hide distance, top margin (with #!-marked 2.0 annotations)
  • 🟡 Line 70–147: includes, layout constants (window now 140×140), global state; adds settings struct, follow/auto-hide state, cached icon
  • 🟢 Line 149–177: ReadSettings — reads and validates/clamps all settings
  • ⚪ Line 179–209: GetCurrentModuleHandle, GetMonitorDpi (dynamic GetDpiForMonitor)
  • 🟢 Line 211–260: IsDesktopDragStart (window-class walk under the cursor), GetSharpRecycleBinIcon (Recycle Bin icon via IShellItemImageFactory, stock icon fallback)
  • 🟡 Line 262–393: drawing — DrawModernTrashIcon, RenderFrame (drawn glass or system icon, optional shadow, auto-hide opacity via UpdateLayeredWindow)
  • 🟢 Line 395–504: drag data helpers — HasFileDragFormat (CF_HDROP or all-filesystem shell ID list), ExtractDragPaths, IsStartEverythingSearchDrag, AllowedRecycleEffect
  • 🟡 Line 506–607: CRecycleDropTarget — hit test against the moving origin; Drop queues the paths for the deletion worker
  • 🟡 Line 611–708: MoveFilesToRecycleBin (now IFileOperation with undo record) and DeleteWorkerThread (STA, pumps messages, drains the queue on stop)
  • 🟢 Line 710–902: z-order restore, follow-cursor movement, auto-hide fade/hide/restore logic
  • 🟡 Line 904–1042: OverlayWndProc — drag start computes placement and shows the overlay; drag end starts the hide animation; 25 ms animation timer
  • 🟡 Line 1044–1120: OverlayUIThread — OLE/GDI+ init, window class + overlay window, RegisterDragDrop, message loop, teardown incl. UnregisterClassW
  • 🟡 Line 1122–1156: DoDragDrop hook — classifies the drag source and posts start/end to the overlay found by class name
  • 🟢 Line 1158–1175: IsDesktopShellHostProcess (shell-window owner, command-line fallback), FindSharedRecycleOverlay
  • 🟡 Line 1177–1225: Wh_ModInit — non-shell Explorer processes only install the DoDragDrop hook; the shell process also starts the deletion worker and overlay UI thread
  • 🟢 Line 1227–1230: Wh_ModSettingsChanged — always requests a reload
  • 🟡 Line 1232–1262: Wh_ModUninit — shell process only: joins the UI thread, then the deletion worker, closes handles

Side effects of interest

  • 🟡 Line 611–659: external file write: recycles the dropped files/folders (IFileOperation::DeleteItems with FOFX_RECYCLEONDELETE | FOFX_ADDUNDORECORD, may permanently delete when an item can't be recycled, after the nuke warning) on the deletion worker thread after each accepted drop. These are the user's own files and this is the mod's feature.
  • 🟡 Line 1138–1141, 1149–1152: IPC: every explorer.exe process looks up WindhawkDragToDeleteOverlay with FindWindowW and posts WM_USER+101 (with desktop/search flags in wParam) to the overlay in the desktop-shell explorer.exe, at the start and end of each file drag (inside the DoDragDrop hook).
  • ⚪ Line 1089–1093: IPC: RegisterDragDrop on the overlay window accepts OLE drops from other processes (Explorer windows in separate processes). The data object is queried in DragEnter/Drop.


Next steps:

  • /ai-review - after pushing fixes, to get a review of the updated code. You can repeat this as many times as you need, but each review is thorough and usually there's no need for more than 2-3 iterations.
  • /ready-for-reviewer - once you're satisfied with the state of the pull request, to hand it over to a human reviewer. If some findings above are left unaddressed, add a short note explaining why.

See the review process for details.

Important: Each reply that was generated by AI must be disclosed by including the following text in the reply: "Generated by AI. Model: (ai-model-name)".

@windhawk-reviewer windhawk-reviewer Bot added waiting-for-author The author's turn: request an AI review, or respond to one that was posted. and removed waiting-for-ai-review An AI review was requested and is being prepared. labels Nov 12, 2026
@iMAboud

iMAboud commented Nov 12, 2026

Copy link
Copy Markdown
Contributor Author

/ready-for-reviewer

@windhawk-reviewer windhawk-reviewer Bot added waiting-for-reviewer Ready for a human reviewer, and in the queue for one. and removed waiting-for-author The author's turn: request an AI review, or respond to one that was posted. labels Nov 12, 2026
@m417z
m417z merged commit 65feabc into ramensoftware:main Nov 13, 2026
5 checks passed
@windhawk-reviewer windhawk-reviewer Bot removed the waiting-for-reviewer Ready for a human reviewer, and in the queue for one. label Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants