mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 23:08:05 +08: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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user