Open new windows with a default size and position (#9204)
This PR changes GPUI to open windows with a default size and location, and to otherwise inherit from their spawning window. Note: The linux build now crashes on startup. Release Notes: - N/A --------- Co-authored-by: Nathan <nathan@zed.dev> Co-authored-by: Ezekiel Warren <zaucy@users.noreply.github.com>
This commit is contained in:
co-authored by
Nathan
Ezekiel Warren
parent
9a2dceeea1
commit
e792c1a5c5
@@ -4,15 +4,16 @@ use std::rc::Rc;
|
||||
use copypasta::ClipboardProvider;
|
||||
|
||||
use crate::platform::PlatformWindow;
|
||||
use crate::{AnyWindowHandle, CursorStyle, DisplayId, PlatformDisplay, WindowOptions};
|
||||
use crate::{AnyWindowHandle, CursorStyle, DisplayId, PlatformDisplay, WindowParams};
|
||||
|
||||
pub trait Client {
|
||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>>;
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;
|
||||
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>>;
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow>;
|
||||
fn set_cursor_style(&self, style: CursorStyle);
|
||||
fn get_clipboard(&self) -> Rc<RefCell<dyn ClipboardProvider>>;
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
||||
ForegroundExecutor, Keymap, LinuxDispatcher, LinuxTextSystem, Menu, PathPromptOptions,
|
||||
Platform, PlatformDisplay, PlatformInput, PlatformTextSystem, PlatformWindow, Result,
|
||||
SemanticVersion, Task, WindowOptions,
|
||||
SemanticVersion, Task, WindowOptions, WindowParams,
|
||||
};
|
||||
|
||||
use super::x11::X11Client;
|
||||
@@ -156,6 +156,10 @@ impl Platform for LinuxPlatform {
|
||||
// todo(linux)
|
||||
fn unhide_other_apps(&self) {}
|
||||
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
|
||||
self.client.primary_display()
|
||||
}
|
||||
|
||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
|
||||
self.client.displays()
|
||||
}
|
||||
@@ -172,7 +176,7 @@ impl Platform for LinuxPlatform {
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
self.client.open_window(handle, options)
|
||||
}
|
||||
|
||||
@@ -39,11 +39,12 @@ use crate::platform::linux::client::Client;
|
||||
use crate::platform::linux::wayland::cursor::Cursor;
|
||||
use crate::platform::linux::wayland::window::{WaylandDecorationState, WaylandWindow};
|
||||
use crate::platform::{LinuxPlatformInner, PlatformWindow};
|
||||
use crate::WindowParams;
|
||||
use crate::{
|
||||
platform::linux::wayland::window::WaylandWindowState, AnyWindowHandle, CursorStyle, DisplayId,
|
||||
KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
||||
MouseDownEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,
|
||||
PlatformInput, Point, ScrollDelta, ScrollWheelEvent, TouchPhase, WindowOptions,
|
||||
PlatformInput, Point, ScrollDelta, ScrollWheelEvent, TouchPhase,
|
||||
};
|
||||
|
||||
/// Used to convert evdev scancode to xkb scancode
|
||||
@@ -207,10 +208,14 @@ impl Client for WaylandClient {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
let mut state = self.state.client_state_inner.borrow_mut();
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ use crate::platform::linux::wayland::display::WaylandDisplay;
|
||||
use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow};
|
||||
use crate::scene::Scene;
|
||||
use crate::{
|
||||
px, size, Bounds, Modifiers, Pixels, PlatformDisplay, PlatformInput, Point, PromptLevel, Size,
|
||||
WindowAppearance, WindowBounds, WindowOptions,
|
||||
px, size, Bounds, GlobalPixels, Modifiers, Pixels, PlatformDisplay, PlatformInput, Point,
|
||||
PromptLevel, Size, WindowAppearance, WindowParams,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -125,24 +125,9 @@ impl WaylandWindowState {
|
||||
wl_surf: Arc<wl_surface::WlSurface>,
|
||||
viewport: Option<wp_viewport::WpViewport>,
|
||||
toplevel: Arc<xdg_toplevel::XdgToplevel>,
|
||||
options: WindowOptions,
|
||||
options: WindowParams,
|
||||
) -> Self {
|
||||
if options.bounds == WindowBounds::Maximized {
|
||||
toplevel.set_maximized();
|
||||
} else if options.bounds == WindowBounds::Fullscreen {
|
||||
toplevel.set_fullscreen(None);
|
||||
}
|
||||
|
||||
let bounds: Bounds<u32> = match options.bounds {
|
||||
WindowBounds::Fullscreen | WindowBounds::Maximized => Bounds {
|
||||
origin: Point::default(),
|
||||
size: Size {
|
||||
width: 500,
|
||||
height: 500,
|
||||
}, // todo(implement)
|
||||
},
|
||||
WindowBounds::Fixed(bounds) => bounds.map(|p| p.0 as u32),
|
||||
};
|
||||
let bounds = options.bounds.map(|p| p.0 as u32);
|
||||
|
||||
Self {
|
||||
surface: Arc::clone(&wl_surf),
|
||||
@@ -290,8 +275,8 @@ impl HasDisplayHandle for WaylandWindow {
|
||||
|
||||
impl PlatformWindow for WaylandWindow {
|
||||
// todo(linux)
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
WindowBounds::Maximized
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
@@ -331,9 +316,8 @@ impl PlatformWindow for WaylandWindow {
|
||||
crate::Modifiers::default()
|
||||
}
|
||||
|
||||
// todo(linux)
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
unimplemented!()
|
||||
self
|
||||
}
|
||||
|
||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
|
||||
@@ -379,13 +363,17 @@ impl PlatformWindow for WaylandWindow {
|
||||
}
|
||||
|
||||
fn toggle_full_screen(&self) {
|
||||
if !self.0.inner.borrow_mut().fullscreen {
|
||||
if !self.0.inner.borrow().fullscreen {
|
||||
self.0.toplevel.set_fullscreen(None);
|
||||
} else {
|
||||
self.0.toplevel.unset_fullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
fn is_full_screen(&self) -> bool {
|
||||
self.0.inner.borrow_mut().fullscreen
|
||||
}
|
||||
|
||||
fn on_request_frame(&self, callback: Box<dyn FnMut()>) {
|
||||
self.0.callbacks.borrow_mut().request_frame = Some(callback);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::platform::linux::client::Client;
|
||||
use crate::platform::{LinuxPlatformInner, PlatformWindow};
|
||||
use crate::{
|
||||
AnyWindowHandle, Bounds, CursorStyle, DisplayId, PlatformDisplay, PlatformInput, Point,
|
||||
ScrollDelta, Size, TouchPhase, WindowOptions,
|
||||
ScrollDelta, Size, TouchPhase,
|
||||
};
|
||||
|
||||
use super::{X11Display, X11Window, X11WindowState, XcbAtoms};
|
||||
@@ -284,26 +284,35 @@ impl Client for X11Client {
|
||||
setup
|
||||
.roots()
|
||||
.enumerate()
|
||||
.map(|(root_id, _)| {
|
||||
Rc::new(X11Display::new(&self.xcb_connection, root_id as i32))
|
||||
as Rc<dyn PlatformDisplay>
|
||||
.filter_map(|(root_id, _)| {
|
||||
Some(
|
||||
Rc::new(X11Display::new(&self.xcb_connection, root_id as i32)?)
|
||||
as Rc<dyn PlatformDisplay>,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
|
||||
Some(Rc::new(X11Display::new(&self.xcb_connection, id.0 as i32)))
|
||||
Some(Rc::new(X11Display::new(&self.xcb_connection, id.0 as i32)?))
|
||||
}
|
||||
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
|
||||
Some(Rc::new(
|
||||
X11Display::new(&self.xcb_connection, self.x_root_index)
|
||||
.expect("There should always be a root index"),
|
||||
))
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
_handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
params: crate::WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
let x_window = self.xcb_connection.generate_id();
|
||||
|
||||
let window_ptr = Rc::new(X11WindowState::new(
|
||||
options,
|
||||
params,
|
||||
&self.xcb_connection,
|
||||
self.x_root_index,
|
||||
x_window,
|
||||
|
||||
@@ -11,9 +11,9 @@ pub(crate) struct X11Display {
|
||||
}
|
||||
|
||||
impl X11Display {
|
||||
pub(crate) fn new(xc: &xcb::Connection, x_screen_index: i32) -> Self {
|
||||
let screen = xc.get_setup().roots().nth(x_screen_index as usize).unwrap();
|
||||
Self {
|
||||
pub(crate) fn new(xc: &xcb::Connection, x_screen_index: i32) -> Option<Self> {
|
||||
let screen = xc.get_setup().roots().nth(x_screen_index as usize)?;
|
||||
Some(Self {
|
||||
x_screen_index,
|
||||
bounds: Bounds {
|
||||
origin: Default::default(),
|
||||
@@ -23,7 +23,7 @@ impl X11Display {
|
||||
},
|
||||
},
|
||||
uuid: Uuid::from_bytes([0; 16]),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::{
|
||||
platform::blade::BladeRenderer, size, Bounds, GlobalPixels, Modifiers, Pixels, PlatformAtlas,
|
||||
PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PromptLevel,
|
||||
Scene, Size, WindowAppearance, WindowBounds, WindowOptions,
|
||||
Scene, Size, WindowAppearance, WindowOptions, WindowParams,
|
||||
};
|
||||
use blade_graphics as gpu;
|
||||
use parking_lot::Mutex;
|
||||
@@ -138,13 +138,13 @@ impl rwh::HasDisplayHandle for X11Window {
|
||||
|
||||
impl X11WindowState {
|
||||
pub fn new(
|
||||
options: WindowOptions,
|
||||
params: WindowParams,
|
||||
xcb_connection: &Rc<xcb::Connection>,
|
||||
x_main_screen_index: i32,
|
||||
x_window: x::Window,
|
||||
atoms: &XcbAtoms,
|
||||
) -> Self {
|
||||
let x_screen_index = options
|
||||
let x_screen_index = params
|
||||
.display_id
|
||||
.map_or(x_main_screen_index, |did| did.0 as i32);
|
||||
let screen = xcb_connection
|
||||
@@ -175,32 +175,21 @@ impl X11WindowState {
|
||||
),
|
||||
];
|
||||
|
||||
let bounds = match options.bounds {
|
||||
WindowBounds::Fullscreen | WindowBounds::Maximized => Bounds {
|
||||
origin: Point::default(),
|
||||
size: Size {
|
||||
width: screen.width_in_pixels() as i32,
|
||||
height: screen.height_in_pixels() as i32,
|
||||
},
|
||||
},
|
||||
WindowBounds::Fixed(bounds) => bounds.map(|p| p.0 as i32),
|
||||
};
|
||||
|
||||
xcb_connection.send_request(&x::CreateWindow {
|
||||
depth: x::COPY_FROM_PARENT as u8,
|
||||
wid: x_window,
|
||||
parent: screen.root(),
|
||||
x: bounds.origin.x as i16,
|
||||
y: bounds.origin.y as i16,
|
||||
width: bounds.size.width as u16,
|
||||
height: bounds.size.height as u16,
|
||||
x: params.bounds.origin.x.0 as i16,
|
||||
y: params.bounds.origin.y.0 as i16,
|
||||
width: params.bounds.size.width.0 as u16,
|
||||
height: params.bounds.size.height.0 as u16,
|
||||
border_width: 0,
|
||||
class: x::WindowClass::InputOutput,
|
||||
visual: screen.root_visual(),
|
||||
value_list: &xcb_values,
|
||||
});
|
||||
|
||||
if let Some(titlebar) = options.titlebar {
|
||||
if let Some(titlebar) = params.titlebar {
|
||||
if let Some(title) = titlebar.title {
|
||||
xcb_connection.send_request(&x::ChangeProperty {
|
||||
mode: x::PropMode::Replace,
|
||||
@@ -250,12 +239,12 @@ impl X11WindowState {
|
||||
|
||||
Self {
|
||||
xcb_connection: xcb_connection.clone(),
|
||||
display: Rc::new(X11Display::new(xcb_connection, x_screen_index)),
|
||||
display: Rc::new(X11Display::new(xcb_connection, x_screen_index).unwrap()),
|
||||
raw,
|
||||
x_window,
|
||||
callbacks: RefCell::new(Callbacks::default()),
|
||||
inner: RefCell::new(LinuxWindowInner {
|
||||
bounds,
|
||||
bounds: params.bounds.map(|v| v.0 as i32),
|
||||
scale_factor: 1.0,
|
||||
renderer: BladeRenderer::new(gpu, gpu_extent),
|
||||
input_handler: None,
|
||||
@@ -339,14 +328,12 @@ impl X11WindowState {
|
||||
}
|
||||
|
||||
impl PlatformWindow for X11Window {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
WindowBounds::Fixed(
|
||||
self.0
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.bounds
|
||||
.map(|v| GlobalPixels(v as f32)),
|
||||
)
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
self.0
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.bounds
|
||||
.map(|v| GlobalPixels(v as f32))
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
@@ -454,6 +441,11 @@ impl PlatformWindow for X11Window {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// todo(linux)
|
||||
fn is_full_screen(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn on_request_frame(&self, callback: Box<dyn FnMut()>) {
|
||||
self.0.callbacks.borrow_mut().request_frame = Some(callback);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
||||
ForegroundExecutor, Keymap, MacDispatcher, MacDisplay, MacTextSystem, MacWindow, Menu,
|
||||
MenuItem, PathPromptOptions, Platform, PlatformDisplay, PlatformInput, PlatformTextSystem,
|
||||
PlatformWindow, Result, SemanticVersion, Task, WindowAppearance, WindowOptions,
|
||||
PlatformWindow, Result, SemanticVersion, Task, WindowAppearance, WindowParams,
|
||||
};
|
||||
use anyhow::{anyhow, bail};
|
||||
use block::ConcreteBlock;
|
||||
@@ -477,6 +477,10 @@ impl Platform for MacPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
|
||||
Some(Rc::new(MacDisplay::primary()))
|
||||
}
|
||||
|
||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
|
||||
MacDisplay::all()
|
||||
.map(|screen| Rc::new(screen) as Rc<_>)
|
||||
@@ -494,7 +498,7 @@ impl Platform for MacPlatform {
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
// Clippy thinks that this evaluates to `()`, for some reason.
|
||||
#[allow(clippy::unit_arg, clippy::clone_on_copy)]
|
||||
|
||||
@@ -4,8 +4,7 @@ use crate::{
|
||||
Bounds, DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, GlobalPixels,
|
||||
KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
||||
MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
||||
PlatformWindow, Point, PromptLevel, Size, Timer, WindowAppearance, WindowBounds, WindowKind,
|
||||
WindowOptions,
|
||||
PlatformWindow, Point, PromptLevel, Size, Timer, WindowAppearance, WindowKind, WindowParams,
|
||||
};
|
||||
use block::ConcreteBlock;
|
||||
use cocoa::{
|
||||
@@ -419,23 +418,7 @@ impl MacWindowState {
|
||||
}
|
||||
}
|
||||
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
unsafe {
|
||||
if self.is_fullscreen() {
|
||||
return WindowBounds::Fullscreen;
|
||||
}
|
||||
|
||||
let frame = self.frame();
|
||||
let screen_size = self.native_window.screen().visibleFrame().into();
|
||||
if frame.size == screen_size {
|
||||
WindowBounds::Maximized
|
||||
} else {
|
||||
WindowBounds::Fixed(frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn frame(&self) -> Bounds<GlobalPixels> {
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
let frame = unsafe { NSWindow::frame(self.native_window) };
|
||||
global_bounds_from_ns_rect(frame)
|
||||
}
|
||||
@@ -483,7 +466,15 @@ pub(crate) struct MacWindow(Arc<Mutex<MacWindowState>>);
|
||||
impl MacWindow {
|
||||
pub fn open(
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
WindowParams {
|
||||
bounds,
|
||||
titlebar,
|
||||
kind,
|
||||
is_movable,
|
||||
display_id,
|
||||
focus,
|
||||
show,
|
||||
}: WindowParams,
|
||||
executor: ForegroundExecutor,
|
||||
renderer_context: renderer::Context,
|
||||
) -> Self {
|
||||
@@ -491,7 +482,7 @@ impl MacWindow {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
|
||||
let mut style_mask;
|
||||
if let Some(titlebar) = options.titlebar.as_ref() {
|
||||
if let Some(titlebar) = titlebar.as_ref() {
|
||||
style_mask = NSWindowStyleMask::NSClosableWindowMask
|
||||
| NSWindowStyleMask::NSMiniaturizableWindowMask
|
||||
| NSWindowStyleMask::NSResizableWindowMask
|
||||
@@ -505,7 +496,7 @@ impl MacWindow {
|
||||
| NSWindowStyleMask::NSFullSizeContentViewWindowMask;
|
||||
}
|
||||
|
||||
let native_window: id = match options.kind {
|
||||
let native_window: id = match kind {
|
||||
WindowKind::Normal => msg_send![WINDOW_CLASS, alloc],
|
||||
WindowKind::PopUp => {
|
||||
style_mask |= NSWindowStyleMaskNonactivatingPanel;
|
||||
@@ -513,8 +504,7 @@ impl MacWindow {
|
||||
}
|
||||
};
|
||||
|
||||
let display = options
|
||||
.display_id
|
||||
let display = display_id
|
||||
.and_then(MacDisplay::find_by_id)
|
||||
.unwrap_or_else(MacDisplay::primary);
|
||||
|
||||
@@ -530,23 +520,13 @@ impl MacWindow {
|
||||
}
|
||||
}
|
||||
|
||||
let window_rect = match options.bounds {
|
||||
WindowBounds::Fullscreen => {
|
||||
// Set a temporary size as we will asynchronously resize the window
|
||||
NSRect::new(NSPoint::new(0., 0.), NSSize::new(1024., 768.))
|
||||
}
|
||||
WindowBounds::Maximized => {
|
||||
let display_bounds = display.bounds();
|
||||
let window_rect = {
|
||||
let display_bounds = display.bounds();
|
||||
if bounds.intersects(&display_bounds) {
|
||||
global_bounds_to_ns_rect(bounds)
|
||||
} else {
|
||||
global_bounds_to_ns_rect(display_bounds)
|
||||
}
|
||||
WindowBounds::Fixed(bounds) => {
|
||||
let display_bounds = display.bounds();
|
||||
if bounds.intersects(&display_bounds) {
|
||||
global_bounds_to_ns_rect(bounds)
|
||||
} else {
|
||||
global_bounds_to_ns_rect(display_bounds)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let native_window = native_window.initWithContentRect_styleMask_backing_defer_screen_(
|
||||
@@ -568,17 +548,8 @@ impl MacWindow {
|
||||
assert!(!native_view.is_null());
|
||||
|
||||
let window_size = {
|
||||
let bounds = match options.bounds {
|
||||
WindowBounds::Fullscreen | WindowBounds::Maximized => {
|
||||
native_window.screen().visibleFrame()
|
||||
}
|
||||
WindowBounds::Fixed(bounds) => global_bounds_to_ns_rect(bounds),
|
||||
};
|
||||
let scale = get_scale_factor(native_window);
|
||||
size(
|
||||
bounds.size.width as f32 * scale,
|
||||
bounds.size.height as f32 * scale,
|
||||
)
|
||||
size(bounds.size.width.0 * scale, bounds.size.height.0 * scale)
|
||||
};
|
||||
|
||||
let window = Self(Arc::new(Mutex::new(MacWindowState {
|
||||
@@ -594,7 +565,7 @@ impl MacWindow {
|
||||
native_view as *mut _,
|
||||
window_size,
|
||||
),
|
||||
kind: options.kind,
|
||||
kind,
|
||||
request_frame_callback: None,
|
||||
event_callback: None,
|
||||
activate_callback: None,
|
||||
@@ -608,8 +579,7 @@ impl MacWindow {
|
||||
last_key_equivalent: None,
|
||||
synthetic_drag_counter: 0,
|
||||
last_fresh_keydown: None,
|
||||
traffic_light_position: options
|
||||
.titlebar
|
||||
traffic_light_position: titlebar
|
||||
.as_ref()
|
||||
.and_then(|titlebar| titlebar.traffic_light_position),
|
||||
previous_modifiers_changed_event: None,
|
||||
@@ -628,20 +598,16 @@ impl MacWindow {
|
||||
Arc::into_raw(window.0.clone()) as *const c_void,
|
||||
);
|
||||
|
||||
if let Some(title) = options
|
||||
.titlebar
|
||||
if let Some(title) = titlebar
|
||||
.as_ref()
|
||||
.and_then(|t| t.title.as_ref().map(AsRef::as_ref))
|
||||
{
|
||||
native_window.setTitle_(NSString::alloc(nil).init_str(title));
|
||||
}
|
||||
|
||||
native_window.setMovable_(options.is_movable as BOOL);
|
||||
native_window.setMovable_(is_movable as BOOL);
|
||||
|
||||
if options
|
||||
.titlebar
|
||||
.map_or(true, |titlebar| titlebar.appears_transparent)
|
||||
{
|
||||
if titlebar.map_or(true, |titlebar| titlebar.appears_transparent) {
|
||||
native_window.setTitlebarAppearsTransparent_(YES);
|
||||
native_window.setTitleVisibility_(NSWindowTitleVisibility::NSWindowTitleHidden);
|
||||
}
|
||||
@@ -663,11 +629,7 @@ impl MacWindow {
|
||||
native_window.setContentView_(native_view.autorelease());
|
||||
native_window.makeFirstResponder_(native_view);
|
||||
|
||||
if options.center {
|
||||
native_window.center();
|
||||
}
|
||||
|
||||
match options.kind {
|
||||
match kind {
|
||||
WindowKind::Normal => {
|
||||
native_window.setLevel_(NSNormalWindowLevel);
|
||||
native_window.setAcceptsMouseMovedEvents_(YES);
|
||||
@@ -698,16 +660,11 @@ impl MacWindow {
|
||||
);
|
||||
}
|
||||
}
|
||||
if options.focus {
|
||||
native_window.makeKeyAndOrderFront_(nil);
|
||||
} else if options.show {
|
||||
native_window.orderFront_(nil);
|
||||
}
|
||||
|
||||
if options.bounds == WindowBounds::Fullscreen {
|
||||
// We need to toggle full screen asynchronously as doing so may
|
||||
// call back into the platform handlers.
|
||||
window.toggle_full_screen();
|
||||
if focus {
|
||||
native_window.makeKeyAndOrderFront_(nil);
|
||||
} else if show {
|
||||
native_window.orderFront_(nil);
|
||||
}
|
||||
|
||||
window.0.lock().move_traffic_light();
|
||||
@@ -754,7 +711,7 @@ impl Drop for MacWindow {
|
||||
}
|
||||
|
||||
impl PlatformWindow for MacWindow {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
self.0.as_ref().lock().bounds()
|
||||
}
|
||||
|
||||
@@ -995,6 +952,17 @@ impl PlatformWindow for MacWindow {
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn is_full_screen(&self) -> bool {
|
||||
let this = self.0.lock();
|
||||
let window = this.native_window;
|
||||
|
||||
unsafe {
|
||||
window
|
||||
.styleMask()
|
||||
.contains(NSWindowStyleMask::NSFullScreenWindowMask)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_request_frame(&self, callback: Box<dyn FnMut()>) {
|
||||
self.0.as_ref().lock().request_frame_callback = Some(callback);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId, ForegroundExecutor,
|
||||
Keymap, Platform, PlatformDisplay, PlatformTextSystem, Task, TestDisplay, TestWindow,
|
||||
WindowAppearance, WindowOptions,
|
||||
WindowAppearance, WindowParams,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use collections::VecDeque;
|
||||
@@ -161,6 +161,10 @@ impl Platform for TestPlatform {
|
||||
vec![self.active_display.clone()]
|
||||
}
|
||||
|
||||
fn primary_display(&self) -> Option<std::rc::Rc<dyn crate::PlatformDisplay>> {
|
||||
Some(self.active_display.clone())
|
||||
}
|
||||
|
||||
fn display(&self, id: DisplayId) -> Option<std::rc::Rc<dyn crate::PlatformDisplay>> {
|
||||
self.displays().iter().find(|d| d.id() == id).cloned()
|
||||
}
|
||||
@@ -175,11 +179,11 @@ impl Platform for TestPlatform {
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
params: WindowParams,
|
||||
) -> Box<dyn crate::PlatformWindow> {
|
||||
let window = TestWindow::new(
|
||||
options,
|
||||
handle,
|
||||
params,
|
||||
self.weak.clone(),
|
||||
self.active_display.clone(),
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
px, AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, Pixels, PlatformAtlas,
|
||||
PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, Size,
|
||||
TestPlatform, TileId, WindowAppearance, WindowBounds, WindowOptions,
|
||||
AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, GlobalPixels, Pixels,
|
||||
PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,
|
||||
Size, TestPlatform, TileId, WindowAppearance, WindowParams,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use parking_lot::Mutex;
|
||||
@@ -12,7 +12,7 @@ use std::{
|
||||
};
|
||||
|
||||
pub(crate) struct TestWindowState {
|
||||
pub(crate) bounds: WindowBounds,
|
||||
pub(crate) bounds: Bounds<GlobalPixels>,
|
||||
pub(crate) handle: AnyWindowHandle,
|
||||
display: Rc<dyn PlatformDisplay>,
|
||||
pub(crate) title: Option<String>,
|
||||
@@ -25,6 +25,7 @@ pub(crate) struct TestWindowState {
|
||||
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||
moved_callback: Option<Box<dyn FnMut()>>,
|
||||
input_handler: Option<PlatformInputHandler>,
|
||||
is_fullscreen: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -48,13 +49,13 @@ impl HasDisplayHandle for TestWindow {
|
||||
|
||||
impl TestWindow {
|
||||
pub fn new(
|
||||
options: WindowOptions,
|
||||
handle: AnyWindowHandle,
|
||||
params: WindowParams,
|
||||
platform: Weak<TestPlatform>,
|
||||
display: Rc<dyn PlatformDisplay>,
|
||||
) -> Self {
|
||||
Self(Arc::new(Mutex::new(TestWindowState {
|
||||
bounds: options.bounds,
|
||||
bounds: params.bounds,
|
||||
display,
|
||||
platform,
|
||||
handle,
|
||||
@@ -67,6 +68,7 @@ impl TestWindow {
|
||||
resize_callback: None,
|
||||
moved_callback: None,
|
||||
input_handler: None,
|
||||
is_fullscreen: false,
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -76,17 +78,7 @@ impl TestWindow {
|
||||
let Some(mut callback) = lock.resize_callback.take() else {
|
||||
return;
|
||||
};
|
||||
match &mut lock.bounds {
|
||||
WindowBounds::Fullscreen | WindowBounds::Maximized => {
|
||||
lock.bounds = WindowBounds::Fixed(Bounds {
|
||||
origin: Point::default(),
|
||||
size: size.map(|pixels| f64::from(pixels).into()),
|
||||
});
|
||||
}
|
||||
WindowBounds::Fixed(bounds) => {
|
||||
bounds.size = size.map(|pixels| f64::from(pixels).into());
|
||||
}
|
||||
}
|
||||
lock.bounds.size = size.map(|pixels| f64::from(pixels).into());
|
||||
drop(lock);
|
||||
callback(size, scale_factor);
|
||||
self.0.lock().resize_callback = Some(callback);
|
||||
@@ -115,16 +107,12 @@ impl TestWindow {
|
||||
}
|
||||
|
||||
impl PlatformWindow for TestWindow {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
self.0.lock().bounds
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
let bounds = match self.bounds() {
|
||||
WindowBounds::Fixed(bounds) => bounds,
|
||||
WindowBounds::Maximized | WindowBounds::Fullscreen => self.display().bounds(),
|
||||
};
|
||||
bounds.size.map(|p| px(p.0))
|
||||
self.bounds().size.into()
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f32 {
|
||||
@@ -210,7 +198,12 @@ impl PlatformWindow for TestWindow {
|
||||
}
|
||||
|
||||
fn toggle_full_screen(&self) {
|
||||
unimplemented!()
|
||||
let mut lock = self.0.lock();
|
||||
lock.is_fullscreen = !lock.is_fullscreen;
|
||||
}
|
||||
|
||||
fn is_full_screen(&self) -> bool {
|
||||
self.0.lock().is_fullscreen
|
||||
}
|
||||
|
||||
fn on_request_frame(&self, _callback: Box<dyn FnMut()>) {}
|
||||
|
||||
@@ -53,8 +53,8 @@ use windows::{
|
||||
use crate::{
|
||||
try_get_window_inner, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle,
|
||||
ForegroundExecutor, Keymap, Menu, PathPromptOptions, Platform, PlatformDisplay, PlatformInput,
|
||||
PlatformTextSystem, PlatformWindow, Task, WindowAppearance, WindowOptions, WindowsDispatcher,
|
||||
WindowsDisplay, WindowsTextSystem, WindowsWindow,
|
||||
PlatformTextSystem, PlatformWindow, Task, WindowAppearance, WindowOptions, WindowParams,
|
||||
WindowsDispatcher, WindowsDisplay, WindowsTextSystem, WindowsWindow,
|
||||
};
|
||||
|
||||
pub(crate) struct WindowsPlatform {
|
||||
@@ -327,15 +327,20 @@ impl Platform for WindowsPlatform {
|
||||
Some(Rc::new(WindowsDisplay::new()))
|
||||
}
|
||||
|
||||
// todo(windows)
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
|
||||
Some(Rc::new(WindowsDisplay::new()))
|
||||
}
|
||||
|
||||
// todo(windows)
|
||||
fn active_window(&self) -> Option<AnyWindowHandle> {
|
||||
unimplemented!()
|
||||
None
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
options: WindowParams,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
Box::new(WindowsWindow::new(self.inner.clone(), handle, options))
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ use windows::{
|
||||
WindowsAndMessaging::{
|
||||
CreateWindowExW, DefWindowProcW, GetWindowLongPtrW, LoadCursorW, PostQuitMessage,
|
||||
RegisterClassW, SetWindowLongPtrW, SetWindowTextW, ShowWindow, CREATESTRUCTW,
|
||||
CW_USEDEFAULT, GWLP_USERDATA, HMENU, IDC_ARROW, SW_MAXIMIZE, SW_SHOW, WHEEL_DELTA,
|
||||
GWLP_USERDATA, HMENU, IDC_ARROW, SW_MAXIMIZE, SW_SHOW, WHEEL_DELTA,
|
||||
WINDOW_EX_STYLE, WINDOW_LONG_PTR_INDEX, WM_CHAR, WM_CLOSE, WM_DESTROY, WM_KEYDOWN,
|
||||
WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP,
|
||||
WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_MOVE, WM_NCCREATE, WM_NCDESTROY,
|
||||
@@ -65,7 +65,7 @@ use crate::{
|
||||
KeyUpEvent, Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||
NavigationDirection, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
||||
PlatformInputHandler, PlatformWindow, Point, PromptLevel, Scene, ScrollDelta, Size, TouchPhase,
|
||||
WindowAppearance, WindowBounds, WindowOptions, WindowsDisplay, WindowsPlatformInner,
|
||||
WindowAppearance, WindowParams, WindowsDisplay, WindowsPlatformInner,
|
||||
};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
@@ -614,7 +614,7 @@ impl WindowsWindow {
|
||||
pub(crate) fn new(
|
||||
platform_inner: Rc<WindowsPlatformInner>,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
options: WindowParams,
|
||||
) -> Self {
|
||||
let dwexstyle = WINDOW_EX_STYLE::default();
|
||||
let classname = register_wnd_class();
|
||||
@@ -627,20 +627,10 @@ impl WindowsWindow {
|
||||
.unwrap_or(""),
|
||||
);
|
||||
let dwstyle = WS_OVERLAPPEDWINDOW & !WS_VISIBLE;
|
||||
let mut x = CW_USEDEFAULT;
|
||||
let mut y = CW_USEDEFAULT;
|
||||
let mut nwidth = CW_USEDEFAULT;
|
||||
let mut nheight = CW_USEDEFAULT;
|
||||
match options.bounds {
|
||||
WindowBounds::Fullscreen => {}
|
||||
WindowBounds::Maximized => {}
|
||||
WindowBounds::Fixed(bounds) => {
|
||||
x = bounds.origin.x.0 as i32;
|
||||
y = bounds.origin.y.0 as i32;
|
||||
nwidth = bounds.size.width.0 as i32;
|
||||
nheight = bounds.size.height.0 as i32;
|
||||
}
|
||||
};
|
||||
let x = options.bounds.origin.x.0 as i32;
|
||||
let y = options.bounds.origin.y.0 as i32;
|
||||
let nwidth = options.bounds.size.width.0 as i32;
|
||||
let nheight = options.bounds.size.height.0 as i32;
|
||||
let hwndparent = HWND::default();
|
||||
let hmenu = HMENU::default();
|
||||
let hinstance = HINSTANCE::default();
|
||||
@@ -684,11 +674,7 @@ impl WindowsWindow {
|
||||
.window_handle_values
|
||||
.borrow_mut()
|
||||
.insert(wnd.inner.hwnd.0);
|
||||
match options.bounds {
|
||||
WindowBounds::Fullscreen => wnd.toggle_full_screen(),
|
||||
WindowBounds::Maximized => wnd.maximize(),
|
||||
WindowBounds::Fixed(_) => {}
|
||||
}
|
||||
|
||||
unsafe { ShowWindow(wnd.inner.hwnd, SW_SHOW) };
|
||||
wnd
|
||||
}
|
||||
@@ -728,11 +714,11 @@ impl Drop for WindowsWindow {
|
||||
}
|
||||
|
||||
impl PlatformWindow for WindowsWindow {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
WindowBounds::Fixed(Bounds {
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
Bounds {
|
||||
origin: self.inner.origin.get(),
|
||||
size: self.inner.size.get(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// todo(windows)
|
||||
@@ -887,6 +873,11 @@ impl PlatformWindow for WindowsWindow {
|
||||
// todo(windows)
|
||||
fn toggle_full_screen(&self) {}
|
||||
|
||||
// todo(windows)
|
||||
fn is_full_screen(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
// todo(windows)
|
||||
fn on_request_frame(&self, callback: Box<dyn FnMut()>) {
|
||||
self.inner.callbacks.borrow_mut().request_frame = Some(callback);
|
||||
|
||||
Reference in New Issue
Block a user