How Windows Mobile 6.5 Scaled QVGA Apps to WVGA
When high-resolution WVGA (800x480) devices emerged, thousands of legacy Windows Mobile applications were hardcoded for standard QVGA (320x240) screens. Windows Mobile 6.5 relied on a built-in resolution abstraction layer inside the Graphics, Windowing, and Event Subsystem (GWE) to run these older applications without breaking layouts. This layer intercepted graphical device interface (GDI) calls, dynamically scaled coordinates for touch input, and utilized software- or hardware-accelerated pixel interpolation to upscale legacy interfaces seamlessly to the larger physical display.
The HI_RES_AWARE Manifest Flag
The operating system determined whether an executable required
virtualization by inspecting its binary resources. Native
WVGA-compatible applications contained a custom resource marked
HI_RES_AWARE (defined as resource type
CEUX).
If an application lacked this flag, the Windows Mobile loader flagged the process as legacy (running at a virtual 96 DPI). The OS then routed the application through the resolution abstraction layer rather than granting it direct access to native screen metrics.
Input Coordinate Virtualization
Legacy applications expected touch events within the bounds of
0,0 to 319,239. The abstraction layer
intercepted hardware touch inputs generated by the touch digitizer
driver at the native 800x480 resolution.
Before dispatching standard window messages—such as
WM_LBUTTONDOWN, WM_MOUSEMOVE, and
WM_LBUTTONUP—the GWE translated the physical screen
coordinates down to the virtual 320x240 space. This ensured that
hitboxes, button controls, and custom UI elements aligned precisely with
user interactions without requiring developers to alter their internal
hit-testing logic.
GDI Call Interception and Thunking
When a legacy process requested drawing metrics, the abstraction
layer returned spoofed system metrics. API calls such as
GetSystemMetrics(SM_CXSCREEN) and
GetSystemMetrics(SM_CYSCREEN) reported 320 and 240
respectively, rather than 800 and 480.
For rendering, the system utilized a thunking layer that intercepted GDI drawing primitives (such as lines, rectangles, and text calls):
- Coordinate Upscaling: Standard primitive coordinates were multiplied before rasterization occurred.
- Font Scaling: The font engine mapped legacy font sizes to larger point sizes to ensure system text remained legible at higher pixel densities.
- Off-Screen Buffering: Bitmaps drawn using Device Contexts (DCs) were redirected to virtualized memory buffers before being composited.
Resolving the Aspect Ratio Mismatch
Scaling from QVGA (4:3 aspect ratio) to WVGA (5:3 aspect ratio) introduced an uneven scaling factor:
- Vertical axis: 240 pixels to 480 pixels represents an exact 2x integer scale.
- Horizontal axis: 320 pixels to 800 pixels represents a 2.5x fractional scale.
To resolve this, the abstraction layer implemented one of two vendor-configured strategies:
- Pillarboxing: The 320-pixel width was integer-scaled by 2x to 640 pixels, centered on the screen, leaving 80-pixel black borders on either side.
- Non-Uniform Scaling / Stretch-to-Fit: The horizontal buffer was scaled by 2.5x using nearest-neighbor or bilinear filtering to fill the full 800 pixels. While this produced a slight horizontal stretch on UI controls and circular graphics, it eliminated dead space on the display.
Framebuffer Blitting
Once the virtualized 320x240 frame was composed, the abstraction
layer performed a stretching blit operation (StretchBlt)
directly to the physical display buffer. On devices featuring
contemporary Qualcomm or Marvell processors, this stretch operation was
offloaded to dedicated 2D hardware blitters to prevent the
double-buffering and pixel interpolation overhead from degrading system
responsiveness.