Skip to content

Commit 253029f

Browse files
committed
Fix tool bootstrap detection and macOS pane/fullscreen visuals
1 parent bfac831 commit 253029f

3 files changed

Lines changed: 76 additions & 67 deletions

File tree

assets/shell-integration/install_cli_tools.sh

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,73 @@ ensure_homebrew_installation() {
4343

4444
resolved_tool_path() {
4545
local tool_name="$1"
46-
command -v "$tool_name" 2>/dev/null || true
46+
if command -v "$tool_name" >/dev/null 2>&1; then
47+
command -v "$tool_name"
48+
return 0
49+
fi
50+
51+
for candidate in "/opt/homebrew/bin/$tool_name" "/usr/local/bin/$tool_name"; do
52+
if [[ -x "$candidate" ]]; then
53+
echo "$candidate"
54+
return 0
55+
fi
56+
done
57+
58+
return 1
4759
}
4860

4961
is_legacy_tool_active() {
5062
local tool_name="$1"
5163
local resolved
52-
resolved="$(resolved_tool_path "$tool_name")"
64+
resolved="$(resolved_tool_path "$tool_name" 2>/dev/null || true)"
5365
[[ "$resolved" == "$USER_BIN_DIR/$tool_name" ]]
5466
}
5567

68+
is_brew_formula_installed() {
69+
local formula_name="$1"
70+
71+
if [[ -z "$BREW_BIN" ]]; then
72+
BREW_BIN="$(resolve_brew_bin 2>/dev/null || true)"
73+
fi
74+
75+
if [[ -z "$BREW_BIN" ]]; then
76+
return 1
77+
fi
78+
79+
"$BREW_BIN" list --formula --versions "$formula_name" >/dev/null 2>&1
80+
}
81+
82+
should_install_formula() {
83+
local tool_name="$1"
84+
local formula_name="$2"
85+
local allow_legacy="${3:-0}"
86+
87+
if resolved_tool_path "$tool_name" >/dev/null 2>&1; then
88+
if [[ "$allow_legacy" == "1" ]] && is_legacy_tool_active "$tool_name"; then
89+
return 0
90+
fi
91+
return 1
92+
fi
93+
94+
# PATH can be minimal in non-interactive launch contexts.
95+
# If brew already has this formula installed, skip reinstall.
96+
if is_brew_formula_installed "$formula_name"; then
97+
return 1
98+
fi
99+
100+
return 0
101+
}
102+
56103
collect_missing_tools() {
57104
MISSING_TOOLS=()
58105

59-
if ! command -v starship >/dev/null 2>&1 || is_legacy_tool_active "starship"; then
106+
if should_install_formula "starship" "starship" 1; then
60107
MISSING_TOOLS+=("starship")
61108
fi
62-
if ! command -v delta >/dev/null 2>&1 || is_legacy_tool_active "delta"; then
109+
if should_install_formula "delta" "git-delta" 1; then
63110
MISSING_TOOLS+=("git-delta")
64111
fi
65-
if ! command -v lazygit >/dev/null 2>&1; then
112+
if should_install_formula "lazygit" "lazygit" 0; then
66113
MISSING_TOOLS+=("lazygit")
67114
fi
68115
}

kaku-gui/src/termwindow/render/paint.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -373,18 +373,19 @@ impl crate::TermWindow {
373373
if pos.is_active && num_panes > 1 {
374374
let cell_width = self.render_metrics.cell_size.width as f32;
375375
let cell_height = self.render_metrics.cell_size.height as f32;
376-
let (padding_left, _padding_top) = self.padding_left_top();
376+
let (padding_left, padding_top) = self.padding_left_top();
377377
let border = self.get_os_border();
378378
let tab_bar_height = if self.show_tab_bar {
379379
self.tab_bar_pixel_height().unwrap_or(0.)
380380
} else {
381381
0.
382382
};
383-
let top_pixel_y = if self.config.tab_bar_at_bottom {
383+
let top_bar_height = if self.config.tab_bar_at_bottom {
384384
0.0
385385
} else {
386386
tab_bar_height
387-
} + border.top.get() as f32;
387+
};
388+
let top_pixel_y = top_bar_height + padding_top + border.top.get() as f32;
388389

389390
let x = padding_left
390391
+ border.left.get() as f32
@@ -405,17 +406,22 @@ impl crate::TermWindow {
405406

406407
// Draw dot indicator for the active pane when split
407408
if let Some((dot_x, dot_y, is_top_pane)) = active_pane_top_right {
408-
let cell_height = self.render_metrics.cell_size.height as f32;
409-
// Size and margin scale with the current font's cell height so the
410-
// indicator looks consistent regardless of font size or display DPI.
411-
let dot_size = (cell_height * 0.6).round();
409+
const DOT_SIZE: f32 = 10.0;
412410
const DOT_ALPHA: f32 = 0.5;
413-
// Top pane: 2.5 cells below the pane top (clears the tab bar).
414-
// Lower panes: 3.5 cells below to stay clear of the split line.
411+
const RIGHT_INSET: f32 = 3.0;
412+
const TOP_PANE_MARGIN_WITH_TAB_BAR: f32 = 24.0;
413+
const TOP_PANE_MARGIN_NO_TAB_BAR: f32 = 14.0;
414+
const LOWER_PANE_MARGIN: f32 = 20.0;
415+
416+
let top_pane_margin = if self.show_tab_bar && !self.config.tab_bar_at_bottom {
417+
TOP_PANE_MARGIN_WITH_TAB_BAR
418+
} else {
419+
TOP_PANE_MARGIN_NO_TAB_BAR
420+
};
415421
let margin_top = if is_top_pane {
416-
cell_height * 2.5
422+
top_pane_margin
417423
} else {
418-
cell_height * 3.5
424+
LOWER_PANE_MARGIN
419425
};
420426
let dot_color = self.palette().cursor_bg.to_linear().mul_alpha(DOT_ALPHA);
421427

@@ -431,10 +437,10 @@ impl crate::TermWindow {
431437
self.poly_quad(
432438
&mut layers,
433439
2,
434-
euclid::point2(dot_x - dot_size, dot_y + margin_top),
440+
euclid::point2(dot_x - DOT_SIZE - RIGHT_INSET, dot_y + margin_top),
435441
CIRCLE_POLY,
436442
1,
437-
euclid::size2(dot_size, dot_size),
443+
euclid::size2(DOT_SIZE, DOT_SIZE),
438444
dot_color,
439445
)
440446
.context("active pane indicator")?;

window/src/os/macos/window.rs

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ const NSViewLayerContentsRedrawDuringViewResize: NSInteger = 2;
6464
const FULLSCREEN_ENTER_HIDE_CONTENT_MS: u64 = 30;
6565
const FULLSCREEN_EXIT_HIDE_CONTENT_MS: u64 = 20;
6666
const ZOOM_HIDE_CONTENT_MS: u64 = 20;
67-
const NATIVE_EXIT_HIDE_CONTENT_MS: u64 = 50;
68-
const NATIVE_EXIT_POST_HIDE_CONTENT_MS: u64 = 20;
6967
const MOVE_PERSIST_DELAY_SECS: f64 = 0.35;
7068

7169
#[link(name = "CoreGraphics", kind = "framework")]
@@ -1343,15 +1341,9 @@ impl WindowOps for Window {
13431341
match view.native_fullscreen_target.get() {
13441342
// Enter fullscreen: keep hidden for whole transition to avoid text scale pop.
13451343
Some(true) => return true,
1346-
// Exit fullscreen: reveal sooner so content comes back faster.
1347-
Some(false) => {
1348-
if let Some(until) = view.transition_hide_until.get() {
1349-
if Instant::now() < until {
1350-
return true;
1351-
}
1352-
view.transition_hide_until.set(None);
1353-
}
1354-
}
1344+
// Exit fullscreen: avoid showing a rectangular placeholder
1345+
// during the restore animation.
1346+
Some(false) => view.transition_hide_until.set(None),
13551347
None => return true,
13561348
}
13571349
}
@@ -1497,7 +1489,6 @@ impl WindowInner {
14971489
.native_fullscreen_transition_start
14981490
.set(Some(Instant::now()));
14991491
}
1500-
self.arm_transition_content_hide(NATIVE_EXIT_HIDE_CONTENT_MS, "native_pre_exit", true);
15011492
self.toggle_native_fullscreen();
15021493
true
15031494
} else {
@@ -2682,25 +2673,6 @@ impl WindowView {
26822673
}
26832674
}
26842675

2685-
fn schedule_transition_unhide_repaint(window_id: usize, duration_ms: u64) {
2686-
promise::spawn::spawn(async move {
2687-
async_io::Timer::after(Duration::from_millis(duration_ms)).await;
2688-
Connection::with_window_inner(window_id, move |inner| {
2689-
if let Some(window_view) = WindowView::get_this(unsafe { &**inner.view }) {
2690-
let mut state = window_view.inner.borrow_mut();
2691-
state.paint_throttled = false;
2692-
state.invalidated = true;
2693-
state.events.dispatch(WindowEvent::NeedRepaint);
2694-
}
2695-
unsafe {
2696-
let _: () = msg_send![*inner.view, setNeedsDisplay: YES];
2697-
}
2698-
Ok(())
2699-
});
2700-
})
2701-
.detach();
2702-
}
2703-
27042676
// Called by the inputContext manager when the IME processes events.
27052677
// We need to translate the selector back into appropriate key
27062678
// sequences
@@ -3814,21 +3786,9 @@ impl WindowView {
38143786
this.native_fullscreen_transition_active.set(true);
38153787
this.native_fullscreen_target.set(Some(false));
38163788
this.native_fullscreen_transition_start.set(Some(now));
3789+
this.transition_hide_until.set(None);
38173790
this.inner.borrow_mut().live_resizing = true;
38183791

3819-
// Native exit can be triggered by multiple entry points.
3820-
// Arm the same short hide window here so all paths stay consistent.
3821-
let should_arm_hide = this
3822-
.transition_hide_until
3823-
.get()
3824-
.map(|until| until <= now)
3825-
.unwrap_or(true);
3826-
if should_arm_hide {
3827-
this.transition_hide_until.set(Some(
3828-
now + Duration::from_millis(NATIVE_EXIT_HIDE_CONTENT_MS),
3829-
));
3830-
}
3831-
38323792
if let Ok(mut inner) = this.inner.try_borrow_mut() {
38333793
inner.paint_throttled = false;
38343794
inner.invalidated = true;
@@ -3847,13 +3807,9 @@ impl WindowView {
38473807
extern "C" fn did_exit_fullscreen(this: &mut Object, _sel: Sel, _notification: id) {
38483808
let view_id = this as *mut Object;
38493809
if let Some(this) = Self::get_this(this) {
3850-
let window_id = this.inner.borrow().window_id;
38513810
this.native_fullscreen_transition_active.set(false);
38523811
this.native_fullscreen_target.set(None);
3853-
this.transition_hide_until.set(Some(
3854-
Instant::now() + Duration::from_millis(NATIVE_EXIT_POST_HIDE_CONTENT_MS),
3855-
));
3856-
Self::schedule_transition_unhide_repaint(window_id, NATIVE_EXIT_POST_HIDE_CONTENT_MS);
3812+
this.transition_hide_until.set(None);
38573813
if let Ok(mut inner) = this.inner.try_borrow_mut() {
38583814
inner.live_resizing = true;
38593815
}

0 commit comments

Comments
 (0)