mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-13 04:34:21 -10:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84cbbac006 | ||
|
|
e481c900ca | ||
|
|
2f3a012de7 | ||
|
|
49f9c57bcc | ||
|
|
07609ef9c6 | ||
|
|
bf2427bd3a | ||
|
|
4670859abd |
No files matched your search
Generated
+36
-35
@@ -4038,7 +4038,7 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||
|
||||
[[package]]
|
||||
name = "ide-agent"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"encoding_rs",
|
||||
@@ -4061,7 +4061,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-analysis"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ast-grep-core",
|
||||
"ide-core",
|
||||
@@ -4075,7 +4075,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-build"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dirs 6.0.0",
|
||||
"dunce",
|
||||
@@ -4090,7 +4090,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-clipboard"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"objc2 0.6.5",
|
||||
"objc2-app-kit 0.3.2",
|
||||
@@ -4099,7 +4099,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-core"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"encoding_rs",
|
||||
@@ -4115,7 +4115,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-coverage"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"ide-run",
|
||||
@@ -4129,7 +4129,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-dap"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"ide-jsonrpc",
|
||||
@@ -4147,7 +4147,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-db"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"bb8",
|
||||
"dirs 6.0.0",
|
||||
@@ -4169,7 +4169,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-docker"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"libc",
|
||||
@@ -4183,7 +4183,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-fonts"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-text",
|
||||
@@ -4195,7 +4195,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-github"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"ide-vcs",
|
||||
@@ -4209,7 +4209,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-host"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dirs 6.0.0",
|
||||
"dunce",
|
||||
@@ -4254,7 +4254,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-http"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"parking_lot",
|
||||
@@ -4272,7 +4272,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-index"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"criterion",
|
||||
@@ -4294,7 +4294,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-jsonrpc"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"futures",
|
||||
@@ -4310,7 +4310,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-language"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"criterion",
|
||||
@@ -4365,7 +4365,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-lsp"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"futures",
|
||||
@@ -4390,7 +4390,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-notebook"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"ide-core",
|
||||
@@ -4413,7 +4413,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-plugin"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"ide-language",
|
||||
@@ -4431,7 +4431,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-profiler"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"ide-run",
|
||||
@@ -4444,7 +4444,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-remote"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"globset",
|
||||
"ide-core",
|
||||
@@ -4461,7 +4461,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-run"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"encoding_rs",
|
||||
@@ -4484,7 +4484,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-sdk"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"ide-core",
|
||||
@@ -4503,7 +4503,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-search"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"globset",
|
||||
@@ -4523,7 +4523,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-spell"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"parking_lot",
|
||||
@@ -4536,7 +4536,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-ssh"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dirs 6.0.0",
|
||||
"flate2",
|
||||
@@ -4555,7 +4555,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-syntax"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"ide-language",
|
||||
@@ -4570,7 +4570,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-terminal"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"libc",
|
||||
@@ -4583,7 +4583,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-text"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"ide-core",
|
||||
@@ -4595,7 +4595,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-tools"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"hex",
|
||||
@@ -4616,7 +4616,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-vcs"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"encoding_rs",
|
||||
@@ -4635,7 +4635,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-vfs"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"chardetng",
|
||||
"dunce",
|
||||
@@ -4657,7 +4657,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-web"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"ide-core",
|
||||
"open",
|
||||
@@ -4673,7 +4673,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ide-workspace"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"dunce",
|
||||
@@ -6144,7 +6144,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openidea"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"block2 0.6.2",
|
||||
@@ -6207,6 +6207,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ resolver = "3"
|
||||
members = ["crates/*", "src-tauri"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
edition = "2024"
|
||||
rust-version = "1.96"
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
·
|
||||
<a href="#benchmark">Benchmark</a>
|
||||
·
|
||||
<a href="#build">Build</a>
|
||||
·
|
||||
<a href="https://discord.gg/2Zy4yn7gP">Discord</a>
|
||||
</p>
|
||||
|
||||
@@ -47,24 +45,6 @@ IDEA analyses Python more deeply, so "ready" doesn't mean the same work on
|
||||
both sides. Both are measured from the outside, the same way: see
|
||||
[`perf/compare`](perf/compare) to run it on your machine and projects.
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
pnpm install
|
||||
pnpm tauri dev
|
||||
```
|
||||
|
||||
Rust 1.96, Node 22, pnpm and the [Tauri prerequisites](https://v2.tauri.app/start/prerequisites/).
|
||||
|
||||
Native notebook execution tests are opt-in and need two distinct Python environments
|
||||
with `ipykernel` installed:
|
||||
|
||||
```sh
|
||||
OPENIDEA_TEST_PYTHON=/first/env/bin/python \
|
||||
OPENIDEA_TEST_PYTHON_SECOND=/second/env/bin/python \
|
||||
cargo test -p ide-notebook --test kernel_runtime -- --ignored --test-threads=1
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[Apache 2.0](LICENSE). Bundled third-party assets are listed in [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md).
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "openidea",
|
||||
"private": true,
|
||||
"description": "An open-source IDE inspired by IntelliJ IDEA",
|
||||
"version": "0.1.32",
|
||||
"version": "0.1.33",
|
||||
"license": "Apache-2.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -78,3 +78,11 @@ objc2-core-foundation = { version = "0.3", default-features = false, features =
|
||||
objc2-foundation = { version = "0.3", default-features = false, features = ["std", "block2", "NSNotification", "NSOperation", "NSString"] }
|
||||
# Used only by the debug font-restriction override; Cargo dependency cfg cannot test debug_assertions.
|
||||
objc2-web-kit = { version = "0.3", default-features = false, features = ["std", "WKWebViewConfiguration", "WKPreferences"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { version = "0.61", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Gdi",
|
||||
"Win32_UI_Shell",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
] }
|
||||
@@ -19,6 +19,8 @@ mod theme_frame;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod titlebar;
|
||||
mod window_groups;
|
||||
#[cfg(any(windows, test))]
|
||||
mod window_work_area;
|
||||
mod windows;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
@@ -70,6 +72,9 @@ pub fn run() {
|
||||
// Single instance first: a second launch focuses this one and opens its path argument.
|
||||
// Debug builds have a separate identifier per worktree.
|
||||
let app = app.plugin(tauri_plugin_single_instance::init(windows::on_second_instance));
|
||||
// Install before window-state restores maximized geometry during window creation.
|
||||
#[cfg(windows)]
|
||||
let app = app.plugin(window_work_area::init());
|
||||
let app = app.plugin(tauri_plugin_opener::init()).plugin(tauri_plugin_dialog::init());
|
||||
#[cfg(target_os = "linux")]
|
||||
let app = app.plugin(linux_window_state::plugin());
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
//! Native maximize bounds for every Windows frameless window, including state restoration.
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use native::init;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
struct Rect {
|
||||
left: i32,
|
||||
top: i32,
|
||||
right: i32,
|
||||
bottom: i32,
|
||||
}
|
||||
|
||||
/// All coordinates are physical pixels in the selected monitor's coordinate space.
|
||||
/// Auto-hide needs one exposed pixel, but an already reserved edge needs no extra inset.
|
||||
fn bounds(monitor: Rect, work: Rect, auto_hide: [bool; 4], fullscreen: bool) -> Rect {
|
||||
if fullscreen {
|
||||
return monitor;
|
||||
}
|
||||
let [left, top, right, bottom] = auto_hide;
|
||||
Rect {
|
||||
left: work.left + i32::from(left && work.left == monitor.left),
|
||||
top: work.top + i32::from(top && work.top == monitor.top),
|
||||
right: work.right - i32::from(right && work.right == monitor.right),
|
||||
bottom: work.bottom - i32::from(bottom && work.bottom == monitor.bottom),
|
||||
}
|
||||
}
|
||||
|
||||
fn maximize_geometry(monitor: Rect, area: Rect) -> (i32, i32, i32, i32) {
|
||||
(area.left - monitor.left, area.top - monitor.top, area.right - area.left, area.bottom - area.top)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod native {
|
||||
use super::{Rect, bounds, maximize_geometry};
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{HWND, LPARAM, LRESULT, RECT, WPARAM},
|
||||
Graphics::Gdi::{
|
||||
GetMonitorInfoW, HMONITOR, MONITOR_DEFAULTTONEAREST, MONITORINFO, MonitorFromRect, MonitorFromWindow,
|
||||
},
|
||||
UI::{
|
||||
Shell::{
|
||||
ABE_BOTTOM, ABE_LEFT, ABE_RIGHT, ABE_TOP, ABM_GETAUTOHIDEBAREX, APPBARDATA, DefSubclassProc,
|
||||
RemoveWindowSubclass, SHAppBarMessage, SetWindowSubclass,
|
||||
},
|
||||
WindowsAndMessaging::{
|
||||
GWL_STYLE, GetWindowLongPtrW, IsZoomed, MINMAXINFO, NCCALCSIZE_PARAMS, WM_GETMINMAXINFO, WM_NCCALCSIZE,
|
||||
WM_NCDESTROY, WS_CAPTION,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const SUBCLASS: usize = 0x410;
|
||||
|
||||
pub fn init() -> tauri::plugin::TauriPlugin<tauri::Wry> {
|
||||
tauri::plugin::Builder::new("window-work-area")
|
||||
.on_window_ready(|window| {
|
||||
if window.is_decorated().unwrap_or(true) {
|
||||
return;
|
||||
}
|
||||
let install = || -> tauri::Result<()> {
|
||||
let hwnd = window.hwnd()?.0 as usize;
|
||||
window.run_on_main_thread(move || {
|
||||
// Subclasses must be installed and removed on the owning GUI thread.
|
||||
if unsafe { SetWindowSubclass(hwnd as HWND, Some(window_proc), SUBCLASS, 0) } == 0 {
|
||||
tracing::warn!(
|
||||
"cannot install window work area handler: {}",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
})
|
||||
};
|
||||
if let Err(error) = install() {
|
||||
tracing::warn!("cannot install window work area handler: {error}");
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
fn rect(rect: RECT) -> Rect {
|
||||
Rect { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }
|
||||
}
|
||||
|
||||
fn native_rect(rect: Rect) -> RECT {
|
||||
RECT { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }
|
||||
}
|
||||
|
||||
unsafe fn monitor_bounds(monitor: HMONITOR, fullscreen: bool) -> Option<(Rect, Rect)> {
|
||||
let mut info = MONITORINFO { cbSize: size_of::<MONITORINFO>() as u32, ..Default::default() };
|
||||
if unsafe { GetMonitorInfoW(monitor, &mut info) } == 0 {
|
||||
return None;
|
||||
}
|
||||
let mut auto_hide = [false; 4];
|
||||
if !fullscreen {
|
||||
for (index, edge) in [ABE_LEFT, ABE_TOP, ABE_RIGHT, ABE_BOTTOM].into_iter().enumerate() {
|
||||
let mut data = APPBARDATA {
|
||||
cbSize: size_of::<APPBARDATA>() as u32,
|
||||
uEdge: edge,
|
||||
rc: info.rcMonitor,
|
||||
..Default::default()
|
||||
};
|
||||
auto_hide[index] = unsafe { SHAppBarMessage(ABM_GETAUTOHIDEBAREX, &mut data) } != 0;
|
||||
}
|
||||
}
|
||||
let monitor = rect(info.rcMonitor);
|
||||
Some((monitor, bounds(monitor, rect(info.rcWork), auto_hide, fullscreen)))
|
||||
}
|
||||
|
||||
unsafe extern "system" fn window_proc(
|
||||
hwnd: HWND,
|
||||
message: u32,
|
||||
wparam: WPARAM,
|
||||
lparam: LPARAM,
|
||||
_id: usize,
|
||||
_data: usize,
|
||||
) -> LRESULT {
|
||||
// Tao keeps WS_CAPTION on frameless windows and removes it for native fullscreen.
|
||||
// Read native styles here: a Tauri state query from its window procedure can deadlock.
|
||||
let fullscreen = unsafe { GetWindowLongPtrW(hwnd, GWL_STYLE) } as u32 & WS_CAPTION == 0;
|
||||
match message {
|
||||
WM_GETMINMAXINFO if !fullscreen => {
|
||||
// Keep Tao's min/max tracking constraints, then set the outer maximize bounds.
|
||||
let result = unsafe { DefSubclassProc(hwnd, message, wparam, lparam) };
|
||||
let monitor = unsafe { MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) };
|
||||
if let Some((monitor, area)) = unsafe { monitor_bounds(monitor, false) } {
|
||||
let (x, y, width, height) = maximize_geometry(monitor, area);
|
||||
let info = unsafe { &mut *(lparam as *mut MINMAXINFO) };
|
||||
info.ptMaxPosition.x = x;
|
||||
info.ptMaxPosition.y = y;
|
||||
info.ptMaxSize.x = width;
|
||||
info.ptMaxSize.y = height;
|
||||
}
|
||||
result
|
||||
}
|
||||
WM_NCCALCSIZE if wparam != 0 && (fullscreen || unsafe { IsZoomed(hwnd) } != 0) => {
|
||||
let params = unsafe { &mut *(lparam as *mut NCCALCSIZE_PARAMS) };
|
||||
// Use the proposed rectangle: a move/snap/DPI change can target another monitor.
|
||||
let monitor = unsafe { MonitorFromRect(¶ms.rgrc[0], MONITOR_DEFAULTTONEAREST) };
|
||||
if let Some((_, area)) = unsafe { monitor_bounds(monitor, fullscreen) } {
|
||||
// Replace Tao's client-only clamp and global auto-hide query. Fullscreen
|
||||
// must retain the entire display, even when entered from a maximized window.
|
||||
params.rgrc[0] = native_rect(area);
|
||||
0
|
||||
} else {
|
||||
unsafe { DefSubclassProc(hwnd, message, wparam, lparam) }
|
||||
}
|
||||
}
|
||||
WM_NCDESTROY => {
|
||||
unsafe { RemoveWindowSubclass(hwnd, Some(window_proc), SUBCLASS) };
|
||||
unsafe { DefSubclassProc(hwnd, message, wparam, lparam) }
|
||||
}
|
||||
_ => unsafe { DefSubclassProc(hwnd, message, wparam, lparam) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn r(left: i32, top: i32, right: i32, bottom: i32) -> Rect {
|
||||
Rect { left, top, right, bottom }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn taskbars_on_every_edge_and_secondary_displays() {
|
||||
for (monitor, work, expected) in [
|
||||
// Reported case: maximized window must leave the bottom taskbar visible.
|
||||
(r(0, 0, 1920, 1080), r(0, 0, 1920, 1040), (0, 0, 1920, 1040)),
|
||||
(r(0, 0, 1920, 1080), r(48, 0, 1920, 1080), (48, 0, 1872, 1080)),
|
||||
(r(0, 0, 1920, 1080), r(0, 40, 1920, 1080), (0, 40, 1920, 1040)),
|
||||
(r(0, 0, 1920, 1080), r(0, 0, 1872, 1080), (0, 0, 1872, 1080)),
|
||||
// Negative origin, top taskbar, 150% display beside a 100% display.
|
||||
(r(-2560, -1440, 0, 0), r(-2560, -1380, 0, 0), (0, 60, 2560, 1380)),
|
||||
// 250% display: physical bounds must not be scaled with the previous monitor's DPI.
|
||||
(r(1920, 0, 5760, 2160), r(1920, 0, 5760, 2060), (0, 0, 3840, 2060)),
|
||||
] {
|
||||
let area = bounds(monitor, work, [false; 4], false);
|
||||
assert_eq!(area, work);
|
||||
assert_eq!(maximize_geometry(monitor, area), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_hide_leaves_a_physical_pixel_only_on_its_own_monitor_edge() {
|
||||
let monitor = r(-1920, 0, 0, 1080);
|
||||
for (edges, expected) in [
|
||||
([true, false, false, false], r(-1919, 0, 0, 1080)),
|
||||
([false, true, false, false], r(-1920, 1, 0, 1080)),
|
||||
([false, false, true, false], r(-1920, 0, -1, 1080)),
|
||||
([false, false, false, true], r(-1920, 0, 0, 1079)),
|
||||
([false; 4], monitor),
|
||||
([true; 4], r(-1919, 1, -1, 1079)),
|
||||
] {
|
||||
assert_eq!(bounds(monitor, monitor, edges, false), expected);
|
||||
}
|
||||
let reserved = r(-1920, 0, 0, 1040);
|
||||
assert_eq!(bounds(monitor, reserved, [false, false, false, true], false), reserved);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fullscreen_covers_taskbars_including_when_entered_from_maximized() {
|
||||
let monitor = r(1920, -100, 5760, 2060);
|
||||
let work = r(1980, -100, 5760, 1960);
|
||||
assert_eq!(bounds(monitor, work, [true; 4], true), monitor);
|
||||
assert_eq!(bounds(monitor, work, [false; 4], false), work);
|
||||
}
|
||||
}
|
||||
@@ -841,9 +841,18 @@ fn fit_settings_window(window: &WebviewWindow, parent: &WebviewWindow) -> tauri:
|
||||
/// scale and its position is given in physical pixels.
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub(super) fn place_settings_window(window: &WebviewWindow, parent: &WebviewWindow) -> tauri::Result<()> {
|
||||
// Placement setters leave maximized mode. Fit the restored frame, then reapply the saved state.
|
||||
// A restored fullscreen window already covers its display and must not be fitted to the work area.
|
||||
if window.is_fullscreen()? {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(monitor) = parent.current_monitor()?.or(parent.primary_monitor()?) else {
|
||||
return Ok(());
|
||||
};
|
||||
let maximized = window.is_maximized()?;
|
||||
if maximized {
|
||||
window.unmaximize()?;
|
||||
}
|
||||
let scale = monitor.scale_factor();
|
||||
let area = monitor.work_area();
|
||||
let origin = area.position.to_logical::<f64>(scale);
|
||||
@@ -872,6 +881,9 @@ pub(super) fn place_settings_window(window: &WebviewWindow, parent: &WebviewWind
|
||||
)))?;
|
||||
window.set_size(tauri::LogicalSize::new(width, height))?;
|
||||
}
|
||||
if maximized {
|
||||
window.maximize()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "OpenIDEA",
|
||||
"version": "0.1.32",
|
||||
"version": "0.1.33",
|
||||
"identifier": "ai.l0ng.openidea",
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm dev",
|
||||
|
||||
Reference in new issue
Block a user