WIP - adds platform APIs for checking the top most window
This commit is contained in:
parent
a66a0cfd70
commit
426aeb7c5e
9 changed files with 126 additions and 5 deletions
|
@ -21,6 +21,7 @@ use std::{
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use pathfinder_geometry::vector::Vector2F;
|
||||
use postage::oneshot;
|
||||
use smallvec::SmallVec;
|
||||
use smol::prelude::*;
|
||||
|
@ -865,6 +866,12 @@ impl MutableAppContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn screen_position(&self, window_id: usize, view_position: &Vector2F) -> Option<Vector2F> {
|
||||
self.presenters_and_platform_windows
|
||||
.get(&window_id)
|
||||
.map(|(_, window)| window.screen_position(view_position))
|
||||
}
|
||||
|
||||
pub fn window_ids(&self) -> impl Iterator<Item = usize> + '_ {
|
||||
self.cx.windows.keys().cloned()
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ pub trait Platform: Send + Sync {
|
|||
fn read_credentials(&self, url: &str) -> Result<Option<(String, Vec<u8>)>>;
|
||||
fn delete_credentials(&self, url: &str) -> Result<()>;
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle);
|
||||
fn set_cursor_style(&self, style: CursorStyle, window_id: usize, screen_position: &Vector2F);
|
||||
fn should_auto_hide_scrollbars(&self) -> bool;
|
||||
|
||||
fn local_timezone(&self) -> UtcOffset;
|
||||
|
@ -145,6 +145,7 @@ pub trait Window {
|
|||
fn present_scene(&mut self, scene: Scene);
|
||||
fn appearance(&self) -> Appearance;
|
||||
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>);
|
||||
fn screen_position(&self, view_position: &Vector2F) -> Vector2F;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -37,6 +37,7 @@ use objc::{
|
|||
runtime::{Class, Object, Sel},
|
||||
sel, sel_impl,
|
||||
};
|
||||
use pathfinder_geometry::vector::Vector2F;
|
||||
use postage::oneshot;
|
||||
use ptr::null_mut;
|
||||
use std::{
|
||||
|
@ -695,7 +696,19 @@ impl platform::Platform for MacPlatform {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle) {
|
||||
fn set_cursor_style(&self, style: CursorStyle, window_id: usize, screen_position: &Vector2F) {
|
||||
let top_most = Window::window_id_under(screen_position);
|
||||
if top_most.is_none() {
|
||||
return;
|
||||
}
|
||||
if top_most.unwrap() != window_id {
|
||||
return;
|
||||
}
|
||||
|
||||
dbg!(top_most.unwrap(), window_id);
|
||||
|
||||
dbg!(style);
|
||||
|
||||
unsafe {
|
||||
let cursor: id = match style {
|
||||
CursorStyle::Arrow => msg_send![class!(NSCursor), arrowCursor],
|
||||
|
|
|
@ -258,6 +258,10 @@ impl platform::Window for StatusItem {
|
|||
crate::Appearance::from_native(appearance)
|
||||
}
|
||||
}
|
||||
|
||||
fn screen_position(&self, _view_position: &Vector2F) -> Vector2F {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl StatusItemState {
|
||||
|
|
|
@ -559,6 +559,26 @@ impl Window {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_id_under(screen_position: &Vector2F) -> Option<usize> {
|
||||
unsafe {
|
||||
let app = NSApplication::sharedApplication(nil);
|
||||
|
||||
let point = NSPoint::new(screen_position.x() as f64, screen_position.y() as f64);
|
||||
let window_number: NSInteger = msg_send![class!(NSWindow), windowNumberAtPoint:point belowWindowWithWindowNumber:0 as NSInteger];
|
||||
// For some reason this API doesn't work when our two windows are on top of each other
|
||||
let top_most_window: id = msg_send![app, windowWithWindowNumber: window_number];
|
||||
dbg!(top_most_window);
|
||||
let is_panel: BOOL = msg_send![top_most_window, isKindOfClass: PANEL_CLASS];
|
||||
let is_window: BOOL = msg_send![top_most_window, isKindOfClass: WINDOW_CLASS];
|
||||
if is_panel | is_window {
|
||||
let id = get_window_state(&*top_most_window).borrow().id;
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
|
@ -755,6 +775,16 @@ impl platform::Window for Window {
|
|||
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>) {
|
||||
self.0.borrow_mut().appearance_changed_callback = Some(callback);
|
||||
}
|
||||
|
||||
fn screen_position(&self, view_position: &Vector2F) -> Vector2F {
|
||||
let self_borrow = self.0.borrow_mut();
|
||||
unsafe {
|
||||
let point = NSPoint::new(view_position.x() as f64, view_position.y() as f64);
|
||||
let screen_point: NSPoint =
|
||||
msg_send![self_borrow.native_window, convertPointToScreen: point];
|
||||
vec2f(screen_point.x as f32, screen_point.y as f32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowState {
|
||||
|
|
|
@ -178,7 +178,7 @@ impl super::Platform for Platform {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle) {
|
||||
fn set_cursor_style(&self, style: CursorStyle, _window_id: usize, _position: &Vector2F) {
|
||||
*self.cursor.lock() = style;
|
||||
}
|
||||
|
||||
|
@ -332,6 +332,10 @@ impl super::Window for Window {
|
|||
}
|
||||
|
||||
fn on_appearance_changed(&mut self, _: Box<dyn FnMut()>) {}
|
||||
|
||||
fn screen_position(&self, view_position: &Vector2F) -> Vector2F {
|
||||
view_position.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn platform() -> Platform {
|
||||
|
|
|
@ -316,7 +316,14 @@ impl Presenter {
|
|||
break;
|
||||
}
|
||||
}
|
||||
cx.platform().set_cursor_style(style_to_assign);
|
||||
|
||||
if let Some(screen_position) = cx.screen_position(self.window_id, position) {
|
||||
cx.platform().set_cursor_style(
|
||||
style_to_assign,
|
||||
self.window_id,
|
||||
&screen_position,
|
||||
);
|
||||
}
|
||||
|
||||
if !event_reused {
|
||||
if pressed_button.is_some() {
|
||||
|
|
|
@ -209,6 +209,7 @@ impl EventDispatcher {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cx.platform().set_cursor_style(style_to_assign);
|
||||
|
||||
if !event_reused {
|
||||
|
|
|
@ -31,8 +31,9 @@ use futures::{
|
|||
};
|
||||
use gpui::{
|
||||
actions,
|
||||
color::Color,
|
||||
elements::*,
|
||||
geometry::vector::Vector2F,
|
||||
geometry::vector::{vec2f, Vector2F},
|
||||
impl_actions, impl_internal_actions,
|
||||
keymap_matcher::KeymapContext,
|
||||
platform::{CursorStyle, WindowOptions},
|
||||
|
@ -263,6 +264,59 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
|
|||
client.add_view_request_handler(Workspace::handle_follow);
|
||||
client.add_view_message_handler(Workspace::handle_unfollow);
|
||||
client.add_view_message_handler(Workspace::handle_update_followers);
|
||||
|
||||
// REMEMBER TO DELETE THE SHOW NOTIF
|
||||
cx.add_action(
|
||||
|_workspace: &mut Workspace, _: &ShowNotif, cx: &mut ViewContext<Workspace>| {
|
||||
struct DummyView;
|
||||
|
||||
impl Entity for DummyView {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl View for DummyView {
|
||||
fn ui_name() -> &'static str {
|
||||
"DummyView"
|
||||
}
|
||||
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox {
|
||||
MouseEventHandler::<DummyView>::new(0, cx, |state, _cx| {
|
||||
Empty::new()
|
||||
.contained()
|
||||
.with_background_color(if state.hovered() {
|
||||
Color::red()
|
||||
} else {
|
||||
Color::blue()
|
||||
})
|
||||
.constrained()
|
||||
.with_width(200.)
|
||||
.with_height(200.)
|
||||
.boxed()
|
||||
})
|
||||
.on_click(MouseButton::Left, |_, _| {
|
||||
println!("click");
|
||||
})
|
||||
.with_cursor_style(CursorStyle::ResizeUpDown)
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
cx.add_window(
|
||||
WindowOptions {
|
||||
bounds: gpui::WindowBounds::Fixed(gpui::geometry::rect::RectF::new(
|
||||
vec2f(400., 200.),
|
||||
vec2f(300., 200.),
|
||||
)),
|
||||
titlebar: None,
|
||||
center: false,
|
||||
focus: false,
|
||||
kind: gpui::WindowKind::PopUp,
|
||||
is_movable: true,
|
||||
screen: None,
|
||||
},
|
||||
|_cx| DummyView,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type ProjectItemBuilders = HashMap<
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue