Detailed changes
@@ -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();
@@ -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,
}
}