mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-04 06:34:26 +00:00
Implement more GPUI services on windows. (#8940)
### Description This is a part of #8809 , impl the following functions: - `os_version` - `local_timezone` - `double_click_interval` - `set_cursor_style` - `open_url` - `reveal_path` Release Notes: - N/A --------- Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
effc317a06
commit
af87fb98d0
2 changed files with 140 additions and 26 deletions
20
Cargo.toml
20
Cargo.toml
|
@ -215,7 +215,10 @@ hex = "0.4.3"
|
|||
ignore = "0.4.22"
|
||||
indoc = "1"
|
||||
# We explicitly disable http2 support in isahc.
|
||||
isahc = { version = "1.7.2", default-features = false, features = ["static-curl", "text-decoding"] }
|
||||
isahc = { version = "1.7.2", default-features = false, features = [
|
||||
"static-curl",
|
||||
"text-decoding",
|
||||
] }
|
||||
itertools = "0.11.0"
|
||||
lazy_static = "1.4.0"
|
||||
linkify = "0.10.0"
|
||||
|
@ -238,7 +241,10 @@ semver = "1.0"
|
|||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] }
|
||||
serde_json_lenient = { version = "0.1", features = ["preserve_order", "raw_value"] }
|
||||
serde_json_lenient = { version = "0.1", features = [
|
||||
"preserve_order",
|
||||
"raw_value",
|
||||
] }
|
||||
serde_repr = "0.1"
|
||||
sha2 = "0.10"
|
||||
shellexpand = "2.1.0"
|
||||
|
@ -249,7 +255,11 @@ sysinfo = "0.29.10"
|
|||
tempfile = "3.9.0"
|
||||
thiserror = "1.0.29"
|
||||
tiktoken-rs = "0.5.7"
|
||||
time = { version = "0.3", features = ["serde", "serde-well-known", "formatting"] }
|
||||
time = { version = "0.3", features = [
|
||||
"serde",
|
||||
"serde-well-known",
|
||||
"formatting",
|
||||
] }
|
||||
toml = "0.8"
|
||||
tower-http = "0.4.4"
|
||||
tree-sitter = { version = "0.20", features = ["wasm"] }
|
||||
|
@ -312,11 +322,15 @@ sys-locale = "0.3.1"
|
|||
[workspace.dependencies.windows]
|
||||
version = "0.53.0"
|
||||
features = [
|
||||
"Wdk_System_SystemServices",
|
||||
"Win32_Graphics_Gdi",
|
||||
"Win32_Graphics_DirectComposition",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
"Win32_UI_Input_KeyboardAndMouse",
|
||||
"Win32_UI_Shell",
|
||||
"Win32_System_SystemInformation",
|
||||
"Win32_System_SystemServices",
|
||||
"Win32_System_Time",
|
||||
"Win32_Security",
|
||||
"Win32_System_Threading",
|
||||
"Win32_System_DataExchange",
|
||||
|
|
|
@ -17,14 +17,28 @@ use futures::channel::oneshot::Receiver;
|
|||
use parking_lot::Mutex;
|
||||
use time::UtcOffset;
|
||||
use util::{ResultExt, SemanticVersion};
|
||||
use windows::Win32::{
|
||||
Foundation::{CloseHandle, BOOL, HANDLE, HWND, LPARAM, TRUE},
|
||||
Graphics::DirectComposition::DCompositionWaitForCompositorClock,
|
||||
System::Threading::{CreateEventW, GetCurrentThreadId, INFINITE},
|
||||
UI::WindowsAndMessaging::{
|
||||
DispatchMessageW, EnumThreadWindows, PeekMessageW, PostQuitMessage, SystemParametersInfoW,
|
||||
TranslateMessage, MSG, PM_REMOVE, SPI_GETWHEELSCROLLCHARS, SPI_GETWHEELSCROLLLINES,
|
||||
SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, WM_QUIT, WM_SETTINGCHANGE,
|
||||
use windows::{
|
||||
core::{HSTRING, PCWSTR},
|
||||
Wdk::System::SystemServices::RtlGetVersion,
|
||||
Win32::{
|
||||
Foundation::{CloseHandle, BOOL, HANDLE, HWND, LPARAM, TRUE},
|
||||
Graphics::DirectComposition::DCompositionWaitForCompositorClock,
|
||||
System::{
|
||||
Threading::{CreateEventW, GetCurrentThreadId, INFINITE},
|
||||
Time::{GetTimeZoneInformation, TIME_ZONE_ID_INVALID},
|
||||
},
|
||||
UI::{
|
||||
Input::KeyboardAndMouse::GetDoubleClickTime,
|
||||
Shell::ShellExecuteW,
|
||||
WindowsAndMessaging::{
|
||||
DispatchMessageW, EnumThreadWindows, LoadImageW, MsgWaitForMultipleObjects,
|
||||
PeekMessageW, PostQuitMessage, SetCursor, SystemParametersInfoW, TranslateMessage,
|
||||
HCURSOR, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_IBEAM, IDC_NO, IDC_SIZENS, IDC_SIZEWE,
|
||||
IMAGE_CURSOR, LR_DEFAULTSIZE, LR_SHARED, MSG, PM_REMOVE, QS_ALLINPUT,
|
||||
SPI_GETWHEELSCROLLCHARS, SPI_GETWHEELSCROLLLINES, SW_SHOWDEFAULT,
|
||||
SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, WM_QUIT, WM_SETTINGCHANGE,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -300,9 +314,16 @@ impl Platform for WindowsPlatform {
|
|||
WindowAppearance::Dark
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
fn open_url(&self, url: &str) {
|
||||
// todo!("windows")
|
||||
let url_string = url.to_string();
|
||||
self.background_executor()
|
||||
.spawn(async move {
|
||||
if url_string.is_empty() {
|
||||
return;
|
||||
}
|
||||
open_target(url_string.as_str());
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
|
@ -320,9 +341,22 @@ impl Platform for WindowsPlatform {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
fn reveal_path(&self, path: &Path) {
|
||||
unimplemented!()
|
||||
let Ok(file_full_path) = path.canonicalize() else {
|
||||
log::error!("unable to parse file path");
|
||||
return;
|
||||
};
|
||||
self.background_executor()
|
||||
.spawn(async move {
|
||||
let Some(path) = file_full_path.to_str() else {
|
||||
return;
|
||||
};
|
||||
if path.is_empty() {
|
||||
return;
|
||||
}
|
||||
open_target(path);
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn on_become_active(&self, callback: Box<dyn FnMut()>) {
|
||||
|
@ -365,11 +399,20 @@ impl Platform for WindowsPlatform {
|
|||
}
|
||||
|
||||
fn os_version(&self) -> Result<SemanticVersion> {
|
||||
Ok(SemanticVersion {
|
||||
major: 1,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
})
|
||||
let mut info = unsafe { std::mem::zeroed() };
|
||||
let status = unsafe { RtlGetVersion(&mut info) };
|
||||
if status.is_ok() {
|
||||
Ok(SemanticVersion {
|
||||
major: info.dwMajorVersion as _,
|
||||
minor: info.dwMinorVersion as _,
|
||||
patch: info.dwBuildNumber as _,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow::anyhow!(
|
||||
"unable to get Windows version: {}",
|
||||
std::io::Error::last_os_error()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn app_version(&self) -> Result<SemanticVersion> {
|
||||
|
@ -385,14 +428,28 @@ impl Platform for WindowsPlatform {
|
|||
Err(anyhow!("not yet implemented"))
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
fn local_timezone(&self) -> UtcOffset {
|
||||
UtcOffset::from_hms(9, 0, 0).unwrap()
|
||||
let mut info = unsafe { std::mem::zeroed() };
|
||||
let ret = unsafe { GetTimeZoneInformation(&mut info) };
|
||||
if ret == TIME_ZONE_ID_INVALID {
|
||||
log::error!(
|
||||
"Unable to get local timezone: {}",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
return UtcOffset::UTC;
|
||||
}
|
||||
// Windows treat offset as:
|
||||
// UTC = localtime + offset
|
||||
// so we add a minus here
|
||||
let hours = -info.Bias / 60;
|
||||
let minutes = -info.Bias % 60;
|
||||
|
||||
UtcOffset::from_hms(hours as _, minutes as _, 0).unwrap()
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
fn double_click_interval(&self) -> Duration {
|
||||
Duration::from_millis(100)
|
||||
let millis = unsafe { GetDoubleClickTime() };
|
||||
Duration::from_millis(millis as _)
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
|
@ -400,8 +457,31 @@ impl Platform for WindowsPlatform {
|
|||
Err(anyhow!("not yet implemented"))
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
fn set_cursor_style(&self, style: CursorStyle) {}
|
||||
fn set_cursor_style(&self, style: CursorStyle) {
|
||||
let handle = match style {
|
||||
CursorStyle::IBeam | CursorStyle::IBeamCursorForVerticalLayout => unsafe {
|
||||
load_cursor(IDC_IBEAM)
|
||||
},
|
||||
CursorStyle::Crosshair => unsafe { load_cursor(IDC_CROSS) },
|
||||
CursorStyle::PointingHand | CursorStyle::DragLink => unsafe { load_cursor(IDC_HAND) },
|
||||
CursorStyle::ResizeLeft | CursorStyle::ResizeRight | CursorStyle::ResizeLeftRight => unsafe {
|
||||
load_cursor(IDC_SIZEWE)
|
||||
},
|
||||
CursorStyle::ResizeUp | CursorStyle::ResizeDown | CursorStyle::ResizeUpDown => unsafe {
|
||||
load_cursor(IDC_SIZENS)
|
||||
},
|
||||
CursorStyle::OperationNotAllowed => unsafe { load_cursor(IDC_NO) },
|
||||
_ => unsafe { load_cursor(IDC_ARROW) },
|
||||
};
|
||||
if handle.is_err() {
|
||||
log::error!(
|
||||
"Error loading cursor image: {}",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
return;
|
||||
}
|
||||
let _ = unsafe { SetCursor(HCURSOR(handle.unwrap().0)) };
|
||||
}
|
||||
|
||||
// todo!("windows")
|
||||
fn should_auto_hide_scrollbars(&self) -> bool {
|
||||
|
@ -437,3 +517,23 @@ impl Platform for WindowsPlatform {
|
|||
Task::ready(Err(anyhow!("register_url_scheme unimplemented")))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn load_cursor(name: PCWSTR) -> Result<HANDLE> {
|
||||
LoadImageW(None, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED).map_err(|e| anyhow!(e))
|
||||
}
|
||||
|
||||
fn open_target(target: &str) {
|
||||
unsafe {
|
||||
let ret = ShellExecuteW(
|
||||
None,
|
||||
windows::core::w!("open"),
|
||||
&HSTRING::from(target),
|
||||
None,
|
||||
None,
|
||||
SW_SHOWDEFAULT,
|
||||
);
|
||||
if ret.0 <= 32 {
|
||||
log::error!("Unable to open target: {}", std::io::Error::last_os_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue