modal: Fix modal, drawer overlay position on Linux. (#515)
- Update `overlay` for Modal, still handle click out to dismiss, even it no overlay.
This commit is contained in:
parent
6acbfb5298
commit
9eba97ddf6
4 changed files with 80 additions and 67 deletions
|
|
@ -15,7 +15,9 @@ use crate::{
|
||||||
scroll::ScrollbarAxis,
|
scroll::ScrollbarAxis,
|
||||||
theme::ActiveTheme,
|
theme::ActiveTheme,
|
||||||
title_bar::TITLE_BAR_HEIGHT,
|
title_bar::TITLE_BAR_HEIGHT,
|
||||||
v_flex, IconName, Placement, Sizable, StyledExt as _,
|
v_flex,
|
||||||
|
window_border::SHADOW_SIZE,
|
||||||
|
IconName, Placement, Sizable, StyledExt as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(drawer, [Escape]);
|
actions!(drawer, [Escape]);
|
||||||
|
|
@ -119,11 +121,11 @@ impl RenderOnce for Drawer {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
let placement = self.placement;
|
let placement = self.placement;
|
||||||
let titlebar_height = self.margin_top;
|
let titlebar_height = self.margin_top;
|
||||||
let size = cx.viewport_size();
|
let size = cx.viewport_size() - gpui::size(SHADOW_SIZE * 2, SHADOW_SIZE * 2);
|
||||||
let on_close = self.on_close.clone();
|
let on_close = self.on_close.clone();
|
||||||
|
|
||||||
anchored()
|
anchored()
|
||||||
.position(point(px(0.), titlebar_height))
|
.position(point(px(0.) + SHADOW_SIZE, titlebar_height + SHADOW_SIZE))
|
||||||
.snap_to_window()
|
.snap_to_window()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{rc::Rc, time::Duration};
|
use std::{rc::Rc, time::Duration};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, anchored, div, hsla, prelude::FluentBuilder, px, relative, Animation,
|
actions, anchored, div, hsla, point, prelude::FluentBuilder, px, relative, Animation,
|
||||||
AnimationExt as _, AnyElement, AppContext, Bounds, ClickEvent, Div, FocusHandle, Hsla,
|
AnimationExt as _, AnyElement, AppContext, Bounds, ClickEvent, Div, FocusHandle, Hsla,
|
||||||
InteractiveElement, IntoElement, KeyBinding, MouseButton, ParentElement, Pixels, Point,
|
InteractiveElement, IntoElement, KeyBinding, MouseButton, ParentElement, Pixels, Point,
|
||||||
RenderOnce, SharedString, Styled, WindowContext,
|
RenderOnce, SharedString, Styled, WindowContext,
|
||||||
|
|
@ -11,7 +11,9 @@ use crate::{
|
||||||
animation::cubic_bezier,
|
animation::cubic_bezier,
|
||||||
button::{Button, ButtonVariants as _},
|
button::{Button, ButtonVariants as _},
|
||||||
theme::ActiveTheme as _,
|
theme::ActiveTheme as _,
|
||||||
v_flex, ContextModal, IconName, Sizable as _,
|
v_flex,
|
||||||
|
window_border::SHADOW_SIZE,
|
||||||
|
ContextModal, IconName, Sizable as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(modal, [Escape]);
|
actions!(modal, [Escape]);
|
||||||
|
|
@ -162,7 +164,7 @@ impl RenderOnce for Modal {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl gpui::IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl gpui::IntoElement {
|
||||||
let layer_ix = self.layer_ix;
|
let layer_ix = self.layer_ix;
|
||||||
let on_close = self.on_close.clone();
|
let on_close = self.on_close.clone();
|
||||||
let view_size = cx.viewport_size();
|
let view_size = cx.viewport_size() - gpui::size(SHADOW_SIZE * 2, SHADOW_SIZE * 2);
|
||||||
let bounds = Bounds {
|
let bounds = Bounds {
|
||||||
origin: Point::default(),
|
origin: Point::default(),
|
||||||
size: view_size,
|
size: view_size,
|
||||||
|
|
@ -171,78 +173,83 @@ impl RenderOnce for Modal {
|
||||||
let y = self.margin_top.unwrap_or(view_size.height / 10.) + offset_top;
|
let y = self.margin_top.unwrap_or(view_size.height / 10.) + offset_top;
|
||||||
let x = bounds.center().x - self.width / 2.;
|
let x = bounds.center().x - self.width / 2.;
|
||||||
|
|
||||||
anchored().snap_to_window().child(
|
anchored()
|
||||||
div()
|
.position(point(SHADOW_SIZE, SHADOW_SIZE))
|
||||||
.occlude()
|
.snap_to_window()
|
||||||
.w(view_size.width)
|
.child(
|
||||||
.h(view_size.height)
|
div()
|
||||||
.when(self.overlay_visible, |this| {
|
.occlude()
|
||||||
this.bg(overlay_color(self.overlay, cx))
|
.w(view_size.width)
|
||||||
})
|
.h(view_size.height)
|
||||||
.when(self.overlay, |this| {
|
.when(self.overlay_visible, |this| {
|
||||||
this.on_mouse_down(MouseButton::Left, {
|
this.bg(overlay_color(self.overlay, cx))
|
||||||
|
})
|
||||||
|
.on_mouse_down(MouseButton::Left, {
|
||||||
let on_close = self.on_close.clone();
|
let on_close = self.on_close.clone();
|
||||||
move |_, cx| {
|
move |_, cx| {
|
||||||
on_close(&ClickEvent::default(), cx);
|
on_close(&ClickEvent::default(), cx);
|
||||||
cx.close_modal();
|
cx.close_modal();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
.child(
|
||||||
.child(
|
self.base
|
||||||
self.base
|
.id(SharedString::from(format!("modal-{layer_ix}")))
|
||||||
.id(SharedString::from(format!("modal-{layer_ix}")))
|
.key_context(CONTEXT)
|
||||||
.key_context(CONTEXT)
|
.track_focus(&self.focus_handle)
|
||||||
.track_focus(&self.focus_handle)
|
.when(self.keyboard, |this| {
|
||||||
.when(self.keyboard, |this| {
|
this.on_action({
|
||||||
this.on_action({
|
let on_close = self.on_close.clone();
|
||||||
let on_close = self.on_close.clone();
|
move |_: &Escape, cx| {
|
||||||
move |_: &Escape, cx| {
|
// FIXME:
|
||||||
// FIXME:
|
//
|
||||||
//
|
// Here some Modal have no focus_handle, so it will not work will Escape key.
|
||||||
// Here some Modal have no focus_handle, so it will not work will Escape key.
|
// But by now, we `cx.close_modal()` going to close the last active model, so the Escape is unexpected to work.
|
||||||
// But by now, we `cx.close_modal()` going to close the last active model, so the Escape is unexpected to work.
|
on_close(&ClickEvent::default(), cx);
|
||||||
on_close(&ClickEvent::default(), cx);
|
cx.close_modal();
|
||||||
cx.close_modal();
|
}
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
})
|
.absolute()
|
||||||
.absolute()
|
.occlude()
|
||||||
.occlude()
|
.relative()
|
||||||
.relative()
|
.left(x)
|
||||||
.left(x)
|
.top(y)
|
||||||
.top(y)
|
.w(self.width)
|
||||||
.w(self.width)
|
.when_some(self.max_width, |this, w| this.max_w(w))
|
||||||
.when_some(self.max_width, |this, w| this.max_w(w))
|
.when_some(self.title, |this, title| {
|
||||||
.when_some(self.title, |this, title| {
|
this.child(div().line_height(relative(1.)).child(title))
|
||||||
this.child(div().line_height(relative(1.)).child(title))
|
})
|
||||||
})
|
.when(self.show_close, |this| {
|
||||||
.when(self.show_close, |this| {
|
this.child(
|
||||||
this.child(
|
Button::new(SharedString::from(format!(
|
||||||
Button::new(SharedString::from(format!("modal-close-{layer_ix}")))
|
"modal-close-{layer_ix}"
|
||||||
|
)))
|
||||||
.absolute()
|
.absolute()
|
||||||
.top_2()
|
.top_2()
|
||||||
.right_2()
|
.right_2()
|
||||||
.small()
|
.small()
|
||||||
.ghost()
|
.ghost()
|
||||||
.icon(IconName::Close)
|
.icon(IconName::Close)
|
||||||
.on_click(move |_, cx| {
|
.on_click(
|
||||||
on_close(&ClickEvent::default(), cx);
|
move |_, cx| {
|
||||||
cx.close_modal();
|
on_close(&ClickEvent::default(), cx);
|
||||||
}),
|
cx.close_modal();
|
||||||
)
|
},
|
||||||
})
|
),
|
||||||
.child(self.content)
|
)
|
||||||
.children(self.footer)
|
})
|
||||||
.with_animation(
|
.child(self.content)
|
||||||
"slide-down",
|
.children(self.footer)
|
||||||
Animation::new(Duration::from_secs_f64(0.25))
|
.with_animation(
|
||||||
.with_easing(cubic_bezier(0.32, 0.72, 0., 1.)),
|
"slide-down",
|
||||||
move |this, delta| {
|
Animation::new(Duration::from_secs_f64(0.25))
|
||||||
let y_offset = px(0.) + delta * px(30.);
|
.with_easing(cubic_bezier(0.32, 0.72, 0., 1.)),
|
||||||
this.top(y + y_offset).opacity(delta)
|
move |this, delta| {
|
||||||
},
|
let y_offset = px(0.) + delta * px(30.);
|
||||||
),
|
this.top(y + y_offset).opacity(delta)
|
||||||
),
|
},
|
||||||
)
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,7 @@ impl Render for Root {
|
||||||
window_border().child(
|
window_border().child(
|
||||||
div()
|
div()
|
||||||
.id("root")
|
.id("root")
|
||||||
|
.relative()
|
||||||
.size_full()
|
.size_full()
|
||||||
.font_family(".SystemUIFont")
|
.font_family(".SystemUIFont")
|
||||||
.bg(cx.theme().background)
|
.bg(cx.theme().background)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ use gpui::{
|
||||||
|
|
||||||
use crate::theme::ActiveTheme;
|
use crate::theme::ActiveTheme;
|
||||||
|
|
||||||
const SHADOW_SIZE: Pixels = Pixels(12.0);
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
pub(crate) const SHADOW_SIZE: Pixels = Pixels(0.0);
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub(crate) const SHADOW_SIZE: Pixels = Pixels(12.0);
|
||||||
const BORDER_SIZE: Pixels = Pixels(1.0);
|
const BORDER_SIZE: Pixels = Pixels(1.0);
|
||||||
pub(crate) const BORDER_RADIUS: Pixels = Pixels(0.0);
|
pub(crate) const BORDER_RADIUS: Pixels = Pixels(0.0);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue