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
@@ -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)
} }