|
19 | 19 |
|
20 | 20 | use std::ffi::{OsStr, OsString, CString}; |
21 | 21 | use std::fmt; |
| 22 | +use std::mem; |
22 | 23 | use std::os::windows::ffi::{OsStrExt, OsStringExt}; |
| 24 | +use std::ptr; |
23 | 25 | use std::slice; |
24 | | -use std::mem; |
25 | | - |
26 | 26 | use winapi::ctypes::c_void; |
27 | 27 | use winapi::shared::guiddef::REFIID; |
28 | 28 | use winapi::shared::minwindef::*; |
29 | 29 | use winapi::shared::ntdef::*; |
30 | 30 | use winapi::shared::windef::*; |
31 | 31 | use winapi::shared::winerror::SUCCEEDED; |
| 32 | +use winapi::um::fileapi::*; |
| 33 | +use winapi::um::handleapi::*; |
32 | 34 | use winapi::um::libloaderapi::*; |
| 35 | +use winapi::um::processenv::*; |
33 | 36 | use winapi::um::shellscalingapi::*; |
34 | 37 | use winapi::um::unknwnbase::IUnknown; |
| 38 | +use winapi::um::winbase::*; |
| 39 | +use winapi::um::wincon::*; |
| 40 | +// This needs to be explicit, otherwise HRESULT will conflict |
| 41 | +use winapi::um::winnt::{GENERIC_READ, GENERIC_WRITE, FILE_SHARE_WRITE}; |
35 | 42 |
|
36 | 43 | use direct2d::enums::DrawTextOptions; |
37 | 44 |
|
@@ -227,6 +234,7 @@ lazy_static! { |
227 | 234 |
|
228 | 235 | /// Initialize the app. At the moment, this is mostly needed for hi-dpi. |
229 | 236 | pub fn init() { |
| 237 | + attach_console(); |
230 | 238 | if let Some(func) = OPTIONAL_FUNCTIONS.SetProcessDpiAwareness { |
231 | 239 | // This function is only supported on windows 10 |
232 | 240 | unsafe { |
@@ -257,3 +265,37 @@ macro_rules! accel { |
257 | 265 | ] |
258 | 266 | } |
259 | 267 | } |
| 268 | + |
| 269 | +/// Attach the process to the console of the parent process. This allows xi-win to |
| 270 | +/// correctly print to a console when run from powershell or cmd. |
| 271 | +/// If no console is available, allocate a new console. |
| 272 | +fn attach_console() { |
| 273 | + unsafe { |
| 274 | + let stdout = GetStdHandle(STD_OUTPUT_HANDLE); |
| 275 | + if stdout != INVALID_HANDLE_VALUE && GetFileType(stdout) != FILE_TYPE_UNKNOWN { |
| 276 | + // We already have a perfectly valid stdout and must not attach. |
| 277 | + // This happens, for example in MingW consoles like git bash. |
| 278 | + return; |
| 279 | + } |
| 280 | + |
| 281 | + if AttachConsole(ATTACH_PARENT_PROCESS) > 0 { |
| 282 | + let chnd = CreateFileA( |
| 283 | + CString::new("CONOUT$").unwrap().as_ptr(), |
| 284 | + GENERIC_READ | GENERIC_WRITE, |
| 285 | + FILE_SHARE_WRITE, |
| 286 | + ptr::null_mut(), |
| 287 | + OPEN_EXISTING, |
| 288 | + 0, |
| 289 | + ptr::null_mut()); |
| 290 | + |
| 291 | + if chnd == INVALID_HANDLE_VALUE { |
| 292 | + // CreateFileA failed. |
| 293 | + return; |
| 294 | + } |
| 295 | + |
| 296 | + SetStdHandle(STD_OUTPUT_HANDLE, chnd); |
| 297 | + SetStdHandle(STD_ERROR_HANDLE, chnd); |
| 298 | + } |
| 299 | + } |
| 300 | +} |
| 301 | + |
0 commit comments