all keyboard and mouse events are silently dropped. The application window opens and renders correctly, but is_key_down, is_key_pressed, and all other input queries always return false/no events.
The same binary compiled for x86_64-pc-windows-msvc works correctly on x86-64 Windows hardware.
Root Cause
In src/native/windows.rs, the run() function stores a pointer to WindowsDisplay in the window's user data slot via SetWindowLongPtrA. This pointer is later retrieved by the window procedure (win32_wndproc) to dispatch events. The storage call is guarded by architecture #[cfg] attributes, but aarch64 is not covered:
// src/native/windows.rs — run() function, ~line 945
#[cfg(target_arch = "x86_64")]
SetWindowLongPtrA(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);
#[cfg(target_arch = "x86")]
SetWindowLong(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);
On aarch64, neither cfg block is compiled, so SetWindowLongPtrA is never called. The user data slot remains 0.
The window procedure retrieves the pointer using target_pointer_width = "64" (which correctly covers aarch64), but always reads 0:
// src/native/windows.rs — win32_wndproc()
#[cfg(target_pointer_width = "64")]
{
display_ptr = GetWindowLongPtrA(hwnd, GWLP_USERDATA) // always returns 0 on aarch64
}
if display_ptr == 0 {
return DefWindowProcW(hwnd, umsg, wparam, lparam); // every event is dropped here
}
Because display_ptr is always 0, win32_wndproc returns early for every window message, including WM_KEYDOWN, WM_KEYUP, WM_MOUSEMOVE, etc. No events ever reach the application.
The same bug exists in the set_fullscreen method (~line 164), which has the identical architecture gap:
#[cfg(target_arch = "x86_64")]
SetWindowLongPtrA(self.wnd, GWL_STYLE, win_style as _);
#[cfg(target_arch = "x86")]
SetWindowLong(self.wnd, GWL_STYLE, win_style as _);
// aarch64 → neither branch compiles → window style is never updated
Fix
Add aarch64 to the x86_64 branch in both locations, since ARM64 Windows is a 64-bit platform and uses SetWindowLongPtrA (not the 32-bit SetWindowLong):
run() function:
// Before
#[cfg(target_arch = "x86_64")]
SetWindowLongPtrA(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);
#[cfg(target_arch = "x86")]
SetWindowLong(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);
// After
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
SetWindowLongPtrA(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);
#[cfg(target_arch = "x86")]
SetWindowLong(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);
set_fullscreen() method:
// Before
#[cfg(target_arch = "x86_64")]
SetWindowLongPtrA(self.wnd, GWL_STYLE, win_style as _);
#[cfg(target_arch = "x86")]
SetWindowLong(self.wnd, GWL_STYLE, win_style as _);
// After
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
SetWindowLongPtrA(self.wnd, GWL_STYLE, win_style as _);
#[cfg(target_arch = "x86")]
SetWindowLong(self.wnd, GWL_STYLE, win_style as _);
Reproduction
- Any macroquad/miniquad application that reads keyboard or mouse input
- Compile for
aarch64-pc-windows-msvc
- Run on a Windows ARM64 machine (e.g. Snapdragon X, Surface Pro X)
- Observe: window opens, renders, but all input is ignored
Not reproducible when the same code is compiled for x86_64-pc-windows-msvc and run on x86-64 Windows.
Notes
- The
win32_wndproc retrieval already uses target_pointer_width = "64" (correct for aarch64), so only the storage side needs fixing.
- Alternatively, both sites could be simplified to use
target_pointer_width consistently to future-proof against other 64-bit Windows targets.
all keyboard and mouse events are silently dropped. The application window opens and renders correctly, but
is_key_down,is_key_pressed, and all other input queries always return false/no events.The same binary compiled for
x86_64-pc-windows-msvcworks correctly on x86-64 Windows hardware.Root Cause
In
src/native/windows.rs, therun()function stores a pointer toWindowsDisplayin the window's user data slot viaSetWindowLongPtrA. This pointer is later retrieved by the window procedure (win32_wndproc) to dispatch events. The storage call is guarded by architecture#[cfg]attributes, butaarch64is not covered:On
aarch64, neithercfgblock is compiled, soSetWindowLongPtrAis never called. The user data slot remains 0.The window procedure retrieves the pointer using
target_pointer_width = "64"(which correctly covers aarch64), but always reads 0:Because
display_ptris always 0,win32_wndprocreturns early for every window message, includingWM_KEYDOWN,WM_KEYUP,WM_MOUSEMOVE, etc. No events ever reach the application.The same bug exists in the
set_fullscreenmethod (~line 164), which has the identical architecture gap:Fix
Add
aarch64to thex86_64branch in both locations, since ARM64 Windows is a 64-bit platform and usesSetWindowLongPtrA(not the 32-bitSetWindowLong):run()function:set_fullscreen()method:Reproduction
aarch64-pc-windows-msvcNot reproducible when the same code is compiled for
x86_64-pc-windows-msvcand run on x86-64 Windows.Notes
win32_wndprocretrieval already usestarget_pointer_width = "64"(correct for aarch64), so only the storage side needs fixing.target_pointer_widthconsistently to future-proof against other 64-bit Windows targets.