Skip to content

Add support for Windows 7 and 8 #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ nix = "0.22.0"
[target.'cfg(target_os="windows")'.dependencies]
winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi", "errhandlingapi"] }
uuid = { version = "0.8", features = ["v4"], optional = true }
libloading = "0.8.0"

[target.'cfg(target_os="macos")'.dependencies]
cocoa = "0.24.0"
Expand Down
35 changes: 35 additions & 0 deletions src/win/dynamic_win_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use libloading::{Library, Symbol};
use winapi::shared::minwindef::{BOOL, UINT};
use winapi::shared::windef::{DPI_AWARENESS_CONTEXT, HWND};

/// Provides access to some Win32 API functions that are not available in older Windows versions.
///
/// This is better than eagerly linking to these functions because then the resulting binary
/// wouldn't work *at all* in the older Windows versions, whereas with this approach, we can
/// fall back to alternative logic or alternative values on a case-by-case basis.
pub struct DynamicWinApi {
user32_library: Library,
}

impl DynamicWinApi {
/// Loads the dynamic windows API, in particular "user32.dll".
pub fn load() -> Self {
unsafe { Self { user32_library: Library::new("user32.dll").unwrap() } }
}

/// Should be available from Windows 10 onwards.
pub fn set_process_dpi_awareness_context(
&self,
) -> Option<Symbol<SetProcessDpiAwarenessContext>> {
unsafe { self.user32_library.get(b"SetProcessDpiAwarenessContext").ok() }
}

/// Should be available from Windows 10 onwards.
pub fn get_dpi_for_window(&self) -> Option<Symbol<GetDpiForWindow>> {
unsafe { self.user32_library.get(b"GetDpiForWindow").ok() }
}
}

type SetProcessDpiAwarenessContext = extern "stdcall" fn(value: DPI_AWARENESS_CONTEXT) -> BOOL;

type GetDpiForWindow = extern "stdcall" fn(hwnd: HWND) -> UINT;
1 change: 1 addition & 0 deletions src/win/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod dynamic_win_api;
mod keyboard;
mod window;

Expand Down
32 changes: 16 additions & 16 deletions src/win/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ use winapi::shared::windef::{HWND, RECT};
use winapi::um::combaseapi::CoCreateGuid;
use winapi::um::winuser::{
AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW,
GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW,
ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW,
SetWindowPos, TranslateMessage, UnregisterClassW, CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA,
IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE,
WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP,
WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCDESTROY,
WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
WM_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD,
WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
XBUTTON1, XBUTTON2,
GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, ReleaseCapture,
SetCapture, SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, UnregisterClassW,
CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER,
WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN,
WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL,
WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW,
WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, WM_USER, WM_XBUTTONDOWN,
WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX,
WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, XBUTTON1, XBUTTON2,
};

use std::cell::{Cell, RefCell};
Expand All @@ -35,6 +34,7 @@ use crate::{

use super::keyboard::KeyboardState;

use crate::win::dynamic_win_api::DynamicWinApi;
#[cfg(feature = "opengl")]
use crate::{gl::GlContext, window::RawWindowHandleWrapper};

Expand Down Expand Up @@ -681,15 +681,15 @@ impl Window<'_> {
};
*window_state.handler.borrow_mut() = Some(Box::new(handler));

// Only works on Windows 10 unfortunately.
SetProcessDpiAwarenessContext(
winapi::shared::windef::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE,
);
let dynamic_win_api = DynamicWinApi::load();
if let Some(f) = dynamic_win_api.set_process_dpi_awareness_context() {
f(winapi::shared::windef::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
}

// Now we can get the actual dpi of the window.
let new_rect = if let WindowScalePolicy::SystemScaleFactor = options.scale {
// Only works on Windows 10 unfortunately.
let dpi = GetDpiForWindow(hwnd);
let dpi =
if let Some(f) = dynamic_win_api.get_dpi_for_window() { f(hwnd) } else { 96 };
let scale_factor = dpi as f64 / 96.0;

let mut window_info = window_state.window_info.borrow_mut();
Expand Down