Skip to content

Commit 747077c

Browse files
Desktop: Add window abstraction layer (#3299)
* window abstraction * fix linux * fix windows * fix fmt * remove windows file that was left * use self
1 parent 2582400 commit 747077c

File tree

9 files changed

+189
-120
lines changed

9 files changed

+189
-120
lines changed

desktop/src/app.rs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use rfd::AsyncFileDialog;
22
use std::fs;
33
use std::path::PathBuf;
4-
use std::sync::Arc;
54
use std::sync::mpsc::Receiver;
65
use std::sync::mpsc::Sender;
76
use std::sync::mpsc::SyncSender;
@@ -12,22 +11,20 @@ use winit::application::ApplicationHandler;
1211
use winit::event::WindowEvent;
1312
use winit::event_loop::ActiveEventLoop;
1413
use winit::event_loop::ControlFlow;
15-
use winit::window::Window;
1614
use winit::window::WindowId;
1715

1816
use crate::cef;
1917
use crate::consts::CEF_MESSAGE_LOOP_MAX_ITERATIONS;
2018
use crate::event::{AppEvent, AppEventScheduler};
21-
use crate::native_window;
2219
use crate::persist::PersistentData;
2320
use crate::render::GraphicsState;
21+
use crate::window::Window;
2422
use graphite_desktop_wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, Platform};
2523
use graphite_desktop_wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages};
2624

2725
pub(crate) struct App {
2826
cef_context: Box<dyn cef::CefContext>,
29-
window: Option<Arc<dyn Window>>,
30-
native_window: native_window::NativeWindowHandle,
27+
window: Option<Window>,
3128
cef_schedule: Option<Instant>,
3229
cef_window_size_sender: Sender<cef::WindowSize>,
3330
graphics_state: Option<GraphicsState>,
@@ -82,7 +79,6 @@ impl App {
8279
web_communication_initialized: false,
8380
web_communication_startup_buffer: Vec::new(),
8481
persistent_data,
85-
native_window: Default::default(),
8682
launch_documents,
8783
}
8884
}
@@ -173,18 +169,17 @@ impl App {
173169
}
174170
DesktopFrontendMessage::MinimizeWindow => {
175171
if let Some(window) = &self.window {
176-
window.set_minimized(true);
172+
window.minimize();
177173
}
178174
}
179175
DesktopFrontendMessage::MaximizeWindow => {
180176
if let Some(window) = &self.window {
181-
let maximized = !window.is_maximized();
182-
window.set_maximized(maximized);
177+
window.toggle_maximize();
183178
}
184179
}
185180
DesktopFrontendMessage::DragWindow => {
186181
if let Some(window) = &self.window {
187-
let _ = window.drag_window();
182+
let _ = window.start_drag();
188183
}
189184
}
190185
DesktopFrontendMessage::CloseWindow => {
@@ -348,15 +343,11 @@ impl App {
348343
}
349344
impl ApplicationHandler for App {
350345
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
351-
let window_attributes = self.native_window.build(event_loop);
352-
353-
let window: Arc<dyn Window> = Arc::from(event_loop.create_window(window_attributes).unwrap());
354-
355-
self.native_window.setup(window.as_ref());
346+
let window = Window::new(event_loop);
347+
self.window = Some(window);
356348

357-
let graphics_state = GraphicsState::new(window.clone(), self.wgpu_context.clone());
349+
let graphics_state = GraphicsState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone());
358350

359-
self.window = Some(window);
360351
self.graphics_state = Some(graphics_state);
361352

362353
tracing::info!("Winit window created and ready");
@@ -397,7 +388,7 @@ impl ApplicationHandler for App {
397388
let Some(ref mut graphics_state) = self.graphics_state else { return };
398389
// Only rerender once we have a new UI texture to display
399390
if let Some(window) = &self.window {
400-
match graphics_state.render(window.as_ref()) {
391+
match graphics_state.render(window) {
401392
Ok(_) => {}
402393
Err(wgpu::SurfaceError::Lost) => {
403394
tracing::warn!("lost surface");

desktop/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ mod cef;
1010
mod cli;
1111
mod dirs;
1212
mod event;
13-
mod native_window;
1413
mod persist;
1514
mod render;
15+
mod window;
1616

1717
mod gpu_context;
1818

desktop/src/native_window.rs

Lines changed: 0 additions & 71 deletions
This file was deleted.

desktop/src/render/graphics_state.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use std::sync::Arc;
2-
use winit::window::Window;
1+
use crate::window::Window;
32

43
use graphite_desktop_wrapper::{Color, WgpuContext, WgpuExecutor};
54

@@ -24,10 +23,9 @@ pub(crate) struct GraphicsState {
2423
}
2524

2625
impl GraphicsState {
27-
pub(crate) fn new(window: Arc<dyn Window>, context: WgpuContext) -> Self {
26+
pub(crate) fn new(window: &Window, context: WgpuContext) -> Self {
2827
let size = window.surface_size();
29-
30-
let surface = context.instance.create_surface(window).unwrap();
28+
let surface = window.create_surface(context.instance.clone());
3129

3230
let surface_caps = surface.get_capabilities(&context.adapter);
3331
let surface_format = surface_caps.formats.iter().find(|f| f.is_srgb()).copied().unwrap_or(surface_caps.formats[0]);
@@ -232,7 +230,7 @@ impl GraphicsState {
232230
self.bind_overlays_texture(texture);
233231
}
234232

235-
pub(crate) fn render(&mut self, window: &dyn Window) -> Result<(), wgpu::SurfaceError> {
233+
pub(crate) fn render(&mut self, window: &Window) -> Result<(), wgpu::SurfaceError> {
236234
if let Some(scene) = self.overlays_scene.take() {
237235
self.render_overlays(scene);
238236
}

desktop/src/window.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use std::sync::Arc;
2+
use winit::event_loop::ActiveEventLoop;
3+
use winit::window::{Window as WinitWindow, WindowAttributes};
4+
5+
use crate::consts::APP_NAME;
6+
7+
pub(crate) trait NativeWindow {
8+
fn configure(attributes: WindowAttributes, event_loop: &dyn ActiveEventLoop) -> WindowAttributes;
9+
fn new(window: &dyn WinitWindow) -> Self;
10+
}
11+
12+
#[cfg(target_os = "linux")]
13+
mod linux;
14+
#[cfg(target_os = "linux")]
15+
use linux as native;
16+
17+
#[cfg(target_os = "macos")]
18+
mod mac;
19+
#[cfg(target_os = "macos")]
20+
use mac as native;
21+
22+
#[cfg(target_os = "windows")]
23+
mod win;
24+
#[cfg(target_os = "windows")]
25+
use win as native;
26+
27+
pub(crate) struct Window {
28+
winit_window: Arc<dyn winit::window::Window>,
29+
#[allow(dead_code)]
30+
native_handle: native::NativeWindowImpl,
31+
}
32+
33+
impl Window {
34+
pub(crate) fn new(event_loop: &dyn ActiveEventLoop) -> Self {
35+
let mut attributes = WindowAttributes::default()
36+
.with_title(APP_NAME)
37+
.with_min_surface_size(winit::dpi::LogicalSize::new(400, 300))
38+
.with_surface_size(winit::dpi::LogicalSize::new(1200, 800))
39+
.with_resizable(true)
40+
.with_theme(Some(winit::window::Theme::Dark));
41+
42+
attributes = native::NativeWindowImpl::configure(attributes, event_loop);
43+
44+
let winit_window = event_loop.create_window(attributes).unwrap();
45+
let native_handle = native::NativeWindowImpl::new(winit_window.as_ref());
46+
Self {
47+
winit_window: winit_window.into(),
48+
native_handle,
49+
}
50+
}
51+
52+
pub(crate) fn request_redraw(&self) {
53+
self.winit_window.request_redraw();
54+
}
55+
56+
pub(crate) fn create_surface(&self, instance: Arc<wgpu::Instance>) -> wgpu::Surface<'static> {
57+
instance.create_surface(self.winit_window.clone()).unwrap()
58+
}
59+
60+
pub(crate) fn pre_present_notify(&self) {
61+
self.winit_window.pre_present_notify();
62+
}
63+
64+
pub(crate) fn surface_size(&self) -> winit::dpi::PhysicalSize<u32> {
65+
self.winit_window.surface_size()
66+
}
67+
68+
pub(crate) fn minimize(&self) {
69+
self.winit_window.set_minimized(true);
70+
}
71+
72+
pub(crate) fn toggle_maximize(&self) {
73+
self.winit_window.set_maximized(!self.winit_window.is_maximized());
74+
}
75+
76+
pub(crate) fn is_maximized(&self) -> bool {
77+
self.winit_window.is_maximized()
78+
}
79+
80+
pub(crate) fn start_drag(&self) {
81+
let _ = self.winit_window.drag_window();
82+
}
83+
84+
pub(crate) fn set_cursor(&self, cursor: winit::cursor::Cursor) {
85+
self.winit_window.set_cursor(cursor);
86+
}
87+
}

desktop/src/window/linux.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use winit::event_loop::ActiveEventLoop;
2+
use winit::platform::wayland::ActiveEventLoopExtWayland;
3+
use winit::platform::wayland::WindowAttributesWayland;
4+
use winit::platform::x11::WindowAttributesX11;
5+
use winit::window::{Window, WindowAttributes};
6+
7+
use crate::consts::{APP_ID, APP_NAME};
8+
9+
use super::NativeWindow;
10+
11+
pub(super) struct NativeWindowImpl {}
12+
13+
impl NativeWindow for NativeWindowImpl {
14+
fn configure(attributes: WindowAttributes, event_loop: &dyn ActiveEventLoop) -> WindowAttributes {
15+
if event_loop.is_wayland() {
16+
let wayland_attributes = WindowAttributesWayland::default().with_name(APP_ID, "").with_prefer_csd(true);
17+
attributes.with_platform_attributes(Box::new(wayland_attributes))
18+
} else {
19+
let x11_attributes = WindowAttributesX11::default().with_name(APP_ID, APP_NAME);
20+
attributes.with_platform_attributes(Box::new(x11_attributes))
21+
}
22+
}
23+
24+
fn new(_window: &dyn Window) -> Self {
25+
NativeWindowImpl {}
26+
}
27+
}

desktop/src/window/mac.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use winit::event_loop::ActiveEventLoop;
2+
use winit::window::{Window, WindowAttributes};
3+
4+
use super::NativeWindow;
5+
6+
pub(super) struct NativeWindowImpl {}
7+
8+
impl NativeWindow for NativeWindowImpl {
9+
fn configure(attributes: WindowAttributes, _event_loop: &dyn ActiveEventLoop) -> WindowAttributes {
10+
let mac_window = winit::platform::macos::WindowAttributesMacOS::default()
11+
.with_titlebar_transparent(true)
12+
.with_fullsize_content_view(true)
13+
.with_title_hidden(true);
14+
attributes.with_platform_attributes(Box::new(mac_window))
15+
}
16+
17+
fn new(_window: &dyn Window) -> Self {
18+
NativeWindowImpl {}
19+
}
20+
}

desktop/src/window/win.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use winit::event_loop::ActiveEventLoop;
2+
use winit::window::{Window, WindowAttributes};
3+
4+
use super::NativeWindow;
5+
6+
pub(super) struct NativeWindowImpl {
7+
native_handle: native_handle::NativeWindowHandle,
8+
}
9+
10+
impl NativeWindow for NativeWindowImpl {
11+
fn configure(attributes: WindowAttributes, _event_loop: &dyn ActiveEventLoop) -> WindowAttributes {
12+
if let Ok(win_icon) = winit::platform::windows::WinIcon::from_resource(1, None) {
13+
let icon = winit::icon::Icon(std::sync::Arc::new(win_icon));
14+
attributes.with_window_icon(Some(icon))
15+
} else {
16+
attributes
17+
}
18+
}
19+
20+
fn new(window: &dyn Window) -> Self {
21+
let native_handle = native_handle::NativeWindowHandle::new(window);
22+
NativeWindowImpl { native_handle }
23+
}
24+
}
25+
26+
impl Drop for NativeWindowImpl {
27+
fn drop(&mut self) {
28+
self.native_handle.destroy();
29+
}
30+
}
31+
32+
mod native_handle;

0 commit comments

Comments
 (0)