Compare commits

...

100 Commits

Author SHA1 Message Date
Conrad Irwin
3f3f5c6ebd Merge branch 'main' into restore-max 2024-05-07 10:08:49 -06:00
Junkui Zhang
e9df71b124 fix linux BorrowMutError 2024-05-06 11:15:36 +08:00
Junkui Zhang
23997f3331 fixs 2024-05-05 23:41:55 +08:00
Junkui Zhang
ca6285bbe6 rename window_bounds() to bounds(), restore_status() to window_bounds() 2024-05-05 23:41:55 +08:00
Junkui Zhang
4d19d22b3f fix example 2024-05-05 23:41:55 +08:00
Junkui Zhang
f1c097568f update wayland 2024-05-05 23:41:55 +08:00
Junkui Zhang
2b00564518 revert macOS maximized impl 2024-05-05 23:41:54 +08:00
Junkui Zhang
33da303148 add comments 2024-05-05 23:41:54 +08:00
Junkui Zhang
4d656dba84 update editor_tests 2024-05-05 23:41:54 +08:00
Junkui Zhang
ca5dfaed8c update storybook 2024-05-05 23:41:54 +08:00
Junkui Zhang
74cb91ee7d fix 2024-05-05 23:41:54 +08:00
Junkui Zhang
22b1760486 update macOS 2024-05-05 23:41:54 +08:00
Junkui Zhang
3560bf7e51 update linux 2024-05-05 23:41:19 +08:00
Junkui Zhang
38f889ac97 update examples 2024-05-05 23:41:19 +08:00
Junkui Zhang
9a1bbb2dd3 update test_context 2024-05-05 23:41:19 +08:00
Junkui Zhang
7debce8b4b update x11/window.rs 2024-05-05 23:41:19 +08:00
Junkui Zhang
8d8490b79a update tests 2024-05-05 23:41:19 +08:00
Junkui Zhang
afe58e42ba remove unused import 2024-05-05 23:41:18 +08:00
Junkui Zhang
fadbf4690a rename SerializedWindowOpenStatus to SerializedWindowBounds 2024-05-05 23:41:18 +08:00
Junkui Zhang
eb9da1888b update zed.rs 2024-05-05 23:41:18 +08:00
Junkui Zhang
e7bc90ef91 update collab_ui 2024-05-05 23:41:18 +08:00
Junkui Zhang
a06ce20503 udpate collab_ui 2024-05-05 23:41:18 +08:00
Junkui Zhang
5b6899a226 update workspace 2024-05-05 23:41:18 +08:00
Junkui Zhang
b5ae7bc893 update SerializedWindowOpenStatus 2024-05-05 23:41:18 +08:00
Junkui Zhang
8b4273ee5e rename WindowOpenStatue to WindowBounds 2024-05-05 23:41:18 +08:00
Junkui Zhang
9eeb45d67b fix merge conficts 2024-05-05 23:41:18 +08:00
Junkui Zhang
04e8a44c23 remove macOS function 2024-05-05 23:41:18 +08:00
Junkui Zhang
cfbbaeab50 remove is_minimized 2024-05-05 23:41:18 +08:00
Junkui Zhang
1486fe0a59 remove unneeded is_minimized 2024-05-05 23:41:18 +08:00
Junkui Zhang
af26d6bbcf remove comments 2024-05-05 23:41:18 +08:00
Junkui Zhang
882ced6949 update windows::window 2024-05-05 23:41:18 +08:00
Junkui Zhang
f39e977363 remove unneeded restore bounds 2024-05-05 23:41:18 +08:00
Junkui Zhang
107dd9081d fix error 2024-05-05 23:41:18 +08:00
Junkui Zhang
7502b46c1f revert some changes 2024-05-05 23:41:18 +08:00
Junkui Zhang
ee9579a84f update wayland 2024-05-05 23:41:18 +08:00
Junkui Zhang
b9818c6984 update test 2024-05-05 23:41:17 +08:00
Junkui Zhang
7f7755af68 update 2024-05-05 23:41:17 +08:00
Junkui Zhang
5bfb26510f update rename 2024-05-05 23:41:17 +08:00
Junkui Zhang
a32346db25 fix 2024-05-05 23:41:17 +08:00
Junkui Zhang
8d0d02b887 update wayland 2024-05-05 23:41:17 +08:00
Junkui Zhang
06f3f52159 rename FullScreen to Fullscreen 2024-05-05 23:41:17 +08:00
Junkui Zhang
2a3048aca7 update Workspace 2024-05-05 23:41:17 +08:00
Junkui Zhang
f2cf9fefe7 remove unused 2024-05-05 23:41:17 +08:00
Junkui Zhang
dab7b8220b update WaylandWindow 2024-05-05 23:41:17 +08:00
Junkui Zhang
1e9fd8364d udpate MacWindow 2024-05-05 23:41:17 +08:00
Junkui Zhang
ae1428679a update X11Window 2024-05-05 23:41:17 +08:00
Junkui Zhang
80628911b2 update MacWindow 2024-05-05 23:41:17 +08:00
Junkui Zhang
040babebf9 update TestWindow 2024-05-05 23:41:17 +08:00
Junkui Zhang
9032a8b111 update linux 2024-05-05 23:41:17 +08:00
Junkui Zhang
b9228f1dc1 update Windows 2024-05-05 23:41:17 +08:00
Junkui Zhang
d4b7e88aeb refactor window open action 2024-05-05 23:41:17 +08:00
Junkui Zhang
7275d61f82 revert WindowParams 2024-05-05 23:41:17 +08:00
Junkui Zhang
451cd47a7e fix x11 2024-05-05 23:41:00 +08:00
Junkui Zhang
68d1ccfeb1 Linux init 2024-05-05 23:41:00 +08:00
Junkui Zhang
0c17f691c0 remove debug print 2024-05-05 23:41:00 +08:00
Junkui Zhang
d130d3e02e fix fullscreen 2024-05-05 23:41:00 +08:00
Junkui Zhang
d541a75e3c fix err 2024-05-05 23:41:00 +08:00
Junkui Zhang
1ccad5b078 fix db error 2024-05-05 23:41:00 +08:00
Junkui Zhang
696d496367 move maximize 2024-05-05 23:41:00 +08:00
Junkui Zhang
20d9a3e8db macOS init 2024-05-05 23:41:00 +08:00
Junkui Zhang
691a2e983d update macOS 2024-05-05 23:41:00 +08:00
Junkui Zhang
2c5a7ddd00 macOS init 2024-05-05 23:40:43 +08:00
Junkui Zhang
2b2d5ea813 fmt 2024-05-05 23:40:43 +08:00
Junkui Zhang
8b8ef5fbe4 fix story book 2024-05-05 23:40:43 +08:00
Junkui Zhang
03c60f943e fix workspace 2024-05-05 23:40:42 +08:00
Junkui Zhang
48f875f9d8 try fix test 2024-05-05 23:40:42 +08:00
Junkui Zhang
b0d43e51bb try fix test 2024-05-05 23:40:42 +08:00
Junkui Zhang
92481a93aa use bounds 2024-05-05 23:40:42 +08:00
Junkui Zhang
300121f5cc update tests 2024-05-05 23:40:42 +08:00
Junkui Zhang
056adae16c remove debug print 2024-05-05 23:40:42 +08:00
Junkui Zhang
24e07874b3 catch up main branch changes 2024-05-05 23:40:42 +08:00
Junkui Zhang
fbd87c96d0 remember fullscreen restore size 2024-05-05 23:40:42 +08:00
Junkui Zhang
dabce12916 add get_bounds 2024-05-05 23:40:42 +08:00
Junkui Zhang
84369f3e4b remove unused variables 2024-05-05 23:40:42 +08:00
Junkui Zhang
d54ba0e579 use GetWindowPlacement to retrieve information needed 2024-05-05 23:40:42 +08:00
Junkui Zhang
7fca2173ce try another approch 2024-05-05 23:40:42 +08:00
Junkui Zhang
8034b76867 windows impl 2024-05-05 23:40:42 +08:00
Junkui Zhang
de38629efb fix 2024-05-05 23:40:42 +08:00
Junkui Zhang
7a4f6677cc update windows impl 2024-05-05 23:40:42 +08:00
Junkui Zhang
0cd31c8da3 report restore size 2024-05-05 23:40:42 +08:00
Junkui Zhang
2410470d72 change function 2024-05-05 23:40:42 +08:00
Junkui Zhang
ab6ff3ffcc update windows window creatation 2024-05-05 23:40:42 +08:00
Junkui Zhang
f261cf513a udpate serialization and deserial 2024-05-05 23:40:42 +08:00
Junkui Zhang
b1c01ef45c add restore size 2024-05-05 23:40:42 +08:00
Junkui Zhang
8616381ed9 remove fullscreen 2024-05-05 23:40:42 +08:00
Junkui Zhang
66d702922e remove unused 2024-05-05 23:40:42 +08:00
Junkui Zhang
0386f76e55 fix bug 2024-05-05 23:40:42 +08:00
Junkui Zhang
ae8f9ad22f fix zed.rs 2024-05-05 23:40:41 +08:00
Junkui Zhang
608469eca8 fix typo 2024-05-05 23:40:41 +08:00
Junkui Zhang
9fe0184cad try fix test 2024-05-05 23:40:41 +08:00
Junkui Zhang
4669b14c57 fix workspace_for_roots 2024-05-05 23:40:41 +08:00
Junkui Zhang
40fe820aae fix typo 2024-05-05 23:40:41 +08:00
Junkui Zhang
ea086316ed fix join project 2024-05-05 23:40:41 +08:00
Junkui Zhang
c62970a6cc update SerializedWorkspace 2024-05-05 23:40:41 +08:00
Junkui Zhang
218a7e2b69 impl serialization 2024-05-05 23:40:41 +08:00
Junkui Zhang
a8b9393477 fix gpui::window 2024-05-05 23:40:41 +08:00
Junkui Zhang
6c4d5bcbd5 fix Windows impl 2024-05-05 23:40:41 +08:00
Junkui Zhang
e72b94bbbf fix collab 2024-05-05 23:40:41 +08:00
Junkui Zhang
49e085037e change WindowParams and WindowOptions 2024-05-05 23:40:41 +08:00
Junkui Zhang
7c0ea926f0 init 2024-05-05 23:40:09 +08:00
19 changed files with 306 additions and 227 deletions

View File

@@ -14,7 +14,7 @@ pub use collab_panel::CollabPanel;
pub use collab_titlebar_item::CollabTitlebarItem;
use gpui::{
actions, point, AppContext, DevicePixels, Pixels, PlatformDisplay, Size, Task,
WindowBackgroundAppearance, WindowContext, WindowKind, WindowOptions,
WindowBackgroundAppearance, WindowBounds, WindowContext, WindowKind, WindowOptions,
};
use panel_settings::MessageEditorSettings;
pub use panel_settings::{
@@ -117,14 +117,13 @@ fn notification_window_options(
let app_id = ReleaseChannel::global(cx).app_id();
WindowOptions {
bounds: Some(bounds),
window_bounds: Some(WindowBounds::Windowed(bounds)),
titlebar: None,
focus: false,
show: true,
kind: WindowKind::PopUp,
is_movable: false,
display_id: Some(screen.id()),
fullscreen: false,
window_background: WindowBackgroundAppearance::default(),
app_id: Some(app_id.to_owned()),
}

View File

@@ -9,7 +9,7 @@ use crate::{
JoinLines,
};
use futures::StreamExt;
use gpui::{div, TestAppContext, VisualTestContext, WindowOptions};
use gpui::{div, TestAppContext, VisualTestContext, WindowBounds, WindowOptions};
use indoc::indoc;
use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent, LanguageSettingsContent},
@@ -7468,10 +7468,10 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
let follower = cx.update(|cx| {
cx.open_window(
WindowOptions {
bounds: Some(Bounds::from_corners(
window_bounds: Some(WindowBounds::Windowed(Bounds::from_corners(
gpui::Point::new(0.into(), 0.into()),
gpui::Point::new(10.into(), 80.into()),
)),
))),
..Default::default()
},
|cx| cx.new_view(|cx| build_editor(buffer.clone(), cx)),

View File

@@ -63,7 +63,11 @@ fn main() {
.with_assets(Assets {})
.run(|cx: &mut AppContext| {
let options = WindowOptions {
bounds: Some(Bounds::centered(None, size(px(300.), px(300.)), cx)),
window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
None,
size(px(300.), px(300.)),
cx,
))),
..Default::default()
};
cx.open_window(options, |cx| {

View File

@@ -26,7 +26,7 @@ fn main() {
let bounds = Bounds::centered(None, size(px(600.0), px(600.0)), cx);
cx.open_window(
WindowOptions {
bounds: Some(bounds),
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|cx| {

View File

@@ -79,10 +79,10 @@ fn main() {
..Default::default()
}),
bounds: Some(Bounds {
window_bounds: Some(WindowBounds::Windowed(Bounds {
size: size(px(1100.), px(600.)).into(),
origin: Point::new(DevicePixels::from(200), DevicePixels::from(200)),
}),
})),
..Default::default()
};

View File

@@ -43,7 +43,7 @@ fn main() {
WindowOptions {
// Set the bounds of the window in screen coordinates
bounds: Some(bounds),
window_bounds: Some(WindowBounds::Windowed(bounds)),
// Specify the display_id to ensure the window is created on the correct screen
display_id: Some(screen.id()),
@@ -53,7 +53,6 @@ fn main() {
show: true,
kind: WindowKind::PopUp,
is_movable: false,
fullscreen: false,
app_id: None,
}
};

View File

@@ -4,8 +4,8 @@ use crate::{
Element, Empty, Entity, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Model,
ModelContext, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent,
MouseUpEvent, Pixels, Platform, Point, Render, Result, Size, Task, TestDispatcher,
TestPlatform, TestWindow, TextSystem, View, ViewContext, VisualContext, WindowContext,
WindowHandle, WindowOptions,
TestPlatform, TestWindow, TextSystem, View, ViewContext, VisualContext, WindowBounds,
WindowContext, WindowHandle, WindowOptions,
};
use anyhow::{anyhow, bail};
use futures::{channel::oneshot, Stream, StreamExt};
@@ -188,7 +188,7 @@ impl TestAppContext {
let bounds = Bounds::maximized(None, &mut cx);
cx.open_window(
WindowOptions {
bounds: Some(bounds),
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|cx| cx.new_view(build_window),
@@ -201,7 +201,7 @@ impl TestAppContext {
let bounds = Bounds::maximized(None, &mut cx);
let window = cx.open_window(
WindowOptions {
bounds: Some(bounds),
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|cx| cx.new_view(|_| Empty),
@@ -224,7 +224,7 @@ impl TestAppContext {
let bounds = Bounds::maximized(None, &mut cx);
let window = cx.open_window(
WindowOptions {
bounds: Some(bounds),
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|cx| cx.new_view(build_root_view),

View File

@@ -184,7 +184,7 @@ unsafe impl Send for DisplayId {}
pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
fn bounds(&self) -> Bounds<DevicePixels>;
fn is_maximized(&self) -> bool;
fn is_minimized(&self) -> bool;
fn window_bounds(&self) -> WindowBounds;
fn content_size(&self) -> Size<Pixels>;
fn scale_factor(&self) -> f32;
fn appearance(&self) -> WindowAppearance;
@@ -515,9 +515,10 @@ pub trait InputHandler: 'static {
/// The variables that can be configured when creating a new window
#[derive(Debug)]
pub struct WindowOptions {
/// The bounds of the window in screen coordinates.
/// None -> inherit, Some(bounds) -> set bounds
pub bounds: Option<Bounds<DevicePixels>>,
/// Specifies the state and bounds of the window in screen coordinates.
/// - `None`: Inherit the bounds.
/// - `Some(WindowBounds)`: Open a window with corresponding state and its restore size.
pub window_bounds: Option<WindowBounds>,
/// The titlebar configuration of the window
pub titlebar: Option<TitlebarOptions>,
@@ -528,9 +529,6 @@ pub struct WindowOptions {
/// Whether the window should be shown when created
pub show: bool,
/// Whether the window should be fullscreen when created
pub fullscreen: bool,
/// The kind of window to create
pub kind: WindowKind,
@@ -571,10 +569,40 @@ pub(crate) struct WindowParams {
pub window_background: WindowBackgroundAppearance,
}
/// Represents the status of how a window should be opened.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum WindowBounds {
/// Indicates that the window should open in a windowed state with the given bounds.
Windowed(Bounds<DevicePixels>),
/// Indicates that the window should open in a maximized state.
/// The bounds provided here represent the restore size of the window.
Maximized(Bounds<DevicePixels>),
/// Indicates that the window should open in fullscreen mode.
/// The bounds provided here represent the restore size of the window.
Fullscreen(Bounds<DevicePixels>),
}
impl Default for WindowBounds {
fn default() -> Self {
WindowBounds::Windowed(Bounds::default())
}
}
impl WindowBounds {
/// Retrieve the inner bounds
pub fn get_bounds(&self) -> Bounds<DevicePixels> {
match self {
WindowBounds::Windowed(bounds) => *bounds,
WindowBounds::Maximized(bounds) => *bounds,
WindowBounds::Fullscreen(bounds) => *bounds,
}
}
}
impl Default for WindowOptions {
fn default() -> Self {
Self {
bounds: None,
window_bounds: None,
titlebar: Some(TitlebarOptions {
title: Default::default(),
appears_transparent: Default::default(),
@@ -585,7 +613,6 @@ impl Default for WindowOptions {
kind: WindowKind::Normal,
is_movable: true,
display_id: None,
fullscreen: false,
window_background: WindowBackgroundAppearance::default(),
app_id: None,
}

View File

@@ -28,7 +28,7 @@ use crate::scene::Scene;
use crate::{
px, size, Bounds, DevicePixels, Globals, Modifiers, Pixels, PlatformDisplay, PlatformInput,
Point, PromptLevel, Size, WaylandClientState, WaylandClientStatePtr, WindowAppearance,
WindowBackgroundAppearance, WindowParams,
WindowBackgroundAppearance, WindowBounds, WindowParams,
};
#[derive(Default)]
@@ -79,6 +79,7 @@ pub struct WaylandWindowState {
input_handler: Option<PlatformInputHandler>,
decoration_state: WaylandDecorationState,
fullscreen: bool,
restore_bounds: Bounds<DevicePixels>,
maximized: bool,
client: WaylandClientStatePtr,
callbacks: Callbacks,
@@ -151,6 +152,7 @@ impl WaylandWindowState {
input_handler: None,
decoration_state: WaylandDecorationState::Client,
fullscreen: false,
restore_bounds: Bounds::default(),
maximized: false,
callbacks: Callbacks::default(),
client,
@@ -332,10 +334,15 @@ impl WaylandWindowStatePtr {
let height = NonZeroU32::new(height as u32);
let fullscreen = states.contains(&(xdg_toplevel::State::Fullscreen as u8));
let maximized = states.contains(&(xdg_toplevel::State::Maximized as u8));
self.resize(width, height);
self.set_fullscreen(fullscreen);
let mut state = self.state.borrow_mut();
state.maximized = maximized;
state.fullscreen = fullscreen;
if fullscreen || maximized {
state.restore_bounds = state.bounds.map(|p| DevicePixels(p as i32));
}
drop(state);
self.resize(width, height);
self.set_fullscreen(fullscreen);
false
}
@@ -545,9 +552,17 @@ impl PlatformWindow for WaylandWindow {
self.borrow().maximized
}
fn is_minimized(&self) -> bool {
// This cannot be determined by the client
false
// todo(linux)
// check if it is right
fn window_bounds(&self) -> WindowBounds {
let state = self.borrow();
if state.fullscreen {
WindowBounds::Fullscreen(state.restore_bounds)
} else if state.maximized {
WindowBounds::Maximized(state.restore_bounds)
} else {
WindowBounds::Windowed(state.bounds.map(|p| DevicePixels(p as i32)))
}
}
fn content_size(&self) -> Size<Pixels> {

View File

@@ -5,8 +5,8 @@ use crate::{
platform::blade::{BladeRenderer, BladeSurfaceConfig},
size, Bounds, DevicePixels, ForegroundExecutor, Modifiers, Pixels, Platform, PlatformAtlas,
PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PromptLevel,
Scene, Size, WindowAppearance, WindowBackgroundAppearance, WindowOptions, WindowParams,
X11Client, X11ClientState, X11ClientStatePtr,
Scene, Size, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowOptions,
WindowParams, X11Client, X11ClientState, X11ClientStatePtr,
};
use blade_graphics as gpu;
use parking_lot::Mutex;
@@ -526,8 +526,9 @@ impl PlatformWindow for X11Window {
}
// todo(linux)
fn is_minimized(&self) -> bool {
false
fn window_bounds(&self) -> WindowBounds {
let state = self.0.state.borrow();
WindowBounds::Windowed(state.bounds.map(|p| DevicePixels(p)))
}
fn content_size(&self) -> Size<Pixels> {

View File

@@ -4,7 +4,8 @@ use crate::{
DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke,
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel,
Size, Timer, WindowAppearance, WindowBackgroundAppearance, WindowKind, WindowParams,
Size, Timer, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowKind,
WindowParams,
};
use block::ConcreteBlock;
use cocoa::{
@@ -302,14 +303,6 @@ unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const C
sel!(concludeDragOperation:),
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidMiniaturize:),
window_did_miniaturize as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidDeminiaturize:),
window_did_deminiaturize as extern "C" fn(&Object, Sel, id),
);
decl.register()
}
@@ -348,7 +341,7 @@ struct MacWindowState {
external_files_dragged: bool,
// Whether the next left-mouse click is also the focusing click.
first_mouse: bool,
minimized: bool,
fullscreen_restore_bounds: Bounds<DevicePixels>,
}
impl MacWindowState {
@@ -435,10 +428,6 @@ impl MacWindowState {
}
}
fn is_minimized(&self) -> bool {
self.minimized
}
fn is_fullscreen(&self) -> bool {
unsafe {
let style_mask = self.native_window.styleMask();
@@ -494,6 +483,14 @@ impl MacWindowState {
px((frame.size.height - content_layout_rect.size.height) as f32)
}
}
fn window_bounds(&self) -> WindowBounds {
if self.is_fullscreen() {
WindowBounds::Fullscreen(self.fullscreen_restore_bounds)
} else {
WindowBounds::Windowed(self.bounds())
}
}
}
unsafe impl Send for MacWindowState {}
@@ -639,7 +636,7 @@ impl MacWindow {
previous_keydown_inserted_text: None,
external_files_dragged: false,
first_mouse: false,
minimized: false,
fullscreen_restore_bounds: Bounds::default(),
})));
(*native_window).set_ivar(
@@ -775,12 +772,12 @@ impl PlatformWindow for MacWindow {
self.0.as_ref().lock().bounds()
}
fn is_maximized(&self) -> bool {
self.0.as_ref().lock().is_maximized()
fn window_bounds(&self) -> WindowBounds {
self.0.as_ref().lock().window_bounds()
}
fn is_minimized(&self) -> bool {
self.0.as_ref().lock().is_minimized()
fn is_maximized(&self) -> bool {
self.0.as_ref().lock().is_maximized()
}
fn content_size(&self) -> Size<Pixels> {
@@ -1863,18 +1860,6 @@ extern "C" fn conclude_drag_operation(this: &Object, _: Sel, _: id) {
);
}
extern "C" fn window_did_miniaturize(this: &Object, _: Sel, _: id) {
let window_state = unsafe { get_window_state(this) };
window_state.lock().minimized = true;
}
extern "C" fn window_did_deminiaturize(this: &Object, _: Sel, _: id) {
let window_state = unsafe { get_window_state(this) };
window_state.lock().minimized = false;
}
async fn synthetic_drag(
window_state: Weak<Mutex<MacWindowState>>,
drag_id: usize,

View File

@@ -2,7 +2,7 @@ use crate::{
AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DevicePixels,
DispatchEventResult, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
PlatformInputHandler, PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance,
WindowBackgroundAppearance, WindowParams,
WindowBackgroundAppearance, WindowBounds, WindowParams,
};
use collections::HashMap;
use parking_lot::Mutex;
@@ -112,11 +112,11 @@ impl PlatformWindow for TestWindow {
self.0.lock().bounds
}
fn is_maximized(&self) -> bool {
false
fn window_bounds(&self) -> WindowBounds {
WindowBounds::Windowed(self.bounds())
}
fn is_minimized(&self) -> bool {
fn is_maximized(&self) -> bool {
false
}

View File

@@ -42,6 +42,7 @@ pub(crate) struct WindowsWindowInner {
hwnd: HWND,
origin: Cell<Point<DevicePixels>>,
physical_size: Cell<Size<DevicePixels>>,
fullscreen_restore_bounds: Cell<Bounds<DevicePixels>>,
scale_factor: Cell<f32>,
input_handler: Cell<Option<PlatformInputHandler>>,
renderer: RefCell<BladeRenderer>,
@@ -65,14 +66,8 @@ impl WindowsWindowInner {
transparent: bool,
) -> Self {
let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32;
let origin = Cell::new(Point {
x: DevicePixels(cs.x),
y: DevicePixels(cs.y),
});
let physical_size = Cell::new(Size {
width: DevicePixels(cs.cx),
height: DevicePixels(cs.cy),
});
let origin = Cell::new(point(DevicePixels(cs.x), DevicePixels(cs.y)));
let physical_size = Cell::new(size(DevicePixels(cs.cx), DevicePixels(cs.cy)));
let scale_factor = Cell::new(monitor_dpi / USER_DEFAULT_SCREEN_DPI as f32);
let input_handler = Cell::new(None);
struct RawWindow {
@@ -119,10 +114,13 @@ impl WindowsWindowInner {
let display = RefCell::new(display);
let click_state = RefCell::new(ClickState::new());
let fullscreen = Cell::new(None);
let fullscreen_restore_bounds = Cell::new(Bounds::default());
Self {
hwnd,
origin,
physical_size,
fullscreen_restore_bounds,
scale_factor,
input_handler,
renderer,
@@ -140,8 +138,33 @@ impl WindowsWindowInner {
!self.is_fullscreen() && unsafe { IsZoomed(self.hwnd) }.as_bool()
}
fn is_minimized(&self) -> bool {
unsafe { IsIconic(self.hwnd) }.as_bool()
fn window_bounds(&self) -> WindowBounds {
let placement = unsafe {
let mut placement = WINDOWPLACEMENT {
length: std::mem::size_of::<WINDOWPLACEMENT>() as u32,
..Default::default()
};
GetWindowPlacement(self.hwnd, &mut placement).log_err();
placement
};
let bounds = Bounds {
origin: point(
DevicePixels(placement.rcNormalPosition.left),
DevicePixels(placement.rcNormalPosition.top),
),
size: size(
DevicePixels(placement.rcNormalPosition.right - placement.rcNormalPosition.left),
DevicePixels(placement.rcNormalPosition.bottom - placement.rcNormalPosition.top),
),
};
if self.is_fullscreen() {
WindowBounds::Fullscreen(self.fullscreen_restore_bounds.get())
} else if placement.showCmd == SW_SHOWMAXIMIZED.0 as u32 {
WindowBounds::Maximized(bounds)
} else {
WindowBounds::Windowed(bounds)
}
}
fn is_fullscreen(&self) -> bool {
@@ -152,6 +175,10 @@ impl WindowsWindowInner {
}
async fn toggle_fullscreen(self: Rc<Self>) {
self.fullscreen_restore_bounds.set(Bounds {
origin: self.origin.get(),
size: self.physical_size.get(),
});
let StyleAndBounds {
style,
x,
@@ -304,10 +331,7 @@ impl WindowsWindowInner {
fn handle_move_msg(&self, lparam: LPARAM) -> Option<isize> {
let x = lparam.signed_loword() as i32;
let y = lparam.signed_hiword() as i32;
self.origin.set(Point {
x: DevicePixels(x),
y: DevicePixels(y),
});
self.origin.set(point(DevicePixels(x), DevicePixels(y)));
let size = self.physical_size.get();
let center_x = x + size.width.0 / 2;
let center_y = y + size.height.0 / 2;
@@ -1246,16 +1270,16 @@ impl WindowsWindow {
pub(crate) fn new(
platform_inner: Rc<WindowsPlatformInner>,
handle: AnyWindowHandle,
options: WindowParams,
params: WindowParams,
) -> Self {
let classname = register_wnd_class(platform_inner.icon);
let hide_title_bar = options
let hide_title_bar = params
.titlebar
.as_ref()
.map(|titlebar| titlebar.appears_transparent)
.unwrap_or(false);
let windowname = HSTRING::from(
options
params
.titlebar
.as_ref()
.and_then(|titlebar| titlebar.title.as_ref())
@@ -1263,12 +1287,6 @@ impl WindowsWindow {
.unwrap_or(""),
);
let dwstyle = WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
let x = options.bounds.origin.x.0;
let y = options.bounds.origin.y.0;
let nwidth = options.bounds.size.width.0;
let nheight = options.bounds.size.height.0;
let hwndparent = HWND::default();
let hmenu = HMENU::default();
let hinstance = get_module_handle();
let mut context = WindowCreateContext {
inner: None,
@@ -1287,12 +1305,12 @@ impl WindowsWindow {
classname,
&windowname,
dwstyle,
x,
y,
nwidth,
nheight,
hwndparent,
hmenu,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
None,
None,
hinstance,
lpparam,
)
@@ -1316,7 +1334,20 @@ impl WindowsWindow {
.write()
.push(wnd.inner.hwnd);
unsafe {
let mut placement = WINDOWPLACEMENT {
length: std::mem::size_of::<WINDOWPLACEMENT>() as u32,
..Default::default()
};
GetWindowPlacement(wnd.inner.hwnd, &mut placement).log_err();
placement.rcNormalPosition.left = params.bounds.left().0;
placement.rcNormalPosition.right = params.bounds.right().0;
placement.rcNormalPosition.top = params.bounds.top().0;
placement.rcNormalPosition.bottom = params.bounds.bottom().0;
SetWindowPlacement(wnd.inner.hwnd, &placement).log_err();
}
unsafe { ShowWindow(wnd.inner.hwnd, SW_SHOW) };
wnd
}
}
@@ -1358,8 +1389,8 @@ impl PlatformWindow for WindowsWindow {
self.inner.is_maximized()
}
fn is_minimized(&self) -> bool {
self.inner.is_minimized()
fn window_bounds(&self) -> WindowBounds {
self.inner.window_bounds()
}
/// get the logical size of the app's drawable area.

View File

@@ -12,8 +12,8 @@ use crate::{
RenderSvgParams, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,
SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,
TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, WeakView,
WindowAppearance, WindowBackgroundAppearance, WindowOptions, WindowParams, WindowTextSystem,
SUBPIXEL_VARIANTS,
WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowOptions, WindowParams,
WindowTextSystem, SUBPIXEL_VARIANTS,
};
use anyhow::{anyhow, Context as _, Result};
use collections::{FxHashMap, FxHashSet};
@@ -565,7 +565,7 @@ fn default_bounds(display_id: Option<DisplayId>, cx: &mut AppContext) -> Bounds<
const DEFAULT_WINDOW_OFFSET: Point<DevicePixels> = point(DevicePixels(0), DevicePixels(35));
cx.active_window()
.and_then(|w| w.update(cx, |_, cx| cx.window_bounds()).ok())
.and_then(|w| w.update(cx, |_, cx| cx.bounds()).ok())
.map(|bounds| bounds.map_origin(|origin| origin + DEFAULT_WINDOW_OFFSET))
.unwrap_or_else(|| {
let display = display_id
@@ -592,19 +592,20 @@ impl Window {
cx: &mut AppContext,
) -> Self {
let WindowOptions {
bounds,
window_bounds,
titlebar,
focus,
show,
kind,
is_movable,
display_id,
fullscreen,
window_background,
app_id,
} = options;
let bounds = bounds.unwrap_or_else(|| default_bounds(display_id, cx));
let bounds = window_bounds
.map(|bounds| bounds.get_bounds())
.unwrap_or_else(|| default_bounds(display_id, cx));
let mut platform_window = cx.platform.open_window(
handle,
WindowParams {
@@ -632,8 +633,12 @@ impl Window {
let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();
let last_input_timestamp = Rc::new(Cell::new(Instant::now()));
if fullscreen {
platform_window.toggle_fullscreen();
if let Some(ref window_open_state) = window_bounds {
match window_open_state {
WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),
WindowBounds::Maximized(_) => platform_window.zoom(),
WindowBounds::Windowed(_) => {}
}
}
platform_window.on_close(Box::new({
@@ -691,7 +696,7 @@ impl Window {
let mut cx = cx.to_async();
move |_, _| {
handle
.update(&mut cx, |_, cx| cx.window_bounds_changed())
.update(&mut cx, |_, cx| cx.bounds_changed())
.log_err();
}
}));
@@ -699,7 +704,7 @@ impl Window {
let mut cx = cx.to_async();
move || {
handle
.update(&mut cx, |_, cx| cx.window_bounds_changed())
.update(&mut cx, |_, cx| cx.bounds_changed())
.log_err();
}
}));
@@ -943,10 +948,10 @@ impl<'a> WindowContext<'a> {
self.window.platform_window.is_maximized()
}
/// Check if the platform window is minimized
/// On some platforms (namely Windows) the position is incorrect when minimized
pub fn is_minimized(&self) -> bool {
self.window.platform_window.is_minimized()
/// Return the `WindowBounds` to indicate that how a window should be opened
/// after it has been closed
pub fn window_bounds(&self) -> WindowBounds {
self.window.platform_window.window_bounds()
}
/// Dispatch the given action on the currently focused element.
@@ -1075,7 +1080,7 @@ impl<'a> WindowContext<'a> {
.spawn(|app| f(AsyncWindowContext::new(app, self.window.handle)))
}
fn window_bounds_changed(&mut self) {
fn bounds_changed(&mut self) {
self.window.scale_factor = self.window.platform_window.scale_factor();
self.window.viewport_size = self.window.platform_window.content_size();
self.window.display_id = self.window.platform_window.display().id();
@@ -1088,7 +1093,7 @@ impl<'a> WindowContext<'a> {
}
/// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.
pub fn window_bounds(&self) -> Bounds<DevicePixels> {
pub fn bounds(&self) -> Bounds<DevicePixels> {
self.window.platform_window.bounds()
}

View File

@@ -7,7 +7,8 @@ mod story_selector;
use clap::Parser;
use dialoguer::FuzzySelect;
use gpui::{
div, px, size, AnyView, AppContext, Bounds, Render, ViewContext, VisualContext, WindowOptions,
div, px, size, AnyView, AppContext, Bounds, Render, ViewContext, VisualContext, WindowBounds,
WindowOptions,
};
use log::LevelFilter;
use project::Project;
@@ -85,7 +86,7 @@ fn main() {
let bounds = Bounds::centered(None, size, cx);
let _window = cx.open_window(
WindowOptions {
bounds: Some(bounds),
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
move |cx| {

View File

@@ -5,7 +5,7 @@ use std::path::Path;
use anyhow::{anyhow, bail, Context, Result};
use client::DevServerProjectId;
use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};
use gpui::{point, size, Axis, Bounds};
use gpui::{point, size, Axis, Bounds, WindowBounds};
use sqlez::{
bindable::{Bind, Column, StaticColumnCount},
@@ -59,50 +59,99 @@ impl sqlez::bindable::Column for SerializedAxis {
}
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct SerializedWindowsBounds(pub(crate) Bounds<gpui::DevicePixels>);
#[derive(Copy, Clone, Debug, PartialEq, Default)]
pub(crate) struct SerializedWindowBounds(pub(crate) WindowBounds);
impl StaticColumnCount for SerializedWindowsBounds {
impl StaticColumnCount for SerializedWindowBounds {
fn column_count() -> usize {
5
}
}
impl Bind for SerializedWindowsBounds {
impl Bind for SerializedWindowBounds {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let next_index = statement.bind(&"Fixed", start_index)?;
statement.bind(
&(
SerializedDevicePixels(self.0.origin.x),
SerializedDevicePixels(self.0.origin.y),
SerializedDevicePixels(self.0.size.width),
SerializedDevicePixels(self.0.size.height),
),
next_index,
)
match self.0 {
WindowBounds::Windowed(bounds) => {
let next_index = statement.bind(&"Windowed", start_index)?;
statement.bind(
&(
SerializedDevicePixels(bounds.origin.x),
SerializedDevicePixels(bounds.origin.y),
SerializedDevicePixels(bounds.size.width),
SerializedDevicePixels(bounds.size.height),
),
next_index,
)
}
WindowBounds::Maximized(bounds) => {
let next_index = statement.bind(&"Maximized", start_index)?;
statement.bind(
&(
SerializedDevicePixels(bounds.origin.x),
SerializedDevicePixels(bounds.origin.y),
SerializedDevicePixels(bounds.size.width),
SerializedDevicePixels(bounds.size.height),
),
next_index,
)
}
WindowBounds::Fullscreen(bounds) => {
let next_index = statement.bind(&"FullScreen", start_index)?;
statement.bind(
&(
SerializedDevicePixels(bounds.origin.x),
SerializedDevicePixels(bounds.origin.y),
SerializedDevicePixels(bounds.size.width),
SerializedDevicePixels(bounds.size.height),
),
next_index,
)
}
}
}
}
impl Column for SerializedWindowsBounds {
impl Column for SerializedWindowBounds {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (window_state, next_index) = String::column(statement, start_index)?;
let bounds = match window_state.as_str() {
"Fixed" => {
let status = match window_state.as_str() {
"Windowed" | "Fixed" => {
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
let x: i32 = x;
let y: i32 = y;
let width: i32 = width;
let height: i32 = height;
SerializedWindowsBounds(Bounds {
SerializedWindowBounds(WindowBounds::Windowed(Bounds {
origin: point(x.into(), y.into()),
size: size(width.into(), height.into()),
})
}))
}
"Maximized" => {
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
let x: i32 = x;
let y: i32 = y;
let width: i32 = width;
let height: i32 = height;
SerializedWindowBounds(WindowBounds::Maximized(Bounds {
origin: point(x.into(), y.into()),
size: size(width.into(), height.into()),
}))
}
"FullScreen" => {
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
let x: i32 = x;
let y: i32 = y;
let width: i32 = width;
let height: i32 = height;
SerializedWindowBounds(WindowBounds::Fullscreen(Bounds {
origin: point(x.into(), y.into()),
size: size(width.into(), height.into()),
}))
}
_ => bail!("Window State did not have a valid string"),
};
Ok((bounds, next_index + 4))
Ok((status, next_index + 4))
}
}
@@ -279,6 +328,8 @@ define_connection! {
ALTER TABLE pane_groups ADD COLUMN flexes TEXT;
),
// Add fullscreen field to workspace
// Deprecated, `WindowBounds` holds the fullscreen state now.
// Preserving so users can downgrade Zed.
sql!(
ALTER TABLE workspaces ADD COLUMN fullscreen INTEGER; //bool
),
@@ -328,19 +379,17 @@ impl WorkspaceDb {
workspace_id,
local_paths,
dev_server_project_id,
bounds,
window_bounds,
display,
fullscreen,
centered_layout,
docks,
): (
WorkspaceId,
Option<LocalPaths>,
Option<u64>,
Option<SerializedWindowsBounds>,
Option<SerializedWindowBounds>,
Option<Uuid>,
Option<bool>,
Option<bool>,
DockStructure,
) = self
.select_row_bound(sql! {
@@ -354,7 +403,6 @@ impl WorkspaceDb {
window_width,
window_height,
display,
fullscreen,
centered_layout,
left_dock_visible,
left_dock_active_panel,
@@ -398,8 +446,7 @@ impl WorkspaceDb {
.get_center_pane_group(workspace_id)
.context("Getting center group")
.log_err()?,
bounds: bounds.map(|bounds| bounds.0),
fullscreen: fullscreen.unwrap_or(false),
window_bounds,
centered_layout: centered_layout.unwrap_or(false),
display,
docks,
@@ -549,13 +596,12 @@ impl WorkspaceDb {
pub(crate) fn last_window(
&self,
) -> anyhow::Result<(Option<Uuid>, Option<SerializedWindowsBounds>, Option<bool>)> {
) -> anyhow::Result<(Option<Uuid>, Option<SerializedWindowBounds>)> {
let mut prepared_query =
self.select::<(Option<Uuid>, Option<SerializedWindowsBounds>, Option<bool>)>(sql!(
self.select::<(Option<Uuid>, Option<SerializedWindowBounds>)>(sql!(
SELECT
display,
window_state, window_x, window_y, window_width, window_height,
fullscreen
window_state, window_x, window_y, window_width, window_height
FROM workspaces
WHERE local_paths
IS NOT NULL
@@ -563,10 +609,7 @@ impl WorkspaceDb {
LIMIT 1
))?;
let result = prepared_query()?;
Ok(result
.into_iter()
.next()
.unwrap_or_else(|| (None, None, None)))
Ok(result.into_iter().next().unwrap_or_else(|| (None, None)))
}
query! {
@@ -829,7 +872,7 @@ impl WorkspaceDb {
}
query! {
pub(crate) async fn set_window_bounds(workspace_id: WorkspaceId, bounds: SerializedWindowsBounds, display: Uuid) -> Result<()> {
pub(crate) async fn set_window_open_status(workspace_id: WorkspaceId, bounds: SerializedWindowBounds, display: Uuid) -> Result<()> {
UPDATE workspaces
SET window_state = ?2,
window_x = ?3,
@@ -841,14 +884,6 @@ impl WorkspaceDb {
}
}
query! {
pub(crate) async fn set_fullscreen(workspace_id: WorkspaceId, fullscreen: bool) -> Result<()> {
UPDATE workspaces
SET fullscreen = ?2
WHERE workspace_id = ?1
}
}
query! {
pub(crate) async fn set_centered_layout(workspace_id: WorkspaceId, centered_layout: bool) -> Result<()> {
UPDATE workspaces
@@ -938,10 +973,9 @@ mod tests {
id: WorkspaceId(1),
location: LocalPaths::new(["/tmp", "/tmp2"]).into(),
center_group: Default::default(),
bounds: Default::default(),
window_bounds: Default::default(),
display: Default::default(),
docks: Default::default(),
fullscreen: false,
centered_layout: false,
};
@@ -949,10 +983,9 @@ mod tests {
id: WorkspaceId(2),
location: LocalPaths::new(["/tmp"]).into(),
center_group: Default::default(),
bounds: Default::default(),
window_bounds: Default::default(),
display: Default::default(),
docks: Default::default(),
fullscreen: false,
centered_layout: false,
};
@@ -1049,10 +1082,9 @@ mod tests {
id: WorkspaceId(5),
location: LocalPaths::new(["/tmp", "/tmp2"]).into(),
center_group,
bounds: Default::default(),
window_bounds: Default::default(),
display: Default::default(),
docks: Default::default(),
fullscreen: false,
centered_layout: false,
};
@@ -1079,10 +1111,9 @@ mod tests {
id: WorkspaceId(1),
location: LocalPaths::new(["/tmp", "/tmp2"]).into(),
center_group: Default::default(),
bounds: Default::default(),
window_bounds: Default::default(),
display: Default::default(),
docks: Default::default(),
fullscreen: false,
centered_layout: false,
};
@@ -1090,10 +1121,9 @@ mod tests {
id: WorkspaceId(2),
location: LocalPaths::new(["/tmp"]).into(),
center_group: Default::default(),
bounds: Default::default(),
window_bounds: Default::default(),
display: Default::default(),
docks: Default::default(),
fullscreen: false,
centered_layout: false,
};
@@ -1128,10 +1158,9 @@ mod tests {
id: WorkspaceId(3),
location: LocalPaths::new(&["/tmp", "/tmp2"]).into(),
center_group: Default::default(),
bounds: Default::default(),
window_bounds: Default::default(),
display: Default::default(),
docks: Default::default(),
fullscreen: false,
centered_layout: false,
};
@@ -1163,10 +1192,9 @@ mod tests {
id: WorkspaceId(4),
location: LocalPaths::new(workspace_id).into(),
center_group: center_group.clone(),
bounds: Default::default(),
window_bounds: Default::default(),
display: Default::default(),
docks: Default::default(),
fullscreen: false,
centered_layout: false,
}
}

View File

@@ -1,4 +1,4 @@
use super::SerializedAxis;
use super::{SerializedAxis, SerializedWindowBounds};
use crate::{item::ItemHandle, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId};
use anyhow::{Context, Result};
use async_recursion::async_recursion;
@@ -7,7 +7,7 @@ use db::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
use gpui::{AsyncWindowContext, Bounds, DevicePixels, Model, Task, View, WeakView};
use gpui::{AsyncWindowContext, Model, Task, View, WeakView};
use project::Project;
use serde::{Deserialize, Serialize};
use std::{
@@ -110,8 +110,7 @@ pub(crate) struct SerializedWorkspace {
pub(crate) id: WorkspaceId,
pub(crate) location: SerializedWorkspaceLocation,
pub(crate) center_group: SerializedPaneGroup,
pub(crate) bounds: Option<Bounds<DevicePixels>>,
pub(crate) fullscreen: bool,
pub(crate) window_bounds: Option<SerializedWindowBounds>,
pub(crate) centered_layout: bool,
pub(crate) display: Option<Uuid>,
pub(crate) docks: DockStructure,

View File

@@ -32,7 +32,7 @@ use gpui::{
ElementId, Entity as _, EntityId, EventEmitter, FocusHandle, FocusableView, Global,
GlobalElementId, KeyContext, Keystroke, LayoutId, ManagedView, Model, ModelContext,
PathPromptOptions, Point, PromptLevel, Render, Size, Subscription, Task, View, WeakView,
WindowHandle, WindowOptions,
WindowBounds, WindowHandle, WindowOptions,
};
use item::{
FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings,
@@ -46,7 +46,7 @@ use node_runtime::NodeRuntime;
use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
pub use pane::*;
pub use pane_group::*;
use persistence::{model::SerializedWorkspace, SerializedWindowsBounds, DB};
use persistence::{model::SerializedWorkspace, SerializedWindowBounds, DB};
pub use persistence::{
model::{ItemId, LocalPaths, SerializedDevServerProject, SerializedWorkspaceLocation},
WorkspaceDb, DB as WORKSPACE_DB,
@@ -785,29 +785,15 @@ impl Workspace {
.await;
this.update(&mut cx, |this, cx| {
if let Some(display) = cx.display() {
let window_bounds = cx.window_bounds();
let fullscreen = cx.is_fullscreen();
if let Some(display_uuid) = display.uuid().log_err() {
// Only update the window bounds when not full screen,
// so we can remember the last non-fullscreen bounds
// across restarts
if fullscreen {
cx.background_executor()
.spawn(DB.set_fullscreen(workspace_id, true))
.detach_and_log_err(cx);
} else if !cx.is_minimized() {
cx.background_executor()
.spawn(DB.set_fullscreen(workspace_id, false))
.detach_and_log_err(cx);
cx.background_executor()
.spawn(DB.set_window_bounds(
workspace_id,
SerializedWindowsBounds(window_bounds),
display_uuid,
))
.detach_and_log_err(cx);
}
let window_bounds = cx.window_bounds();
cx.background_executor()
.spawn(DB.set_window_open_status(
workspace_id,
SerializedWindowBounds(window_bounds),
display_uuid,
))
.detach_and_log_err(cx);
}
}
this.bounds_save_task_queued.take();
@@ -947,30 +933,27 @@ impl Workspace {
} else {
let window_bounds_override = window_bounds_env_override();
let (bounds, display, fullscreen) = if let Some(bounds) = window_bounds_override {
(Some(bounds), None, false)
let (window_bounds, display) = if let Some(bounds) = window_bounds_override {
(Some(WindowBounds::Windowed(bounds)), None)
} else {
let restorable_bounds = serialized_workspace
.as_ref()
.and_then(|workspace| {
Some((workspace.display?, workspace.bounds?, workspace.fullscreen))
})
.and_then(|workspace| Some((workspace.display?, workspace.window_bounds?)))
.or_else(|| {
let (display, bounds, fullscreen) = DB.last_window().log_err()?;
Some((display?, bounds?.0, fullscreen.unwrap_or(false)))
let (display, window_bounds) = DB.last_window().log_err()?;
Some((display?, window_bounds?))
});
if let Some((serialized_display, bounds, fullscreen)) = restorable_bounds {
(Some(bounds), Some(serialized_display), fullscreen)
if let Some((serialized_display, serialized_status)) = restorable_bounds {
(Some(serialized_status.0), Some(serialized_display))
} else {
(None, None, false)
(None, None)
}
};
// Use the serialized workspace to construct the new window
let mut options = cx.update(|cx| (app_state.build_window_options)(display, cx))?;
options.bounds = bounds;
options.fullscreen = fullscreen;
options.window_bounds = window_bounds;
let centered_layout = serialized_workspace
.as_ref()
.map(|w| w.centered_layout)
@@ -3667,14 +3650,14 @@ impl Workspace {
if let Some(location) = location {
let center_group = build_serialized_pane_group(&self.center.root, cx);
let docks = build_serialized_docks(self, cx);
let window_bounds = Some(SerializedWindowBounds(cx.window_bounds()));
let serialized_workspace = SerializedWorkspace {
id: self.database_id,
location,
center_group,
bounds: Default::default(),
window_bounds,
display: Default::default(),
docks,
fullscreen: cx.is_fullscreen(),
centered_layout: self.centered_layout,
};
return cx.spawn(|_| persistence::DB.save_workspace(serialized_workspace));
@@ -4867,7 +4850,8 @@ pub fn join_hosted_project(
let window_bounds_override = window_bounds_env_override();
cx.update(|cx| {
let mut options = (app_state.build_window_options)(None, cx);
options.bounds = window_bounds_override;
options.window_bounds =
window_bounds_override.map(|bounds| WindowBounds::Windowed(bounds));
cx.open_window(options, |cx| {
cx.new_view(|cx| {
Workspace::new(Default::default(), project, app_state.clone(), cx)
@@ -4931,7 +4915,8 @@ pub fn join_dev_server_project(
let window_bounds_override = window_bounds_env_override();
cx.update(|cx| {
let mut options = (app_state.build_window_options)(None, cx);
options.bounds = window_bounds_override;
options.window_bounds =
window_bounds_override.map(|bounds| WindowBounds::Windowed(bounds));
cx.open_window(options, |cx| {
cx.new_view(|cx| {
Workspace::new(Default::default(), project, app_state.clone(), cx)
@@ -4993,7 +4978,8 @@ pub fn join_in_room_project(
let window_bounds_override = window_bounds_env_override();
cx.update(|cx| {
let mut options = (app_state.build_window_options)(None, cx);
options.bounds = window_bounds_override;
options.window_bounds =
window_bounds_override.map(|bounds| WindowBounds::Windowed(bounds));
cx.open_window(options, |cx| {
cx.new_view(|cx| {
Workspace::new(Default::default(), project, app_state.clone(), cx)

View File

@@ -96,13 +96,12 @@ pub fn build_window_options(display_uuid: Option<Uuid>, cx: &mut AppContext) ->
appears_transparent: true,
traffic_light_position: Some(point(px(9.0), px(9.0))),
}),
bounds: None,
window_bounds: None,
focus: false,
show: false,
kind: WindowKind::Normal,
is_movable: true,
display_id: display.map(|display| display.id()),
fullscreen: false,
window_background: cx.theme().window_background_appearance(),
app_id: Some(app_id.to_owned()),
}