Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions desktop/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::persist::PersistentData;
use crate::preferences;
use crate::render::{RenderError, RenderState};
use crate::window::Window;
use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, InputMessage, MouseKeys, MouseState};
use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, InputMessage, MouseKeys, MouseState, Preferences};
use crate::wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages};

pub(crate) struct App {
Expand All @@ -46,6 +46,8 @@ pub(crate) struct App {
web_communication_initialized: bool,
web_communication_startup_buffer: Vec<Vec<u8>>,
persistent_data: PersistentData,
#[cfg_attr(not(target_os = "macos"), expect(unused))]
preferences: Preferences,
Comment on lines +49 to +50
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The expect(unused) attribute is likely not what you intend here. The #[expect] attribute is a Clippy attribute used to assert that a lint is triggered for the annotated code, and it will emit a clippy::needless_expect warning if the lint isn't triggered.

While it does suppress the original unused lint, the idiomatic way to suppress warnings for code that is intentionally unused on certain platforms is with #[allow]. Using #[allow(dead_code)] is more specific and clearly communicates the intent without the extra noise of expect.

Suggested change
#[cfg_attr(not(target_os = "macos"), expect(unused))]
preferences: Preferences,
#[cfg_attr(not(target_os = "macos"), allow(dead_code))]
preferences: Preferences,

cli: Cli,
startup_time: Option<Instant>,
exiting: Arc<AtomicBool>,
Expand All @@ -63,6 +65,7 @@ impl App {
wgpu_context: WgpuContext,
app_event_receiver: Receiver<AppEvent>,
app_event_scheduler: AppEventScheduler,
preferences: Preferences,
cli: Cli,
) -> Self {
let ctrlc_app_event_scheduler = app_event_scheduler.clone();
Expand Down Expand Up @@ -116,6 +119,7 @@ impl App {
web_communication_initialized: false,
web_communication_startup_buffer: Vec::new(),
persistent_data,
preferences,
cli,
startup_time: None,
exiting,
Expand Down Expand Up @@ -516,7 +520,12 @@ impl ApplicationHandler for App {
let window = Window::new(event_loop, self.app_event_scheduler.clone());
self.window = Some(window);

let render_state = RenderState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone());
#[cfg(not(target_os = "macos"))]
let present_mode = None;
#[cfg(target_os = "macos")]
let present_mode = if !self.preferences.vsync { Some(wgpu::PresentMode::Immediate) } else { None };

let render_state = RenderState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone(), present_mode);
self.render_state = Some(render_state);

if let Some(window) = &self.window.as_ref() {
Expand Down
10 changes: 6 additions & 4 deletions desktop/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub fn start() {
}
};

let prefs = preferences::read();

// Must be called before event loop initialization or native window integrations will break
App::init();

Expand All @@ -73,7 +75,7 @@ pub fn start() {

let (cef_view_info_sender, cef_view_info_receiver) = std::sync::mpsc::channel();

let disable_ui_acceleration = preferences::read().disable_ui_acceleration || cli.disable_ui_acceleration;
let disable_ui_acceleration = prefs.disable_ui_acceleration || cli.disable_ui_acceleration;
if disable_ui_acceleration {
println!("UI acceleration is disabled");
}
Expand All @@ -95,7 +97,7 @@ pub fn start() {
}
};

let app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli);
let app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, prefs, cli);

let exit_reason = app.run(event_loop);

Expand All @@ -111,15 +113,15 @@ pub fn start() {
drop(lock);

match exit_reason {
#[cfg(target_os = "linux")]
app::ExitReason::Restart | app::ExitReason::UiAccelerationFailure => {
tracing::error!("Restarting application");
let mut command = std::process::Command::new(std::env::current_exe().unwrap());
#[cfg(target_family = "unix")]
let _ = std::os::unix::process::CommandExt::exec(&mut command);
#[cfg(target_family = "unix")]
tracing::error!("Failed to restart application");
#[cfg(not(target_family = "unix"))]
let _ = command.spawn();
tracing::error!("Failed to restart application");
}
_ => {}
}
Expand Down
8 changes: 3 additions & 5 deletions desktop/src/render/state.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::borrow::Cow;
use wgpu::PresentMode;

use crate::window::Window;
use crate::wrapper::{TargetTexture, WgpuContext, WgpuExecutor};
Expand Down Expand Up @@ -27,7 +28,7 @@ pub(crate) struct RenderState {
}

impl RenderState {
pub(crate) fn new(window: &Window, context: WgpuContext) -> Self {
pub(crate) fn new(window: &Window, context: WgpuContext, present_mode: Option<PresentMode>) -> Self {
let size = window.surface_size();
let surface = window.create_surface(context.instance.clone());

Expand All @@ -39,10 +40,7 @@ impl RenderState {
format: surface_format,
width: size.width,
height: size.height,
#[cfg(not(target_os = "macos"))]
present_mode: surface_caps.present_modes[0],
#[cfg(target_os = "macos")]
present_mode: wgpu::PresentMode::Immediate,
present_mode: present_mode.unwrap_or(surface_caps.present_modes[0]),
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
desired_maximum_frame_latency: 1,
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/window/mac/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn menu_items_from_wrapper(entries: Vec<WrapperMenuItem>) -> Vec<MenuItemKind> {
}
WrapperMenuItem::SubMenu { text: name, items, .. } => {
let items = menu_items_from_wrapper(items);
let items = items.iter().map(|item| menu_item_kind_to_dyn(item)).collect::<Vec<&dyn IsMenuItem>>();
let items = items.iter().map(menu_item_kind_to_dyn).collect::<Vec<&dyn IsMenuItem>>();
let submenu = Submenu::with_items(name, true, &items).unwrap();
menu_items.push(MenuItemKind::Submenu(submenu));
}
Expand Down Expand Up @@ -106,7 +106,7 @@ fn replace_children<'a, T: Into<MenuContainer<'a>>>(menu: T, new_items: Vec<Menu
for item in items.iter() {
menu.remove(menu_item_kind_to_dyn(item)).unwrap();
}
let items = new_items.iter().map(|item| menu_item_kind_to_dyn(item)).collect::<Vec<&dyn IsMenuItem>>();
let items = new_items.iter().map(menu_item_kind_to_dyn).collect::<Vec<&dyn IsMenuItem>>();
menu.append_items(items.as_ref()).unwrap();
}

Expand Down
4 changes: 2 additions & 2 deletions desktop/wrapper/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub(crate) mod menu {
panic!("Menu bar layout group is supposed to be a row");
};
widgets
.into_iter()
.iter()
.map(|widget| {
let text_button = match widget.widget.as_ref() {
Widget::TextButton(text_button) => text_button,
Expand Down Expand Up @@ -79,7 +79,7 @@ pub(crate) mod menu {
let enabled = !*disabled;

if !children.is_empty() {
let items = convert_menu_bar_entry_children_to_menu_items(&children, root_widget_id, path.clone());
let items = convert_menu_bar_entry_children_to_menu_items(children, root_widget_id, path.clone());
return MenuItem::SubMenu { id, text, enabled, items };
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,44 @@ impl PreferencesDialogMessageHandler {

rows.push(ui_acceleration);
}

#[cfg(target_os = "macos")]
{
let vsync_description = "
Render frames with vertical synchronization (v-sync) to prevent visual tearing within Graphite and the operating system compositor. This introduces increased input latency which is more noticeable on lower refresh rate displays. Future versions of Graphite will aim to reduce the macOS-specific latency without tearing artifacts.\n\
\n\
The application will restart for this change to take effect.\n\
\n\
*Default: Off.*
"
.trim();

let checkbox_id = CheckboxId::new();
let vsync_checked = preferences.vsync;

let vsync = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
CheckboxInput::new(vsync_checked)
.tooltip_label("Enable V-Sync")
.tooltip_description(vsync_description)
.on_update(|checkbox_input: &CheckboxInput| Message::Batched {
messages: Box::new([PreferencesDialogMessage::MayRequireRestart.into(), PreferencesMessage::VSync { vsync: checkbox_input.checked }.into()]),
})
.for_label(checkbox_id)
.widget_instance(),
TextLabel::new("Enable V-Sync")
.tooltip_label("Enable V-Sync")
.tooltip_description(vsync_description)
.for_checkbox(checkbox_id)
.widget_instance(),
];

rows.push(vsync);
}
}

Layout(rows.into_iter().map(|r| LayoutGroup::row(r)).collect())
Layout(rows.into_iter().map(LayoutGroup::row).collect())
}

pub fn send_layout(&self, responses: &mut VecDeque<Message>, layout_target: LayoutTarget, preferences: &PreferencesMessageHandler) {
Expand Down
40 changes: 31 additions & 9 deletions editor/src/messages/preferences/preferences_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,38 @@ use crate::messages::prelude::*;
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum PreferencesMessage {
// Management messages
Load { preferences: PreferencesMessageHandler },
Load {
preferences: PreferencesMessageHandler,
},
ResetToDefaults,

// Per-preference messages
SelectionMode { selection_mode: SelectionMode },
BrushTool { enabled: bool },
ModifyLayout { zoom_with_scroll: bool },
GraphWireStyle { style: GraphWireStyle },
ViewportZoomWheelRate { rate: f64 },
UIScale { scale: f64 },
DisableUIAcceleration { disable_ui_acceleration: bool },
MaxRenderRegionSize { size: u32 },
SelectionMode {
selection_mode: SelectionMode,
},
BrushTool {
enabled: bool,
},
ModifyLayout {
zoom_with_scroll: bool,
},
GraphWireStyle {
style: GraphWireStyle,
},
ViewportZoomWheelRate {
rate: f64,
},
UIScale {
scale: f64,
},
MaxRenderRegionSize {
size: u32,
},
DisableUIAcceleration {
disable_ui_acceleration: bool,
},
#[cfg(target_os = "macos")]
VSync {
vsync: bool,
},
}
24 changes: 19 additions & 5 deletions editor/src/messages/preferences/preferences_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,23 @@ pub struct PreferencesMessageHandler {
pub graph_wire_style: GraphWireStyle,
pub viewport_zoom_wheel_rate: f64,
pub ui_scale: f64,
pub disable_ui_acceleration: bool,
pub max_render_region_size: u32,
pub disable_ui_acceleration: bool,
#[cfg(target_os = "macos")]
pub vsync: bool,
}

impl PreferencesMessageHandler {
#[cfg(not(target_os = "macos"))]
pub fn needs_restart(&self, other: &Self) -> bool {
self.disable_ui_acceleration != other.disable_ui_acceleration
}

#[cfg(target_os = "macos")]
pub fn needs_restart(&self, other: &Self) -> bool {
self.disable_ui_acceleration != other.disable_ui_acceleration || self.vsync != other.vsync
}

pub fn get_selection_mode(&self) -> SelectionMode {
self.selection_mode
}
Expand All @@ -54,8 +62,10 @@ impl Default for PreferencesMessageHandler {
graph_wire_style: GraphWireStyle::default(),
viewport_zoom_wheel_rate: VIEWPORT_ZOOM_WHEEL_RATE,
ui_scale: UI_SCALE_DEFAULT,
disable_ui_acceleration: false,
max_render_region_size: EditorPreferences::default().max_render_region_size,
disable_ui_acceleration: false,
#[cfg(target_os = "macos")]
vsync: false,
}
}
}
Expand Down Expand Up @@ -112,14 +122,18 @@ impl MessageHandler<PreferencesMessage, PreferencesMessageContext<'_>> for Prefe
self.ui_scale = scale;
responses.add(FrontendMessage::UpdateUIScale { scale: self.ui_scale });
}
PreferencesMessage::DisableUIAcceleration { disable_ui_acceleration } => {
self.disable_ui_acceleration = disable_ui_acceleration;
}
PreferencesMessage::MaxRenderRegionSize { size } => {
self.max_render_region_size = size;
responses.add(PortfolioMessage::EditorPreferences);
responses.add(NodeGraphMessage::RunDocumentGraph);
}
PreferencesMessage::DisableUIAcceleration { disable_ui_acceleration } => {
self.disable_ui_acceleration = disable_ui_acceleration;
}
#[cfg(target_os = "macos")]
PreferencesMessage::VSync { vsync } => {
self.vsync = vsync;
}
}

responses.add(FrontendMessage::TriggerSavePreferences { preferences: self.clone() });
Expand Down
2 changes: 1 addition & 1 deletion node-graph/nodes/gstd/src/pixel_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub async fn pixel_preview<'a: 'n>(
let physical_scale = render_params.scale;

let footprint = *ctx.footprint();
let viewport_zoom = footprint.decompose_scale().x;
let viewport_zoom = footprint.decompose_scale().x * physical_scale;

if render_params.render_mode != RenderMode::PixelPreview || !matches!(render_params.render_output_type, RenderOutputTypeRequest::Vello) || viewport_zoom <= 1. {
let context = OwnedContextImpl::from(ctx).into_context();
Expand Down
Loading