mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Merge pull request #1817 from zed-industries/show-notifications-on-all-screens
Show call notifications on all screens
This commit is contained in:
commit
4412217f51
10 changed files with 145 additions and 63 deletions
|
@ -18,34 +18,37 @@ pub fn init(cx: &mut MutableAppContext) {
|
|||
|
||||
let mut incoming_call = ActiveCall::global(cx).read(cx).incoming();
|
||||
cx.spawn(|mut cx| async move {
|
||||
let mut notification_window = None;
|
||||
let mut notification_windows = Vec::new();
|
||||
while let Some(incoming_call) = incoming_call.next().await {
|
||||
if let Some(window_id) = notification_window.take() {
|
||||
for window_id in notification_windows.drain(..) {
|
||||
cx.remove_window(window_id);
|
||||
}
|
||||
|
||||
if let Some(incoming_call) = incoming_call {
|
||||
const PADDING: f32 = 16.;
|
||||
let screen_size = cx.platform().screen_size();
|
||||
|
||||
let window_size = cx.read(|cx| {
|
||||
let theme = &cx.global::<Settings>().theme.incoming_call_notification;
|
||||
vec2f(theme.window_width, theme.window_height)
|
||||
});
|
||||
let (window_id, _) = cx.add_window(
|
||||
WindowOptions {
|
||||
bounds: WindowBounds::Fixed(RectF::new(
|
||||
vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
|
||||
window_size,
|
||||
)),
|
||||
titlebar: None,
|
||||
center: false,
|
||||
kind: WindowKind::PopUp,
|
||||
is_movable: false,
|
||||
},
|
||||
|_| IncomingCallNotification::new(incoming_call),
|
||||
);
|
||||
notification_window = Some(window_id);
|
||||
|
||||
for screen in cx.platform().screens() {
|
||||
let screen_size = screen.size();
|
||||
let (window_id, _) = cx.add_window(
|
||||
WindowOptions {
|
||||
bounds: WindowBounds::Fixed(RectF::new(
|
||||
vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
|
||||
window_size,
|
||||
)),
|
||||
titlebar: None,
|
||||
center: false,
|
||||
kind: WindowKind::PopUp,
|
||||
is_movable: false,
|
||||
screen: Some(screen),
|
||||
},
|
||||
|_| IncomingCallNotification::new(incoming_call.clone()),
|
||||
);
|
||||
notification_windows.push(window_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -27,39 +27,49 @@ pub fn init(cx: &mut MutableAppContext) {
|
|||
worktree_root_names,
|
||||
} => {
|
||||
const PADDING: f32 = 16.;
|
||||
let screen_size = cx.platform().screen_size();
|
||||
|
||||
let theme = &cx.global::<Settings>().theme.project_shared_notification;
|
||||
let window_size = vec2f(theme.window_width, theme.window_height);
|
||||
let (window_id, _) = cx.add_window(
|
||||
WindowOptions {
|
||||
bounds: WindowBounds::Fixed(RectF::new(
|
||||
vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
|
||||
window_size,
|
||||
)),
|
||||
titlebar: None,
|
||||
center: false,
|
||||
kind: WindowKind::PopUp,
|
||||
is_movable: false,
|
||||
},
|
||||
|_| {
|
||||
ProjectSharedNotification::new(
|
||||
owner.clone(),
|
||||
*project_id,
|
||||
worktree_root_names.clone(),
|
||||
)
|
||||
},
|
||||
);
|
||||
notification_windows.insert(*project_id, window_id);
|
||||
|
||||
for screen in cx.platform().screens() {
|
||||
let screen_size = screen.size();
|
||||
let (window_id, _) = cx.add_window(
|
||||
WindowOptions {
|
||||
bounds: WindowBounds::Fixed(RectF::new(
|
||||
vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
|
||||
window_size,
|
||||
)),
|
||||
titlebar: None,
|
||||
center: false,
|
||||
kind: WindowKind::PopUp,
|
||||
is_movable: false,
|
||||
screen: Some(screen),
|
||||
},
|
||||
|_| {
|
||||
ProjectSharedNotification::new(
|
||||
owner.clone(),
|
||||
*project_id,
|
||||
worktree_root_names.clone(),
|
||||
)
|
||||
},
|
||||
);
|
||||
notification_windows
|
||||
.entry(*project_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(window_id);
|
||||
}
|
||||
}
|
||||
room::Event::RemoteProjectUnshared { project_id } => {
|
||||
if let Some(window_id) = notification_windows.remove(&project_id) {
|
||||
cx.remove_window(window_id);
|
||||
if let Some(window_ids) = notification_windows.remove(&project_id) {
|
||||
for window_id in window_ids {
|
||||
cx.remove_window(window_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
room::Event::Left => {
|
||||
for (_, window_id) in notification_windows.drain() {
|
||||
cx.remove_window(window_id);
|
||||
for (_, window_ids) in notification_windows.drain() {
|
||||
for window_id in window_ids {
|
||||
cx.remove_window(window_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -25,7 +25,7 @@ use postage::oneshot;
|
|||
use serde::Deserialize;
|
||||
use std::{
|
||||
any::Any,
|
||||
fmt::{self, Display},
|
||||
fmt::{self, Debug, Display},
|
||||
ops::Range,
|
||||
path::{Path, PathBuf},
|
||||
rc::Rc,
|
||||
|
@ -44,7 +44,7 @@ pub trait Platform: Send + Sync {
|
|||
fn unhide_other_apps(&self);
|
||||
fn quit(&self);
|
||||
|
||||
fn screen_size(&self) -> Vector2F;
|
||||
fn screens(&self) -> Vec<Rc<dyn Screen>>;
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
|
@ -115,6 +115,11 @@ pub trait InputHandler {
|
|||
fn rect_for_range(&self, range_utf16: Range<usize>) -> Option<RectF>;
|
||||
}
|
||||
|
||||
pub trait Screen: Debug {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn size(&self) -> Vector2F;
|
||||
}
|
||||
|
||||
pub trait Window {
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>);
|
||||
|
@ -149,6 +154,7 @@ pub struct WindowOptions<'a> {
|
|||
pub center: bool,
|
||||
pub kind: WindowKind,
|
||||
pub is_movable: bool,
|
||||
pub screen: Option<Rc<dyn Screen>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -292,6 +298,7 @@ impl<'a> Default for WindowOptions<'a> {
|
|||
center: false,
|
||||
kind: WindowKind::Normal,
|
||||
is_movable: true,
|
||||
screen: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ mod geometry;
|
|||
mod image_cache;
|
||||
mod platform;
|
||||
mod renderer;
|
||||
mod screen;
|
||||
mod sprite_cache;
|
||||
mod status_item;
|
||||
mod window;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use super::{
|
||||
event::key_to_native, status_item::StatusItem, BoolExt as _, Dispatcher, FontSystem, Window,
|
||||
event::key_to_native, screen::Screen, status_item::StatusItem, BoolExt as _, Dispatcher,
|
||||
FontSystem, Window,
|
||||
};
|
||||
use crate::{
|
||||
executor,
|
||||
geometry::vector::{vec2f, Vector2F},
|
||||
keymap,
|
||||
executor, keymap,
|
||||
platform::{self, CursorStyle},
|
||||
Action, AppVersion, ClipboardItem, Event, Menu, MenuItem,
|
||||
};
|
||||
|
@ -14,7 +13,7 @@ use cocoa::{
|
|||
appkit::{
|
||||
NSApplication, NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
|
||||
NSEventModifierFlags, NSMenu, NSMenuItem, NSModalResponse, NSOpenPanel, NSPasteboard,
|
||||
NSPasteboardTypeString, NSSavePanel, NSScreen, NSWindow,
|
||||
NSPasteboardTypeString, NSSavePanel, NSWindow,
|
||||
},
|
||||
base::{id, nil, selector, YES},
|
||||
foundation::{
|
||||
|
@ -488,12 +487,11 @@ impl platform::Platform for MacPlatform {
|
|||
}
|
||||
}
|
||||
|
||||
fn screen_size(&self) -> Vector2F {
|
||||
unsafe {
|
||||
let screen = NSScreen::mainScreen(nil);
|
||||
let frame = NSScreen::frame(screen);
|
||||
vec2f(frame.size.width as f32, frame.size.height as f32)
|
||||
}
|
||||
fn screens(&self) -> Vec<Rc<dyn platform::Screen>> {
|
||||
Screen::all()
|
||||
.into_iter()
|
||||
.map(|screen| Rc::new(screen) as Rc<_>)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
|
|
|
@ -189,7 +189,15 @@ impl Renderer {
|
|||
pub fn render(&mut self, scene: &Scene) {
|
||||
let layer = self.layer.clone();
|
||||
let drawable_size = layer.drawable_size();
|
||||
let drawable = layer.next_drawable().unwrap();
|
||||
let drawable = if let Some(drawable) = layer.next_drawable() {
|
||||
drawable
|
||||
} else {
|
||||
log::error!(
|
||||
"failed to retrieve next drawable, drawable size: {:?}",
|
||||
drawable_size
|
||||
);
|
||||
return;
|
||||
};
|
||||
let command_queue = self.command_queue.clone();
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
|
||||
|
|
44
crates/gpui/src/platform/mac/screen.rs
Normal file
44
crates/gpui/src/platform/mac/screen.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use std::any::Any;
|
||||
|
||||
use crate::{
|
||||
geometry::vector::{vec2f, Vector2F},
|
||||
platform,
|
||||
};
|
||||
use cocoa::{
|
||||
appkit::NSScreen,
|
||||
base::{id, nil},
|
||||
foundation::NSArray,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Screen {
|
||||
pub(crate) native_screen: id,
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
pub fn all() -> Vec<Self> {
|
||||
let mut screens = Vec::new();
|
||||
unsafe {
|
||||
let native_screens = NSScreen::screens(nil);
|
||||
for ix in 0..native_screens.count() {
|
||||
screens.push(Screen {
|
||||
native_screen: native_screens.objectAtIndex(ix),
|
||||
});
|
||||
}
|
||||
}
|
||||
screens
|
||||
}
|
||||
}
|
||||
|
||||
impl platform::Screen for Screen {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn size(&self) -> Vector2F {
|
||||
unsafe {
|
||||
let frame = self.native_screen.frame();
|
||||
vec2f(frame.size.width as f32, frame.size.height as f32)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
mac::platform::NSViewLayerContentsRedrawDuringViewResize,
|
||||
platform::{
|
||||
self,
|
||||
mac::{geometry::RectFExt, renderer::Renderer},
|
||||
mac::{geometry::RectFExt, renderer::Renderer, screen::Screen},
|
||||
Event, WindowBounds,
|
||||
},
|
||||
InputHandler, KeyDownEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
|
||||
|
@ -377,11 +377,17 @@ impl Window {
|
|||
msg_send![PANEL_CLASS, alloc]
|
||||
}
|
||||
};
|
||||
let native_window = native_window.initWithContentRect_styleMask_backing_defer_(
|
||||
let native_window = native_window.initWithContentRect_styleMask_backing_defer_screen_(
|
||||
RectF::new(Default::default(), vec2f(1024., 768.)).to_ns_rect(),
|
||||
style_mask,
|
||||
NSBackingStoreBuffered,
|
||||
NO,
|
||||
options
|
||||
.screen
|
||||
.and_then(|screen| {
|
||||
Some(screen.as_any().downcast_ref::<Screen>()?.native_screen)
|
||||
})
|
||||
.unwrap_or(nil),
|
||||
);
|
||||
assert!(!native_window.is_null());
|
||||
|
||||
|
@ -400,8 +406,12 @@ impl Window {
|
|||
- top_left_bounds.height(),
|
||||
),
|
||||
top_left_bounds.size(),
|
||||
)
|
||||
.to_ns_rect();
|
||||
native_window.setFrame_display_(
|
||||
native_window.convertRectToScreen_(bottom_left_bounds),
|
||||
YES,
|
||||
);
|
||||
native_window.setFrame_display_(bottom_left_bounds.to_ns_rect(), YES);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,8 +131,8 @@ impl super::Platform for Platform {
|
|||
|
||||
fn quit(&self) {}
|
||||
|
||||
fn screen_size(&self) -> Vector2F {
|
||||
vec2f(1024., 768.)
|
||||
fn screens(&self) -> Vec<Rc<dyn crate::Screen>> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
|
|
|
@ -344,6 +344,7 @@ pub fn build_window_options() -> WindowOptions<'static> {
|
|||
center: false,
|
||||
kind: WindowKind::Normal,
|
||||
is_movable: true,
|
||||
screen: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue