From 34eb2c446f5b4653ecac4a628c338543d3580ff4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 5 Aug 2021 11:48:35 -0600 Subject: [PATCH] Start on custom titlebar --- gpui/examples/text.rs | 2 +- gpui/src/app.rs | 47 +++++++++-------- gpui/src/platform.rs | 2 + gpui/src/platform/mac/window.rs | 9 +++- zed/src/editor.rs | 93 ++++++++++++++++++++++++--------- zed/src/workspace.rs | 27 +++++++--- 6 files changed, 125 insertions(+), 55 deletions(-) diff --git a/gpui/examples/text.rs b/gpui/examples/text.rs index 45aa5931129ed43f9e6bf76a1063392827063ed1..08959b77a2f72652ed609e95c92d77be075e4c71 100644 --- a/gpui/examples/text.rs +++ b/gpui/examples/text.rs @@ -12,7 +12,7 @@ fn main() { gpui::App::new(()).unwrap().run(|cx| { cx.platform().activate(true); - cx.add_window(|_| TextView); + cx.add_window(Default::default(), |_| TextView); }); } diff --git a/gpui/src/app.rs b/gpui/src/app.rs index 579bf5c4682dba2fcfbe15d48166396f3a9ea81d..8df38af0d47300d37bef7b1a6206dfbb95fd9c69 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -12,7 +12,6 @@ use anyhow::{anyhow, Result}; use async_task::Task; use keymap::MatchResult; use parking_lot::{Mutex, RwLock}; -use pathfinder_geometry::{rect::RectF, vector::vec2f}; use platform::Event; use postage::{mpsc, sink::Sink as _, stream::Stream as _}; use smol::prelude::*; @@ -300,7 +299,9 @@ impl TestAppContext { T: View, F: FnOnce(&mut ViewContext) -> T, { - self.cx.borrow_mut().add_window(build_root_view) + self.cx + .borrow_mut() + .add_window(Default::default(), build_root_view) } pub fn window_ids(&self) -> Vec { @@ -959,7 +960,11 @@ impl MutableAppContext { handle } - pub fn add_window(&mut self, build_root_view: F) -> (usize, ViewHandle) + pub fn add_window( + &mut self, + window_options: WindowOptions, + build_root_view: F, + ) -> (usize, ViewHandle) where T: View, F: FnOnce(&mut ViewContext) -> T, @@ -976,7 +981,7 @@ impl MutableAppContext { invalidation: None, }, ); - self.open_platform_window(window_id); + self.open_platform_window(window_id, window_options); root_view.update(self, |view, cx| { view.on_focus(cx); cx.notify(); @@ -992,15 +997,11 @@ impl MutableAppContext { self.remove_dropped_entities(); } - fn open_platform_window(&mut self, window_id: usize) { - let mut window = self.cx.platform.open_window( - window_id, - WindowOptions { - bounds: RectF::new(vec2f(0., 0.), vec2f(1024., 768.)), - title: "Zed".into(), - }, - self.foreground.clone(), - ); + fn open_platform_window(&mut self, window_id: usize, window_options: WindowOptions) { + let mut window = + self.cx + .platform + .open_window(window_id, window_options, self.foreground.clone()); let text_layout_cache = TextLayoutCache::new(self.cx.platform.fonts()); let presenter = Rc::new(RefCell::new(Presenter::new( window_id, @@ -3070,7 +3071,7 @@ mod tests { } } - let (window_id, _) = cx.add_window(|cx| View::new(None, cx)); + let (window_id, _) = cx.add_window(Default::default(), |cx| View::new(None, cx)); let handle_1 = cx.add_view(window_id, |cx| View::new(None, cx)); let handle_2 = cx.add_view(window_id, |cx| View::new(Some(handle_1.clone()), cx)); assert_eq!(cx.cx.views.len(), 3); @@ -3126,7 +3127,7 @@ mod tests { } let mouse_down_count = Arc::new(AtomicUsize::new(0)); - let (window_id, _) = cx.add_window(|_| View { + let (window_id, _) = cx.add_window(Default::default(), |_| View { mouse_down_count: mouse_down_count.clone(), }); let presenter = cx.presenters_and_platform_windows[&window_id].0.clone(); @@ -3184,7 +3185,7 @@ mod tests { released: model_released.clone(), }); - let (window_id, _) = cx.add_window(|_| View { + let (window_id, _) = cx.add_window(Default::default(), |_| View { released: view_released.clone(), }); @@ -3227,7 +3228,7 @@ mod tests { type Event = usize; } - let (window_id, handle_1) = cx.add_window(|_| View::default()); + let (window_id, handle_1) = cx.add_window(Default::default(), |_| View::default()); let handle_2 = cx.add_view(window_id, |_| View::default()); let handle_2b = handle_2.clone(); let handle_3 = cx.add_model(|_| Model); @@ -3280,7 +3281,7 @@ mod tests { type Event = (); } - let (window_id, _) = cx.add_window(|_| View); + let (window_id, _) = cx.add_window(Default::default(), |_| View); let observing_view = cx.add_view(window_id, |_| View); let emitting_view = cx.add_view(window_id, |_| View); let observing_model = cx.add_model(|_| Model); @@ -3333,7 +3334,7 @@ mod tests { type Event = (); } - let (_, view) = cx.add_window(|_| View::default()); + let (_, view) = cx.add_window(Default::default(), |_| View::default()); let model = cx.add_model(|_| Model::default()); view.update(cx, |_, c| { @@ -3373,7 +3374,7 @@ mod tests { type Event = (); } - let (window_id, _) = cx.add_window(|_| View); + let (window_id, _) = cx.add_window(Default::default(), |_| View); let observing_view = cx.add_view(window_id, |_| View); let observing_model = cx.add_model(|_| Model); let observed_model = cx.add_model(|_| Model); @@ -3423,7 +3424,7 @@ mod tests { } let events: Arc>> = Default::default(); - let (window_id, view_1) = cx.add_window(|_| View { + let (window_id, view_1) = cx.add_window(Default::default(), |_| View { events: events.clone(), name: "view 1".to_string(), }); @@ -3533,7 +3534,7 @@ mod tests { actions_clone.borrow_mut().push(format!("{} d", view.id)); }); - let (window_id, view_1) = cx.add_window(|_| ViewA { id: 1 }); + let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 }); let view_2 = cx.add_view(window_id, |_| ViewB { id: 2 }); let view_3 = cx.add_view(window_id, |_| ViewA { id: 3 }); let view_4 = cx.add_view(window_id, |_| ViewB { id: 4 }); @@ -3613,7 +3614,7 @@ mod tests { view_2.keymap_context.set.insert("b".into()); view_3.keymap_context.set.insert("c".into()); - let (window_id, view_1) = cx.add_window(|_| view_1); + let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1); let view_2 = cx.add_view(window_id, |_| view_2); let view_3 = cx.add_view(window_id, |_| view_3); diff --git a/gpui/src/platform.rs b/gpui/src/platform.rs index 7107d7763dd373383d874cb90421c4eedd2d0ca2..62225d66e8343a4587abe7690a212227f9c3927f 100644 --- a/gpui/src/platform.rs +++ b/gpui/src/platform.rs @@ -95,9 +95,11 @@ pub trait WindowContext { fn present_scene(&mut self, scene: Scene); } +#[derive(Default)] pub struct WindowOptions<'a> { pub bounds: RectF, pub title: Option<&'a str>, + pub titlebar_appears_transparent: bool, } pub struct PathPromptOptions { diff --git a/gpui/src/platform/mac/window.rs b/gpui/src/platform/mac/window.rs index b1d86acb12e7b358ce747a22f0d32e5c4ff0e270..56969e80892f34266d72ec8cd166825f3a61a658 100644 --- a/gpui/src/platform/mac/window.rs +++ b/gpui/src/platform/mac/window.rs @@ -153,11 +153,15 @@ impl Window { let pool = NSAutoreleasePool::new(nil); let frame = options.bounds.to_ns_rect(); - let style_mask = NSWindowStyleMask::NSClosableWindowMask + let mut style_mask = NSWindowStyleMask::NSClosableWindowMask | NSWindowStyleMask::NSMiniaturizableWindowMask | NSWindowStyleMask::NSResizableWindowMask | NSWindowStyleMask::NSTitledWindowMask; + if options.titlebar_appears_transparent { + style_mask |= NSWindowStyleMask::NSFullSizeContentViewWindowMask; + } + let native_window: id = msg_send![WINDOW_CLASS, alloc]; let native_window = native_window.initWithContentRect_styleMask_backing_defer_( frame, @@ -213,6 +217,9 @@ impl Window { if let Some(title) = options.title.as_ref() { native_window.setTitle_(NSString::alloc(nil).init_str(title)); } + if options.titlebar_appears_transparent { + native_window.setTitlebarAppearsTransparent_(YES); + } native_window.setAcceptsMouseMovedEvents_(YES); native_view.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable); diff --git a/zed/src/editor.rs b/zed/src/editor.rs index d5507f38c9a17b2be23a38e24c0c3182dd3809f1..b3dc4f8a2b860389c1d816a7744ec154cb0b6ec5 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -2659,7 +2659,9 @@ mod tests { fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, editor) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, editor) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); editor.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(2, 2), false, cx); @@ -2725,7 +2727,9 @@ mod tests { fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(2, 2), false, cx); @@ -2757,7 +2761,9 @@ mod tests { fn test_cancel(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(3, 4), false, cx); @@ -2801,8 +2807,9 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6), cx)); let settings = settings::channel(&font_cache).unwrap().1; - let (_, editor) = - cx.add_window(|cx| Editor::for_buffer(buffer.clone(), settings.clone(), cx)); + let (_, editor) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings.clone(), cx) + }); let layouts = editor.update(cx, |editor, cx| { editor @@ -2846,7 +2853,9 @@ mod tests { ) }); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer.clone(), settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx) @@ -2912,7 +2921,9 @@ mod tests { fn test_move_cursor(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6), cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer.clone(), settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings, cx) + }); buffer.update(cx, |buffer, cx| { buffer.edit( @@ -2987,7 +2998,9 @@ mod tests { fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer.clone(), settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings, cx) + }); assert_eq!('ⓐ'.len_utf8(), 3); assert_eq!('α'.len_utf8(), 2); @@ -3043,7 +3056,9 @@ mod tests { fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer.clone(), settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx) .unwrap(); @@ -3072,7 +3087,9 @@ mod tests { fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, "abc\n def", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( &[ @@ -3215,7 +3232,9 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, "use std::str::{foo, bar}\n\n {baz.qux()}", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( &[ @@ -3401,7 +3420,9 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, "use one::{\n two::three::four::five\n};", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.set_wrap_width(140., cx); @@ -3461,7 +3482,9 @@ mod tests { ) }); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer.clone(), settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( @@ -3495,7 +3518,9 @@ mod tests { ) }); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer.clone(), settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( @@ -3523,7 +3548,9 @@ mod tests { fn test_delete_line(cx: &mut gpui::MutableAppContext) { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( &[ @@ -3547,7 +3574,9 @@ mod tests { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx) .unwrap(); @@ -3564,7 +3593,9 @@ mod tests { fn test_duplicate_line(cx: &mut gpui::MutableAppContext) { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( &[ @@ -3591,7 +3622,9 @@ mod tests { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( &[ @@ -3617,7 +3650,9 @@ mod tests { fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(10, 5), cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.fold_ranges( vec![ @@ -3700,7 +3735,9 @@ mod tests { let buffer = cx.add_model(|cx| Buffer::new(0, "one two three four five six ", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; let view = cx - .add_window(|cx| Editor::for_buffer(buffer.clone(), settings, cx)) + .add_window(Default::default(), |cx| { + Editor::for_buffer(buffer.clone(), settings, cx) + }) .1; // Cut with three selections. Clipboard text is divided into three slices. @@ -3832,7 +3869,9 @@ mod tests { fn test_select_all(cx: &mut gpui::MutableAppContext) { let buffer = cx.add_model(|cx| Buffer::new(0, "abc\nde\nfgh", cx)); let settings = settings::channel(&cx.font_cache()).unwrap().1; - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_all(&(), cx); assert_eq!( @@ -3846,7 +3885,9 @@ mod tests { fn test_select_line(cx: &mut gpui::MutableAppContext) { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 5), cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges( &[ @@ -3892,7 +3933,9 @@ mod tests { fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(9, 5), cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.fold_ranges( vec![ @@ -3957,7 +4000,9 @@ mod tests { fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) { let settings = settings::channel(&cx.font_cache()).unwrap().1; let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndefghi\n\njk\nlmno\n", cx)); - let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings, cx)); + let (_, view) = cx.add_window(Default::default(), |cx| { + Editor::for_buffer(buffer, settings, cx) + }); view.update(cx, |view, cx| { view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx) diff --git a/zed/src/workspace.rs b/zed/src/workspace.rs index cb543522d8d348e9dd1b39eb2034ddb3974ceb33..9badef458e00559eb808144d4b67777ecaf8893b 100644 --- a/zed/src/workspace.rs +++ b/zed/src/workspace.rs @@ -12,9 +12,14 @@ use crate::{ }; use anyhow::{anyhow, Result}; use gpui::{ - elements::*, json::to_string_pretty, keymap::Binding, AnyViewHandle, AppContext, ClipboardItem, - Entity, ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext, Task, - View, ViewContext, ViewHandle, WeakModelHandle, + elements::*, + geometry::{rect::RectF, vector::vec2f}, + json::to_string_pretty, + keymap::Binding, + platform::WindowOptions, + AnyViewHandle, AppContext, ClipboardItem, Entity, ModelHandle, MutableAppContext, + PathPromptOptions, PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle, + WeakModelHandle, }; use log::error; pub use pane::*; @@ -93,12 +98,14 @@ fn open_paths(params: &OpenParams, cx: &mut MutableAppContext) -> Task<()> { log::info!("open new workspace"); // Add a new workspace if necessary - let (_, workspace) = cx.add_window(|cx| Workspace::new(¶ms.app_state, cx)); + + let (_, workspace) = + cx.add_window(window_options(), |cx| Workspace::new(¶ms.app_state, cx)); workspace.update(cx, |workspace, cx| workspace.open_paths(¶ms.paths, cx)) } fn open_new(app_state: &Arc, cx: &mut MutableAppContext) { - cx.add_window(|cx| { + cx.add_window(window_options(), |cx| { let mut view = Workspace::new(app_state.as_ref(), cx); view.open_new_file(&app_state, cx); view @@ -106,13 +113,21 @@ fn open_new(app_state: &Arc, cx: &mut MutableAppContext) { } fn join_worktree(app_state: &Arc, cx: &mut MutableAppContext) { - cx.add_window(|cx| { + cx.add_window(window_options(), |cx| { let mut view = Workspace::new(app_state.as_ref(), cx); view.join_worktree(&app_state, cx); view }); } +fn window_options() -> WindowOptions<'static> { + WindowOptions { + bounds: RectF::new(vec2f(0., 0.), vec2f(1024., 768.)), + title: None, + titlebar_appears_transparent: true, + } +} + pub trait Item: Entity + Sized { type View: ItemView;