util.rs

  1use std::sync::OnceLock;
  2
  3use ::util::ResultExt;
  4use windows::Win32::{Foundation::*, System::Threading::*, UI::WindowsAndMessaging::*};
  5
  6use crate::*;
  7
  8pub(crate) trait HiLoWord {
  9    fn hiword(&self) -> u16;
 10    fn loword(&self) -> u16;
 11    fn signed_hiword(&self) -> i16;
 12    fn signed_loword(&self) -> i16;
 13}
 14
 15impl HiLoWord for WPARAM {
 16    fn hiword(&self) -> u16 {
 17        ((self.0 >> 16) & 0xFFFF) as u16
 18    }
 19
 20    fn loword(&self) -> u16 {
 21        (self.0 & 0xFFFF) as u16
 22    }
 23
 24    fn signed_hiword(&self) -> i16 {
 25        ((self.0 >> 16) & 0xFFFF) as i16
 26    }
 27
 28    fn signed_loword(&self) -> i16 {
 29        (self.0 & 0xFFFF) as i16
 30    }
 31}
 32
 33impl HiLoWord for LPARAM {
 34    fn hiword(&self) -> u16 {
 35        ((self.0 >> 16) & 0xFFFF) as u16
 36    }
 37
 38    fn loword(&self) -> u16 {
 39        (self.0 & 0xFFFF) as u16
 40    }
 41
 42    fn signed_hiword(&self) -> i16 {
 43        ((self.0 >> 16) & 0xFFFF) as i16
 44    }
 45
 46    fn signed_loword(&self) -> i16 {
 47        (self.0 & 0xFFFF) as i16
 48    }
 49}
 50
 51pub(crate) unsafe fn get_window_long(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX) -> isize {
 52    #[cfg(target_pointer_width = "64")]
 53    unsafe {
 54        GetWindowLongPtrW(hwnd, nindex)
 55    }
 56    #[cfg(target_pointer_width = "32")]
 57    unsafe {
 58        GetWindowLongW(hwnd, nindex) as isize
 59    }
 60}
 61
 62pub(crate) unsafe fn set_window_long(
 63    hwnd: HWND,
 64    nindex: WINDOW_LONG_PTR_INDEX,
 65    dwnewlong: isize,
 66) -> isize {
 67    #[cfg(target_pointer_width = "64")]
 68    unsafe {
 69        SetWindowLongPtrW(hwnd, nindex, dwnewlong)
 70    }
 71    #[cfg(target_pointer_width = "32")]
 72    unsafe {
 73        SetWindowLongW(hwnd, nindex, dwnewlong as i32) as isize
 74    }
 75}
 76
 77#[derive(Debug, Clone)]
 78pub(crate) struct OwnedHandle(HANDLE);
 79
 80impl OwnedHandle {
 81    pub(crate) fn new(handle: HANDLE) -> Self {
 82        Self(handle)
 83    }
 84
 85    #[inline(always)]
 86    pub(crate) fn to_raw(&self) -> HANDLE {
 87        self.0
 88    }
 89}
 90
 91impl Drop for OwnedHandle {
 92    fn drop(&mut self) {
 93        if !self.0.is_invalid() {
 94            unsafe { CloseHandle(self.0) }.log_err();
 95        }
 96    }
 97}
 98
 99pub(crate) fn create_event() -> windows::core::Result<OwnedHandle> {
100    Ok(OwnedHandle::new(unsafe {
101        CreateEventW(None, false, false, None)?
102    }))
103}
104
105pub(crate) fn windows_credentials_target_name(url: &str) -> String {
106    format!("zed:url={}", url)
107}
108
109pub(crate) fn load_cursor(style: CursorStyle) -> HCURSOR {
110    static ARROW: OnceLock<HCURSOR> = OnceLock::new();
111    static IBEAM: OnceLock<HCURSOR> = OnceLock::new();
112    static CROSS: OnceLock<HCURSOR> = OnceLock::new();
113    static HAND: OnceLock<HCURSOR> = OnceLock::new();
114    static SIZEWE: OnceLock<HCURSOR> = OnceLock::new();
115    static SIZENS: OnceLock<HCURSOR> = OnceLock::new();
116    static NO: OnceLock<HCURSOR> = OnceLock::new();
117    let (lock, name) = match style {
118        CursorStyle::IBeam | CursorStyle::IBeamCursorForVerticalLayout => (&IBEAM, IDC_IBEAM),
119        CursorStyle::Crosshair => (&CROSS, IDC_CROSS),
120        CursorStyle::PointingHand | CursorStyle::DragLink => (&HAND, IDC_HAND),
121        CursorStyle::ResizeLeft
122        | CursorStyle::ResizeRight
123        | CursorStyle::ResizeLeftRight
124        | CursorStyle::ResizeColumn => (&SIZEWE, IDC_SIZEWE),
125        CursorStyle::ResizeUp
126        | CursorStyle::ResizeDown
127        | CursorStyle::ResizeUpDown
128        | CursorStyle::ResizeRow => (&SIZENS, IDC_SIZENS),
129        CursorStyle::OperationNotAllowed => (&NO, IDC_NO),
130        _ => (&ARROW, IDC_ARROW),
131    };
132    *lock.get_or_init(|| {
133        HCURSOR(
134            unsafe { LoadImageW(None, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED) }
135                .log_err()
136                .unwrap_or_default()
137                .0,
138        )
139    })
140}
141
142#[inline]
143pub(crate) fn logical_size(physical_size: Size<DevicePixels>, scale_factor: f32) -> Size<Pixels> {
144    Size {
145        width: px(physical_size.width.0 as f32 / scale_factor),
146        height: px(physical_size.height.0 as f32 / scale_factor),
147    }
148}
149
150#[inline]
151pub(crate) fn logical_point(x: f32, y: f32, scale_factor: f32) -> Point<Pixels> {
152    Point {
153        x: px(x / scale_factor),
154        y: px(y / scale_factor),
155    }
156}