windows: active window implementation (#9314)
active window implementation - bonus vim mode works on windows now Release Notes: - N/A
This commit is contained in:
parent
328aa2cc95
commit
db43479be8
2 changed files with 53 additions and 11 deletions
|
@ -11,6 +11,7 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use ::util::{ResultExt, SemanticVersion};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
use copypasta::{ClipboardContext, ClipboardProvider};
|
use copypasta::{ClipboardContext, ClipboardProvider};
|
||||||
|
@ -19,7 +20,6 @@ use itertools::Itertools;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use time::UtcOffset;
|
use time::UtcOffset;
|
||||||
use util::{ResultExt, SemanticVersion};
|
|
||||||
use windows::{
|
use windows::{
|
||||||
core::*,
|
core::*,
|
||||||
Wdk::System::SystemServices::*,
|
Wdk::System::SystemServices::*,
|
||||||
|
@ -31,12 +31,7 @@ use windows::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::*;
|
||||||
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, ForegroundExecutor,
|
|
||||||
Keymap, Menu, PathPromptOptions, Platform, PlatformDisplay, PlatformInput, PlatformTextSystem,
|
|
||||||
PlatformWindow, Task, WindowAppearance, WindowParams, WindowsDispatcher, WindowsDisplay,
|
|
||||||
WindowsTextSystem, WindowsWindow,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) struct WindowsPlatform {
|
pub(crate) struct WindowsPlatform {
|
||||||
inner: Rc<WindowsPlatformInner>,
|
inner: Rc<WindowsPlatformInner>,
|
||||||
|
@ -64,6 +59,19 @@ pub(crate) struct WindowsPlatformInner {
|
||||||
pub(crate) settings: RefCell<WindowsPlatformSystemSettings>,
|
pub(crate) settings: RefCell<WindowsPlatformSystemSettings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WindowsPlatformInner {
|
||||||
|
pub(crate) fn try_get_windows_inner_from_hwnd(
|
||||||
|
&self,
|
||||||
|
hwnd: HWND,
|
||||||
|
) -> Option<Rc<WindowsWindowInner>> {
|
||||||
|
self.raw_window_handles
|
||||||
|
.read()
|
||||||
|
.iter()
|
||||||
|
.find(|entry| *entry == &hwnd)
|
||||||
|
.and_then(|hwnd| try_get_window_inner(*hwnd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for WindowsPlatformInner {
|
impl Drop for WindowsPlatformInner {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { CloseHandle(self.event) }.ok();
|
unsafe { CloseHandle(self.event) }.ok();
|
||||||
|
@ -282,9 +290,11 @@ impl Platform for WindowsPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(windows)
|
|
||||||
fn active_window(&self) -> Option<AnyWindowHandle> {
|
fn active_window(&self) -> Option<AnyWindowHandle> {
|
||||||
None
|
let active_window_hwnd = unsafe { GetActiveWindow() };
|
||||||
|
self.inner
|
||||||
|
.try_get_windows_inner_from_hwnd(active_window_hwnd)
|
||||||
|
.map(|inner| inner.handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_window(
|
fn open_window(
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub(crate) struct WindowsWindowInner {
|
||||||
renderer: RefCell<BladeRenderer>,
|
renderer: RefCell<BladeRenderer>,
|
||||||
callbacks: RefCell<Callbacks>,
|
callbacks: RefCell<Callbacks>,
|
||||||
platform_inner: Rc<WindowsPlatformInner>,
|
platform_inner: Rc<WindowsPlatformInner>,
|
||||||
handle: AnyWindowHandle,
|
pub(crate) handle: AnyWindowHandle,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +178,7 @@ impl WindowsWindowInner {
|
||||||
match msg {
|
match msg {
|
||||||
WM_ACTIVATE => self.handle_activate_msg(msg, wparam, lparam),
|
WM_ACTIVATE => self.handle_activate_msg(msg, wparam, lparam),
|
||||||
WM_CREATE => self.handle_create_msg(lparam),
|
WM_CREATE => self.handle_create_msg(lparam),
|
||||||
|
WM_SETFOCUS => self.handle_set_focus_msg(msg, wparam, lparam),
|
||||||
WM_MOVE => self.handle_move_msg(lparam),
|
WM_MOVE => self.handle_move_msg(lparam),
|
||||||
WM_SIZE => self.handle_size_msg(lparam),
|
WM_SIZE => self.handle_size_msg(lparam),
|
||||||
WM_NCCALCSIZE => self.handle_calc_client_size(msg, wparam, lparam),
|
WM_NCCALCSIZE => self.handle_calc_client_size(msg, wparam, lparam),
|
||||||
|
@ -968,6 +969,31 @@ impl WindowsWindowInner {
|
||||||
|
|
||||||
unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) }
|
unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_set_focus_msg(&self, _msg: u32, wparam: WPARAM, _lparam: LPARAM) -> LRESULT {
|
||||||
|
// wparam is the window that just lost focus (may be null)
|
||||||
|
// SEE: https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-setfocus
|
||||||
|
let lost_focus_hwnd = HWND(wparam.0 as isize);
|
||||||
|
if let Some(lost_focus_window) = self
|
||||||
|
.platform_inner
|
||||||
|
.try_get_windows_inner_from_hwnd(lost_focus_hwnd)
|
||||||
|
{
|
||||||
|
lost_focus_window
|
||||||
|
.callbacks
|
||||||
|
.borrow_mut()
|
||||||
|
.active_status_change
|
||||||
|
.as_mut()
|
||||||
|
.map(|mut cb| cb(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.callbacks
|
||||||
|
.borrow_mut()
|
||||||
|
.active_status_change
|
||||||
|
.as_mut()
|
||||||
|
.map(|mut cb| cb(true));
|
||||||
|
|
||||||
|
LRESULT(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -1234,7 +1260,9 @@ impl PlatformWindow for WindowsWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&self) {
|
fn activate(&self) {
|
||||||
unsafe { ShowWindowAsync(self.inner.hwnd, SW_NORMAL) };
|
unsafe { SetActiveWindow(self.inner.hwnd) };
|
||||||
|
unsafe { SetFocus(self.inner.hwnd) };
|
||||||
|
unsafe { SetForegroundWindow(self.inner.hwnd) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(windows)
|
// todo(windows)
|
||||||
|
@ -1497,6 +1525,10 @@ unsafe extern "system" fn wnd_proc(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn try_get_window_inner(hwnd: HWND) -> Option<Rc<WindowsWindowInner>> {
|
pub(crate) fn try_get_window_inner(hwnd: HWND) -> Option<Rc<WindowsWindowInner>> {
|
||||||
|
if hwnd == HWND(0) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let ptr = unsafe { get_window_long(hwnd, GWLP_USERDATA) } as *mut Weak<WindowsWindowInner>;
|
let ptr = unsafe { get_window_long(hwnd, GWLP_USERDATA) } as *mut Weak<WindowsWindowInner>;
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
let inner = unsafe { &*ptr };
|
let inner = unsafe { &*ptr };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue