mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-12-23 10:11:54 +00:00
Desktop: Limit application to a single instance (#3441)
* only allow single instance * more reliable CEF cache cleanup * some cleanup * fix lock file location * add simple signal handling * fix skew handles on desktop * mac remove unused helpers
This commit is contained in:
parent
600fb5c28f
commit
39b5229df7
15 changed files with 206 additions and 34 deletions
128
Cargo.lock
generated
128
Cargo.lock
generated
|
|
@ -765,7 +765,7 @@ dependencies = [
|
|||
"thiserror 2.0.16",
|
||||
"tracing",
|
||||
"wgpu",
|
||||
"windows",
|
||||
"windows 0.58.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
|
|
@ -1242,6 +1242,17 @@ dependencies = [
|
|||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790"
|
||||
dependencies = [
|
||||
"dispatch2",
|
||||
"nix",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cursor-icon"
|
||||
version = "1.2.0"
|
||||
|
|
@ -1764,7 +1775,7 @@ dependencies = [
|
|||
"read-fonts 0.35.0",
|
||||
"roxmltree",
|
||||
"smallvec",
|
||||
"windows",
|
||||
"windows 0.58.0",
|
||||
"windows-core 0.58.0",
|
||||
"yeslogic-fontconfig-sys",
|
||||
]
|
||||
|
|
@ -2082,7 +2093,7 @@ dependencies = [
|
|||
"log",
|
||||
"presser",
|
||||
"thiserror 1.0.69",
|
||||
"windows",
|
||||
"windows 0.58.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2262,6 +2273,7 @@ dependencies = [
|
|||
"cef",
|
||||
"cef-dll-sys",
|
||||
"clap",
|
||||
"ctrlc",
|
||||
"derivative",
|
||||
"dirs",
|
||||
"futures",
|
||||
|
|
@ -2273,6 +2285,7 @@ dependencies = [
|
|||
"objc2-app-kit",
|
||||
"objc2-foundation",
|
||||
"open",
|
||||
"pidlock",
|
||||
"rand 0.9.2",
|
||||
"rfd",
|
||||
"ron",
|
||||
|
|
@ -2282,7 +2295,7 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
"vello",
|
||||
"wgpu",
|
||||
"windows",
|
||||
"windows 0.58.0",
|
||||
"winit",
|
||||
]
|
||||
|
||||
|
|
@ -4198,6 +4211,17 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||
|
||||
[[package]]
|
||||
name = "pidlock"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f837924d5368f9f35a1c404699de3c074311358035c77d7164f5948c08b31382"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"thiserror 1.0.69",
|
||||
"windows 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
|
|
@ -7029,7 +7053,7 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
"wgpu-types",
|
||||
"windows",
|
||||
"windows 0.58.0",
|
||||
"windows-core 0.58.0",
|
||||
]
|
||||
|
||||
|
|
@ -7088,6 +7112,27 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core 0.62.2",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.58.0"
|
||||
|
|
@ -7107,13 +7152,37 @@ version = "0.61.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.2.1",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
|
|
@ -7127,9 +7196,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -7149,9 +7218,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -7170,6 +7239,16 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.5.3"
|
||||
|
|
@ -7199,6 +7278,15 @@ dependencies = [
|
|||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
|
|
@ -7218,6 +7306,15 @@ dependencies = [
|
|||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
|
|
@ -7311,6 +7408,15 @@ dependencies = [
|
|||
"windows_x86_64_msvc 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ open = { workspace = true }
|
|||
rand = { workspace = true, features = ["thread_rng"] }
|
||||
serde = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
pidlock = "0.2.2"
|
||||
ctrlc = "3.5.1"
|
||||
|
||||
# Windows-specific dependencies
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ fn bundle(out_dir: &Path, app_bin: &Path, helper_bin: &Path) -> PathBuf {
|
|||
|
||||
create_app(&app_dir, APP_ID, APP_NAME, app_bin, false);
|
||||
|
||||
for helper_type in [None, Some("GPU"), Some("Renderer"), Some("Plugin"), Some("Alerts")] {
|
||||
for helper_type in [None, Some("GPU"), Some("Renderer")] {
|
||||
let helper_id_suffix = helper_type.map(|t| format!(".{t}")).unwrap_or_default();
|
||||
let helper_id = format!("{APP_ID}.helper{helper_id_suffix}");
|
||||
let helper_name_suffix = helper_type.map(|t| format!(" ({t})")).unwrap_or_default();
|
||||
|
|
|
|||
|
|
@ -56,6 +56,13 @@ impl App {
|
|||
app_event_scheduler: AppEventScheduler,
|
||||
launch_documents: Vec<PathBuf>,
|
||||
) -> Self {
|
||||
let ctrlc_app_event_scheduler = app_event_scheduler.clone();
|
||||
ctrlc::set_handler(move || {
|
||||
tracing::info!("Termination signal received, exiting...");
|
||||
ctrlc_app_event_scheduler.schedule(AppEvent::CloseWindow);
|
||||
})
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
|
||||
let rendering_app_event_scheduler = app_event_scheduler.clone();
|
||||
let (start_render_sender, start_render_receiver) = std::sync::mpsc::sync_channel(1);
|
||||
std::thread::spawn(move || {
|
||||
|
|
@ -365,6 +372,7 @@ impl App {
|
|||
tracing::info!("Exiting main event loop");
|
||||
event_loop.exit();
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
AppEvent::MenuEvent { id } => {
|
||||
self.dispatch_desktop_wrapper_message(DesktopWrapperMessage::MenuEvent { id });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use super::CefContext;
|
|||
use super::singlethreaded::SingleThreadedCefContext;
|
||||
use crate::cef::CefEventHandler;
|
||||
use crate::cef::consts::{RESOURCE_DOMAIN, RESOURCE_SCHEME};
|
||||
use crate::cef::dirs::create_instance_dir;
|
||||
use crate::cef::dirs::{create_instance_dir, delete_instance_dirs};
|
||||
use crate::cef::input::InputState;
|
||||
use crate::cef::internal::{BrowserProcessAppImpl, BrowserProcessClientImpl, RenderProcessAppImpl, SchemeHandlerFactoryImpl};
|
||||
|
||||
|
|
@ -85,6 +85,7 @@ impl<H: CefEventHandler> CefContextBuilder<H> {
|
|||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) fn initialize(self, event_handler: H, disable_gpu_acceleration: bool) -> Result<impl CefContext, InitError> {
|
||||
delete_instance_dirs();
|
||||
let instance_dir = create_instance_dir();
|
||||
|
||||
let exe = std::env::current_exe().expect("cannot get current exe path");
|
||||
|
|
@ -105,6 +106,7 @@ impl<H: CefEventHandler> CefContextBuilder<H> {
|
|||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub(crate) fn initialize(self, event_handler: H, disable_gpu_acceleration: bool) -> Result<impl CefContext, InitError> {
|
||||
delete_instance_dirs();
|
||||
let instance_dir = create_instance_dir();
|
||||
|
||||
let settings = Settings {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,19 @@ impl CefContext for SingleThreadedCefContext {
|
|||
impl Drop for SingleThreadedCefContext {
|
||||
fn drop(&mut self) {
|
||||
cef::shutdown();
|
||||
std::fs::remove_dir_all(&self.instance_dir).expect("Failed to remove CEF cache directory");
|
||||
|
||||
// Sometimes some CEF processes still linger at this point and hold file handles to the cache directory.
|
||||
// To mitigate this, we try to remove the directory multiple times with some delay.
|
||||
// TODO: find a better solution if possible.
|
||||
for _ in 0..30 {
|
||||
match std::fs::remove_dir_all(&self.instance_dir) {
|
||||
Ok(_) => break,
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to remove CEF cache directory, retrying...: {e}");
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,24 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::dirs::{ensure_dir_exists, graphite_data_dir};
|
||||
use crate::dirs::{app_data_dir, ensure_dir_exists};
|
||||
|
||||
static CEF_DIR_NAME: &str = "browser";
|
||||
|
||||
pub(crate) fn delete_instance_dirs() {
|
||||
let cef_dir = app_data_dir().join(CEF_DIR_NAME);
|
||||
if let Ok(entries) = std::fs::read_dir(&cef_dir) {
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
let _ = std::fs::remove_dir_all(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_instance_dir() -> PathBuf {
|
||||
let instance_id: String = (0..32).map(|_| format!("{:x}", rand::random::<u8>() % 16)).collect();
|
||||
let path = graphite_data_dir().join(CEF_DIR_NAME).join(instance_id);
|
||||
let path = app_data_dir().join(CEF_DIR_NAME).join(instance_id);
|
||||
ensure_dir_exists(&path);
|
||||
path
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use cef::sys::{cef_event_flags_t, cef_key_event_type_t, cef_mouse_button_type_t};
|
||||
use cef::sys::{cef_key_event_type_t, cef_mouse_button_type_t};
|
||||
use cef::{Browser, ImplBrowser, ImplBrowserHost, KeyEvent, MouseEvent};
|
||||
use winit::event::{ButtonSource, ElementState, MouseButton, MouseScrollDelta, WindowEvent};
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ mod keymap;
|
|||
use keymap::{ToCharRepresentation, ToNativeKeycode, ToVKBits};
|
||||
|
||||
mod state;
|
||||
pub(crate) use state::InputState;
|
||||
pub(crate) use state::{CefModifiers, InputState};
|
||||
|
||||
use super::consts::{PINCH_ZOOM_SPEED, SCROLL_LINE_HEIGHT, SCROLL_LINE_WIDTH, SCROLL_SPEED_X, SCROLL_SPEED_Y};
|
||||
|
||||
|
|
@ -129,9 +129,10 @@ pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputStat
|
|||
}
|
||||
let Some(host) = browser.host() else { return };
|
||||
|
||||
let mut mouse_event: MouseEvent = input_state.into();
|
||||
mouse_event.modifiers |= cef_event_flags_t::EVENTFLAG_CONTROL_DOWN.0 as u32;
|
||||
mouse_event.modifiers |= cef_event_flags_t::EVENTFLAG_PRECISION_SCROLLING_DELTA.0 as u32;
|
||||
let mouse_event = MouseEvent {
|
||||
modifiers: CefModifiers::PINCH_MODIFIERS.into(),
|
||||
..input_state.into()
|
||||
};
|
||||
|
||||
let delta = (delta * PINCH_ZOOM_SPEED).round() as i32;
|
||||
|
||||
|
|
|
|||
|
|
@ -240,10 +240,17 @@ impl CefModifiers {
|
|||
|
||||
Self(inner)
|
||||
}
|
||||
|
||||
pub(super) const PINCH_MODIFIERS: Self = Self(cef_event_flags_t(
|
||||
cef_event_flags_t::EVENTFLAG_CONTROL_DOWN.0 | cef_event_flags_t::EVENTFLAG_PRECISION_SCROLLING_DELTA.0,
|
||||
));
|
||||
}
|
||||
|
||||
impl Into<u32> for CefModifiers {
|
||||
fn into(self) -> u32 {
|
||||
self.0.0 as u32
|
||||
impl From<CefModifiers> for u32 {
|
||||
fn from(val: CefModifiers) -> Self {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
return val.0.0;
|
||||
#[cfg(target_os = "windows")]
|
||||
return val.0.0 as u32;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
pub(crate) const APP_NAME: &str = "Graphite";
|
||||
pub(crate) const APP_ID: &str = "rs.graphite.Graphite";
|
||||
|
||||
pub(crate) const APP_DIRECTORY_NAME: &str = "graphite-editor";
|
||||
pub(crate) const APP_DIRECTORY_NAME: &str = "graphite";
|
||||
pub(crate) const APP_LOCK_FILE_NAME: &str = "instance.lock";
|
||||
pub(crate) const APP_STATE_FILE_NAME: &str = "state.ron";
|
||||
pub(crate) const APP_PREFERENCES_FILE_NAME: &str = "preferences.ron";
|
||||
pub(crate) const APP_DOCUMENTS_DIRECTORY_NAME: &str = "documents";
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ pub(crate) fn ensure_dir_exists(path: &PathBuf) {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn graphite_data_dir() -> PathBuf {
|
||||
pub(crate) fn app_data_dir() -> PathBuf {
|
||||
let path = dirs::data_dir().expect("Failed to get data directory").join(APP_DIRECTORY_NAME);
|
||||
ensure_dir_exists(&path);
|
||||
path
|
||||
}
|
||||
|
||||
pub(crate) fn graphite_autosave_documents_dir() -> PathBuf {
|
||||
let path = graphite_data_dir().join(APP_DOCUMENTS_DIRECTORY_NAME);
|
||||
pub(crate) fn app_autosave_documents_dir() -> PathBuf {
|
||||
let path = app_data_dir().join(APP_DOCUMENTS_DIRECTORY_NAME);
|
||||
ensure_dir_exists(&path);
|
||||
path
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ pub(crate) enum AppEvent {
|
|||
DesktopWrapperMessage(DesktopWrapperMessage),
|
||||
NodeGraphExecutionResult(NodeGraphExecutionResult),
|
||||
CloseWindow,
|
||||
MenuEvent { id: String },
|
||||
#[cfg(target_os = "macos")]
|
||||
MenuEvent {
|
||||
id: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ use cef::CefHandler;
|
|||
use cli::Cli;
|
||||
use event::CreateAppEventSchedulerEventLoopExt;
|
||||
|
||||
use crate::consts::APP_LOCK_FILE_NAME;
|
||||
|
||||
pub fn start() {
|
||||
tracing_subscriber::fmt().with_env_filter(EnvFilter::from_default_env()).init();
|
||||
|
||||
|
|
@ -36,6 +38,22 @@ pub fn start() {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut lock = pidlock::Pidlock::new_validated(dirs::app_data_dir().join(APP_LOCK_FILE_NAME)).unwrap();
|
||||
match lock.acquire() {
|
||||
Ok(lock) => {
|
||||
tracing::info!("Acquired application lock");
|
||||
lock
|
||||
}
|
||||
Err(pidlock::PidlockError::LockExists) => {
|
||||
tracing::error!("Another instance is already running, Exiting.");
|
||||
exit(0);
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to acquire application lock: {err}");
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
App::init();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
|
@ -56,7 +74,7 @@ pub fn start() {
|
|||
}
|
||||
Err(cef::InitError::AlreadyRunning) => {
|
||||
tracing::error!("Another instance is already running, Exiting.");
|
||||
exit(0);
|
||||
exit(1);
|
||||
}
|
||||
Err(cef::InitError::InitializationFailed(code)) => {
|
||||
tracing::error!("Cef initialization failed with code: {code}");
|
||||
|
|
|
|||
|
|
@ -125,13 +125,13 @@ impl PersistentData {
|
|||
}
|
||||
|
||||
fn state_file_path() -> std::path::PathBuf {
|
||||
let mut path = crate::dirs::graphite_data_dir();
|
||||
let mut path = crate::dirs::app_data_dir();
|
||||
path.push(crate::consts::APP_STATE_FILE_NAME);
|
||||
path
|
||||
}
|
||||
|
||||
fn preferences_file_path() -> std::path::PathBuf {
|
||||
let mut path = crate::dirs::graphite_data_dir();
|
||||
let mut path = crate::dirs::app_data_dir();
|
||||
path.push(crate::consts::APP_PREFERENCES_FILE_NAME);
|
||||
path
|
||||
}
|
||||
|
|
@ -189,7 +189,7 @@ impl DocumentStore {
|
|||
}
|
||||
|
||||
fn document_path(id: &DocumentId) -> std::path::PathBuf {
|
||||
let mut path = crate::dirs::graphite_autosave_documents_dir();
|
||||
let mut path = crate::dirs::app_autosave_documents_dir();
|
||||
path.push(format!("{:x}.graphite", id.0));
|
||||
path
|
||||
}
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ impl OverlayContextInternal {
|
|||
let mid = edge_end.midpoint(edge_start);
|
||||
|
||||
for edge in [edge_dir, -edge_dir] {
|
||||
self.draw_triangle(mid + edge * 3. + SKEW_TRIANGLE_OFFSET, edge, SKEW_TRIANGLE_SIZE, None, None);
|
||||
self.draw_triangle(mid + edge * (3. + SKEW_TRIANGLE_OFFSET), edge, SKEW_TRIANGLE_SIZE, None, None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue