Skip to content

Commit

Permalink
Finally fix small window (#731)
Browse files Browse the repository at this point in the history
  • Loading branch information
ImUrX authored Jun 20, 2023
1 parent d6862f1 commit 366a255
Show file tree
Hide file tree
Showing 10 changed files with 5,341 additions and 4,398 deletions.
959 changes: 533 additions & 426 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@fontsource/poppins": "^4.5.8",
"@formatjs/intl-localematcher": "^0.2.32",
"@react-three/fiber": "^8.10.0",
"@tauri-apps/api": "^1.2.0",
"@tauri-apps/api": "^1.4.0",
"@vitejs/plugin-react": "^3.0.0",
"browserslist": "^4.18.1",
"classnames": "^2.3.1",
Expand Down Expand Up @@ -65,7 +65,7 @@
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.0",
"@tauri-apps/cli": "^1.2.3",
"@tauri-apps/cli": "^1.4.0",
"@types/file-saver": "^2.0.5",
"@types/react": "18.0.25",
"@types/react-dom": "^18.0.5",
Expand Down
16 changes: 8 additions & 8 deletions gui/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,27 @@ custom-protocol = ["tauri/custom-protocol"]
[build-dependencies]
tauri-build = { version = "1.2", features = [] }
cfg_aliases = "0.1"
shadow-rs = "0.21"
shadow-rs = "0.23"

[dependencies]
serde_json = "1"
serde = { version = "1", features = ["derive"] }
tauri = { version = "1.2", features = ["devtools", "dialog", "dialog-save", "fs-all", "os-all", "path-all", "shell-execute", "shell-open", "window-close", "window-maximize", "window-minimize", "window-set-resizable", "window-set-size", "window-set-title", "window-start-dragging", "window-unmaximize", "window-unminimize"] }
tauri-runtime = "0.12.1"
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
pretty_env_logger = "0.4"
tauri = { version = "1.4", features = ["devtools", "dialog", "dialog-save", "fs-all", "os-all", "path-all", "shell-execute", "shell-open", "window-close", "window-maximize", "window-minimize", "window-set-resizable", "window-set-size", "window-set-title", "window-start-dragging", "window-unmaximize", "window-unminimize"] }
tauri-runtime = "0.14"
pretty_env_logger = "0.5"
log = "0.4"
clap = { version = "4.0.29", features = ["derive"] }
clap-verbosity-flag = "2"
rand = "0.8.5"
tempfile = "3"
which = "4.3"
glob = "0.3"
open = "3"
shadow-rs = { version = "0.21", default-features = false }
open = "4"
shadow-rs = { version = "0.23", default-features = false }
const_format = "0.2.30"
cfg-if = "1"
color-eyre = "0.6"

[target.'cfg(windows)'.dependencies]
win32job = "1"
winreg = "0.10.1"
winreg = "0.50"
66 changes: 61 additions & 5 deletions gui/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,43 @@
#![cfg_attr(all(not(debug_assertions), windows), windows_subsystem = "windows")]
use std::env;
use std::panic;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;
use std::time::Instant;

use clap::Parser;
use state::WindowState;
use tauri::api::process::{Command, CommandChild};
use tauri::Manager;
use tauri::RunEvent;

#[cfg(windows)]
use tauri::WindowEvent;

use crate::util::{
get_launch_path, show_error, valid_java_paths, Cli, JAVA_BIN, MINIMUM_JAVA_VERSION,
};

mod state;
mod util;

#[tauri::command]
fn update_window_state(
window: tauri::Window,
state: tauri::State<Mutex<WindowState>>,
) -> Result<(), String> {
let mut lock = state.lock().unwrap();
lock.update_state(&window, false)
.map_err(|e| format!("{:?}", e))?;
if window.is_maximized().map_err(|e| e.to_string())? {
window.unmaximize().map_err(|e| e.to_string())?;
lock.update_state(&window, true)
.map_err(|e| format!("{:?}", e))?;
}
Ok(())
}

fn main() {
// Make an error dialog box when panicking
panic::set_hook(Box::new(|panic_info| {
Expand Down Expand Up @@ -108,8 +124,32 @@ fn main() {

let exit_flag_terminated = exit_flag.clone();
let build_result = tauri::Builder::default()
.plugin(tauri_plugin_window_state::Builder::default().build())
.invoke_handler(tauri::generate_handler![update_window_state])
.setup(move |app| {
let window_state =
WindowState::open_state(app.path_resolver().app_config_dir().unwrap())
.unwrap_or_default();

let window = tauri::WindowBuilder::new(
app,
"local",
tauri::WindowUrl::App("index.html".into()),
)
.title("SlimeVR")
.inner_size(1289.0, 709.0)
.min_inner_size(393.0, 667.0)
.resizable(true)
.visible(true)
.decorations(false)
.fullscreen(false)
.disable_file_drop_handler()
.build()?;
if window_state.is_old() {
window_state.update_window(&window, false)?;
}

app.manage(Mutex::new(window_state));

if let Some(mut recv) = stdout_recv {
let app_handle = app.app_handle();
tauri::async_runtime::spawn(async move {
Expand Down Expand Up @@ -139,6 +179,12 @@ fn main() {
Ok(())
})
.on_window_event(|e| match e.event() {
WindowEvent::CloseRequested { .. } => {
let window_state = e.window().state::<Mutex<WindowState>>();
if let Err(e) = update_window_state(e.window().clone(), window_state) {
log::error!("failed to update window state {}", e)
}
}
// See https://github.com/tauri-apps/tauri/issues/4012#issuecomment-1449499149
#[cfg(windows)]
WindowEvent::Resized(_) => std::thread::sleep(std::time::Duration::from_nanos(1)),
Expand All @@ -147,8 +193,18 @@ fn main() {
.build(tauri::generate_context!());
match build_result {
Ok(app) => {
app.run(move |_app_handle, event| match event {
app.run(move |app_handle, event| match event {
RunEvent::ExitRequested { .. } => {
let window_state = app_handle.state::<Mutex<WindowState>>();
let lock = window_state.lock().unwrap();
let config_dir =
app_handle.path_resolver().app_config_dir().unwrap();
let window_state_res = lock.save_state(config_dir);
match window_state_res {
Ok(()) => log::info!("saved window state"),
Err(e) => log::error!("failed to save window state: {}", e),
}

let Some(ref mut child) = backend else { return };
let write_result = child.write(b"exit\n");
match write_result {
Expand Down
110 changes: 110 additions & 0 deletions gui/src-tauri/src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use std::{fs, path::PathBuf};

use color_eyre::Result;
use serde::{Deserialize, Serialize};
use tauri::{LogicalSize, Monitor, PhysicalPosition, PhysicalSize, Window};

static STATE_FILENAME: &str = ".window-state.json";

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct WindowState {
maximized: bool,
width: f64,
height: f64,
x: i32,
y: i32,
#[serde(skip)]
old: bool,
}

impl WindowState {
pub fn open_state(path: PathBuf) -> Option<Self> {
if let Ok(file) = fs::File::open(path.join(STATE_FILENAME)) {
return serde_json::from_reader(file)
.map(|mut s: WindowState| {
s.old = true;
s
})
.ok();
}
None
}

pub fn is_old(&self) -> bool {
self.old
}

pub fn save_state(&self, path: PathBuf) -> Result<()> {
if !path.exists() {
fs::create_dir(&path)?
}
let file = fs::File::create(path.join(STATE_FILENAME))?;
serde_json::to_writer(file, self)?;
Ok(())
}

pub fn update_state(
&mut self,
window: &Window,
ignore_maximized: bool,
) -> Result<()> {
let maximized = window.is_maximized()?;
self.maximized = maximized || (self.maximized && ignore_maximized);
// We early return when it's maximized because we dont have to save the state
// of the rest of the window when it's maximized.
if maximized {
return Ok(());
}
let scale_factor = window.scale_factor()?;
let size = window.outer_size()?.to_logical::<f64>(scale_factor);
let pos = window.outer_position()?;

self.width = size.width;
self.height = size.height;

self.x = pos.x;
self.y = pos.y;
Ok(())
}

pub fn update_window(&self, window: &Window, ignore_maximized: bool) -> Result<()> {
let maximized = !ignore_maximized && window.is_maximized()?;
if maximized && !self.maximized {
window.unmaximize()?;
}

window.set_size(LogicalSize::new(self.width, self.height))?;

let pos = PhysicalPosition::new(self.x, self.y);
for monitor in window.available_monitors()? {
if monitor.contains(pos) {
window.set_position(pos)?;
break;
}
}

if !ignore_maximized && !maximized && self.maximized {
window.maximize()?;
}

Ok(())
}
}

pub trait MonitorExt {
fn contains(&self, position: PhysicalPosition<i32>) -> bool;
}

/// Allowed amount to overflow out of the screen
const ALLOWED_OVERFLOW: i32 = 16;
impl MonitorExt for Monitor {
fn contains(&self, position: PhysicalPosition<i32>) -> bool {
let PhysicalPosition { x, y } = *self.position();
let PhysicalSize { width, height } = *self.size();

(x < position.x + ALLOWED_OVERFLOW) as _
&& (position.x - ALLOWED_OVERFLOW) < (x + width as i32)
&& (y - ALLOWED_OVERFLOW) < position.y as _
&& (position.y + ALLOWED_OVERFLOW) < (y + height as i32)
}
}
7 changes: 2 additions & 5 deletions gui/src-tauri/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn get_launch_path(cli: Cli) -> Option<PathBuf> {
let paths = [
cli.launch_from_path,
// AppImage passes the fakeroot in `APPDIR` env var.
env::var_os("APPDIR").map(|x| PathBuf::from(x)),
env::var_os("APPDIR").map(PathBuf::from),
env::current_dir().ok(),
// getcwd in Mac can't be trusted, so let's get the executable's path
env::current_exe()
Expand All @@ -73,10 +73,7 @@ pub fn get_launch_path(cli: Cli) -> Option<PathBuf> {
Some(PathBuf::from("/usr/share/slimevr/")),
];

paths
.into_iter()
.filter_map(|x| x)
.find(|x| is_valid_path(x))
paths.into_iter().flatten().find(|x| is_valid_path(x))
}

pub fn spawn_java(java: &OsStr, java_version: &OsStr) -> std::io::Result<Child> {
Expand Down
17 changes: 0 additions & 17 deletions gui/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,6 @@
"setSize": true
}
},
"windows": [
{
"title": "SlimeVR",
"width": 1289,
"height": 709,
"minWidth": 393,
"minHeight": 667,
"resizable": true,
"fullscreen": false,
"decorations": false,
"transparent": false,
"fileDropEnabled": false,
"visible": true,
"hiddenTitle": true,
"tabbingIdentifier": "slimevr"
}
],
"security": {
"csp": null
}
Expand Down
30 changes: 0 additions & 30 deletions gui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@ import { os } from '@tauri-apps/api';
import { VMCSettings } from './components/settings/pages/VMCSettings';
import { MountingChoose } from './components/onboarding/pages/mounting/MountingChoose';
import { ProportionsChoose } from './components/onboarding/pages/body-proportions/ProportionsChoose';
import { LogicalSize, appWindow } from '@tauri-apps/api/window';
import { StatusProvider } from './components/providers/StatusSystemContext';
import { VersionUpdateModal } from './components/VersionUpdateModal';
import { CalibrationTutorialPage } from './components/onboarding/pages/CalibrationTutorial';
import { AssignmentTutorialPage } from './components/onboarding/pages/assignment-preparation/AssignmentTutorial';
import { open } from '@tauri-apps/api/shell';
import semver from 'semver';
import { tauri } from '../src-tauri/tauri.conf.json';
import { useBreakpoint } from './hooks/breakpoint';
import { VRModePage } from './components/vr-mode/VRModePage';

Expand Down Expand Up @@ -148,11 +146,6 @@ function Layout() {
);
}

const MIN_SIZE = {
width: tauri.windows[0].minWidth,
height: tauri.windows[0].minHeight,
};

export default function App() {
const websocketAPI = useProvideWebsocketApi();
const { l10n } = useLocalization();
Expand Down Expand Up @@ -190,29 +183,6 @@ export default function App() {
}, []);
}

// This doesn't seem to resize it live, but if you close it, it gets restored to min size
useEffect(() => {
if (!document.body.classList.contains('windows_nt')) return;
const interval = setInterval(() => {
appWindow
.outerSize()
.then(async (size) => {
const logicalSize = size.toLogical(await appWindow.scaleFactor());
if (
logicalSize.height < MIN_SIZE.height ||
logicalSize.width < MIN_SIZE.width
) {
appWindow.setSize(new LogicalSize(MIN_SIZE.width, MIN_SIZE.height));
}
})
.catch((r) => {
console.error(r);
clearInterval(interval);
});
}, 5000);
return () => clearInterval(interval);
}, []);

if (window.__TAURI_METADATA__) {
useEffect(() => {
const unlisten = listen(
Expand Down
Loading

0 comments on commit 366a255

Please sign in to comment.