fix snapping

This commit is contained in:
KingKDot
2026-07-12 14:30:34 -05:00
parent 24a20ed3f9
commit 1d2b50b333
2 changed files with 57 additions and 32 deletions
@@ -75,8 +75,13 @@ const (
GW_HWNDPREV = 3 GW_HWNDPREV = 3
PW_RENDERFULLCONTENT = 0x00000002 PW_RENDERFULLCONTENT = 0x00000002
STARTF_USESIZE = 0x00000002
STARTF_USEPOSITION = 0x00000004 STARTF_USEPOSITION = 0x00000004
CREATE_NEW_CONSOLE = 0x00000010 CREATE_NEW_CONSOLE = 0x00000010
SWP_NOSIZE = 0x0001
SWP_NOZORDER = 0x0004
SWP_NOACTIVATE = 0x0010
SWP_SHOWWINDOW = 0x0040
MOUSEEVENTF_MOVE = 0x0001 MOUSEEVENTF_MOVE = 0x0001
MOUSEEVENTF_LEFTDOWN = 0x0002 MOUSEEVENTF_LEFTDOWN = 0x0002
MOUSEEVENTF_LEFTUP = 0x0004 MOUSEEVENTF_LEFTUP = 0x0004
@@ -31,21 +31,21 @@ var (
virtualInitialized bool virtualInitialized bool
virtualMu sync.Mutex virtualMu sync.Mutex
virtualCursorEnabled bool virtualCursorEnabled bool
virtualInputMu sync.Mutex virtualInputMu sync.Mutex
virtualLastCursor point virtualLastCursor point
virtualHasCursor bool virtualHasCursor bool
virtualWorkingWindow uintptr virtualWorkingWindow uintptr
virtualShiftDown bool virtualShiftDown bool
virtualCtrlDown bool virtualCtrlDown bool
virtualAltDown bool virtualAltDown bool
virtualCapsLock bool virtualCapsLock bool
virtualMovingWindow bool virtualMovingWindow bool
virtualMoveOffset point virtualMoveOffset point
virtualWindowSize point virtualWindowSize point
virtualWindowToMove uintptr virtualWindowToMove uintptr
virtualMouseButtons uint32 virtualMouseButtons uint32
virtualLastScale atomic.Uint64 virtualLastScale atomic.Uint64
virtualResizingWindow uintptr virtualResizingWindow uintptr
virtualResizeHit int32 virtualResizeHit int32
virtualResizeStart point virtualResizeStart point
@@ -716,7 +716,9 @@ func StartVirtualProcess(filePath string) (uint32, error) {
si.cb = uint32(unsafe.Sizeof(si)) si.cb = uint32(unsafe.Sizeof(si))
si.dwX = uint32(bounds.Min.X) si.dwX = uint32(bounds.Min.X)
si.dwY = uint32(bounds.Min.Y) si.dwY = uint32(bounds.Min.Y)
si.dwFlags = STARTF_USEPOSITION si.dwXSize = uint32(bounds.Dx())
si.dwYSize = uint32(bounds.Dy())
si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE
creationFlags := uintptr(0) creationFlags := uintptr(0)
if virtualCommandNeedsNewConsole(filePath) { if virtualCommandNeedsNewConsole(filePath) {
// Console hosts only consistently honor STARTF_USEPOSITION when Windows // Console hosts only consistently honor STARTF_USEPOSITION when Windows
@@ -782,31 +784,25 @@ func virtualTopLevelWindowSet() map[uintptr]struct{} {
result := make(map[uintptr]struct{}) result := make(map[uintptr]struct{})
deskHwnd, _, _ := procGetDesktopWindow.Call() deskHwnd, _, _ := procGetDesktopWindow.Call()
for hwnd := getTopWindow(deskHwnd); hwnd != 0; hwnd = getWindow(hwnd, GW_HWNDNEXT) { for hwnd := getTopWindow(deskHwnd); hwnd != 0; hwnd = getWindow(hwnd, GW_HWNDNEXT) {
if isWindowVisible(hwnd) { result[hwnd] = struct{}{}
result[hwnd] = struct{}{}
}
} }
return result return result
} }
func moveProcessWindowsToVirtualMonitor(pid uint32, bounds image.Rectangle, baseline map[uintptr]struct{}) { func moveProcessWindowsToVirtualMonitor(pid uint32, bounds image.Rectangle, baseline map[uintptr]struct{}) {
hwndMap := make(map[uintptr]uint32) hwndMap := make(map[uintptr]bool)
for attempt := 0; attempt < 75; attempt++ {
time.Sleep(200 * time.Millisecond)
for attempt := 0; attempt < 300; attempt++ {
deskHwnd, _, _ := procGetDesktopWindow.Call() deskHwnd, _, _ := procGetDesktopWindow.Call()
hwnd := getTopWindow(deskHwnd) hwnd := getTopWindow(deskHwnd)
if hwnd == 0 { if hwnd == 0 {
time.Sleep(virtualPlacementPollDelay(attempt))
continue continue
} }
moved := 0 moved := 0
for hwnd != 0 { for hwnd != 0 {
if !isWindowVisible(hwnd) { visible := isWindowVisible(hwnd)
hwnd = getWindow(hwnd, GW_HWNDNEXT)
continue
}
var winPID uint32 var winPID uint32
procGetWindowThreadProcessId.Call(hwnd, uintptr(unsafe.Pointer(&winPID))) procGetWindowThreadProcessId.Call(hwnd, uintptr(unsafe.Pointer(&winPID)))
@@ -816,11 +812,10 @@ func moveProcessWindowsToVirtualMonitor(pid uint32, bounds image.Rectangle, base
continue continue
} }
if _, already := hwndMap[hwnd]; already { if alreadyVisibleMove, already := hwndMap[hwnd]; already && (!visible || alreadyVisibleMove) {
hwnd = getWindow(hwnd, GW_HWNDNEXT) hwnd = getWindow(hwnd, GW_HWNDNEXT)
continue continue
} }
hwndMap[hwnd] = pid
var r rect var r rect
procGetWindowRect.Call(hwnd, uintptr(unsafe.Pointer(&r))) procGetWindowRect.Call(hwnd, uintptr(unsafe.Pointer(&r)))
@@ -841,7 +836,12 @@ func moveProcessWindowsToVirtualMonitor(pid uint32, bounds image.Rectangle, base
if winH > bounds.Dy() { if winH > bounds.Dy() {
winH = bounds.Dy() winH = bounds.Dy()
} }
procSetWindowPos.Call(hwnd, 0, uintptr(newX), uintptr(newY), uintptr(winW), uintptr(winH), 0x0040|0x0010) flags := uintptr(SWP_NOZORDER | SWP_NOACTIVATE)
if visible {
flags |= SWP_SHOWWINDOW
}
procSetWindowPos.Call(hwnd, 0, uintptr(newX), uintptr(newY), uintptr(winW), uintptr(winH), flags)
hwndMap[hwnd] = visible
log.Printf("virtual: moved window hwnd=0x%x (pid=%d) to virtual monitor (%d,%d)", hwnd, pid, bounds.Min.X, bounds.Min.Y) log.Printf("virtual: moved window hwnd=0x%x (pid=%d) to virtual monitor (%d,%d)", hwnd, pid, bounds.Min.X, bounds.Min.Y)
moved++ moved++
@@ -849,6 +849,18 @@ func moveProcessWindowsToVirtualMonitor(pid uint32, bounds image.Rectangle, base
} }
_ = moved // keep watching for child/handed-off windows after the first one _ = moved // keep watching for child/handed-off windows after the first one
time.Sleep(virtualPlacementPollDelay(attempt))
}
}
func virtualPlacementPollDelay(attempt int) time.Duration {
switch {
case attempt < 120:
return 10 * time.Millisecond
case attempt < 180:
return 50 * time.Millisecond
default:
return 200 * time.Millisecond
} }
} }
@@ -2302,10 +2314,18 @@ func resizeVirtualWindowIfDragging(screenPt point) {
} }
const minW, minH = int32(120), int32(80) const minW, minH = int32(120), int32(80)
if right-left < minW { if right-left < minW {
if hit == 10 || hit == 13 || hit == 16 { left = right-minW } else { right = left+minW } if hit == 10 || hit == 13 || hit == 16 {
left = right - minW
} else {
right = left + minW
}
} }
if bottom-top < minH { if bottom-top < minH {
if hit == 12 || hit == 13 || hit == 14 { top = bottom-minH } else { bottom = top+minH } if hit == 12 || hit == 13 || hit == 14 {
top = bottom - minH
} else {
bottom = top + minH
}
} }
procSetWindowPos.Call(hwnd, 0, uintptr(left), uintptr(top), uintptr(right-left), uintptr(bottom-top), 0x0010|0x0040) procSetWindowPos.Call(hwnd, 0, uintptr(left), uintptr(top), uintptr(right-left), uintptr(bottom-top), 0x0010|0x0040)
} }