example: Fix to hide WebView when switch tab. (#764)
fixes #763 it also prevent crashing on linux due to gtk not initialized --------- Co-authored-by: Jason Lee <huacnlee@gmail.com>
This commit is contained in:
parent
99e7f8ee70
commit
4f0617e96f
5 changed files with 92 additions and 13 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -6257,6 +6257,7 @@ dependencies = [
|
||||||
"fake",
|
"fake",
|
||||||
"gpui",
|
"gpui",
|
||||||
"gpui-component",
|
"gpui-component",
|
||||||
|
"gtk",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"regex",
|
"regex",
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,8 @@ serde = "1"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
unindent = "0.2.3"
|
unindent = "0.2.3"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
|
gtk = { version = "0.18" }
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,7 @@ pub fn init(cx: &mut App) {
|
||||||
input_story::init(cx);
|
input_story::init(cx);
|
||||||
dropdown_story::init(cx);
|
dropdown_story::init(cx);
|
||||||
popup_story::init(cx);
|
popup_story::init(cx);
|
||||||
|
webview_story::init(cx);
|
||||||
|
|
||||||
let http_client = std::sync::Arc::new(
|
let http_client = std::sync::Arc::new(
|
||||||
reqwest_client::ReqwestClient::user_agent("gpui-component/story").unwrap(),
|
reqwest_client::ReqwestClient::user_agent("gpui-component/story").unwrap(),
|
||||||
|
|
@ -226,9 +227,11 @@ pub fn init(cx: &mut App) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let view = cx.new(|cx| {
|
let view = cx.new(|cx| {
|
||||||
let (title, description, closable, zoomable, story) = story_state.to_story(window, cx);
|
let (title, description, closable, zoomable, story, on_active) =
|
||||||
let mut container =
|
story_state.to_story(window, cx);
|
||||||
StoryContainer::new(window, cx).story(story, story_state.story_klass);
|
let mut container = StoryContainer::new(window, cx)
|
||||||
|
.story(story, story_state.story_klass)
|
||||||
|
.on_active(on_active);
|
||||||
|
|
||||||
cx.on_focus_in(
|
cx.on_focus_in(
|
||||||
&container.focus_handle,
|
&container.focus_handle,
|
||||||
|
|
@ -279,6 +282,7 @@ pub struct StoryContainer {
|
||||||
story_klass: Option<SharedString>,
|
story_klass: Option<SharedString>,
|
||||||
closable: bool,
|
closable: bool,
|
||||||
zoomable: Option<PanelControl>,
|
zoomable: Option<PanelControl>,
|
||||||
|
on_active: Option<fn(AnyView, bool, &mut Window, &mut App)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -305,6 +309,22 @@ pub trait Story: Focusable + Render {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable>;
|
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable>;
|
||||||
|
|
||||||
|
fn on_active(&mut self, active: bool, window: &mut Window, cx: &mut App) {
|
||||||
|
let _ = active;
|
||||||
|
let _ = window;
|
||||||
|
let _ = cx;
|
||||||
|
}
|
||||||
|
fn on_active_any(view: AnyView, active: bool, window: &mut Window, cx: &mut App)
|
||||||
|
where
|
||||||
|
Self: 'static,
|
||||||
|
{
|
||||||
|
if let Some(story) = view.downcast::<Self>().ok() {
|
||||||
|
cx.update_entity(&story, |story, cx| {
|
||||||
|
story.on_active(active, window, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventEmitter<ContainerEvent> for StoryContainer {}
|
impl EventEmitter<ContainerEvent> for StoryContainer {}
|
||||||
|
|
@ -324,6 +344,7 @@ impl StoryContainer {
|
||||||
story_klass: None,
|
story_klass: None,
|
||||||
closable: true,
|
closable: true,
|
||||||
zoomable: Some(PanelControl::default()),
|
zoomable: Some(PanelControl::default()),
|
||||||
|
on_active: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,7 +356,9 @@ impl StoryContainer {
|
||||||
let focus_handle = story.focus_handle(cx);
|
let focus_handle = story.focus_handle(cx);
|
||||||
|
|
||||||
let view = cx.new(|cx| {
|
let view = cx.new(|cx| {
|
||||||
let mut story = Self::new(window, cx).story(story.into(), story_klass);
|
let mut story = Self::new(window, cx)
|
||||||
|
.story(story.into(), story_klass)
|
||||||
|
.on_active(S::on_active_any);
|
||||||
story.focus_handle = focus_handle;
|
story.focus_handle = focus_handle;
|
||||||
story.closable = S::closable();
|
story.closable = S::closable();
|
||||||
story.zoomable = S::zoomable();
|
story.zoomable = S::zoomable();
|
||||||
|
|
@ -363,6 +386,10 @@ impl StoryContainer {
|
||||||
self.story_klass = Some(story_klass.into());
|
self.story_klass = Some(story_klass.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub fn on_active(mut self, on_active: fn(AnyView, bool, &mut Window, &mut App)) -> Self {
|
||||||
|
self.on_active = Some(on_active);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn on_action_panel_info(
|
fn on_action_panel_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -420,6 +447,7 @@ impl StoryState {
|
||||||
bool,
|
bool,
|
||||||
Option<PanelControl>,
|
Option<PanelControl>,
|
||||||
AnyView,
|
AnyView,
|
||||||
|
fn(AnyView, bool, &mut Window, &mut App),
|
||||||
) {
|
) {
|
||||||
macro_rules! story {
|
macro_rules! story {
|
||||||
($klass:tt) => {
|
($klass:tt) => {
|
||||||
|
|
@ -429,6 +457,7 @@ impl StoryState {
|
||||||
$klass::closable(),
|
$klass::closable(),
|
||||||
$klass::zoomable(),
|
$klass::zoomable(),
|
||||||
$klass::view(window, cx).into(),
|
$klass::view(window, cx).into(),
|
||||||
|
$klass::on_active_any,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -500,8 +529,13 @@ impl Panel for StoryContainer {
|
||||||
println!("panel: {} zoomed: {}", self.name, zoomed);
|
println!("panel: {} zoomed: {}", self.name, zoomed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_active(&mut self, active: bool, _window: &mut Window, _cx: &mut App) {
|
fn set_active(&mut self, active: bool, _window: &mut Window, cx: &mut App) {
|
||||||
println!("panel: {} active: {}", self.name, active);
|
println!("panel: {} active: {}", self.name, active);
|
||||||
|
if let Some(on_active) = self.on_active {
|
||||||
|
if let Some(story) = self.story.clone() {
|
||||||
|
on_active(story, active, _window, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn popup_menu(&self, menu: PopupMenu, _window: &Window, _cx: &App) -> PopupMenu {
|
fn popup_menu(&self, menu: PopupMenu, _window: &Window, _cx: &App) -> PopupMenu {
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,18 @@ use gpui_component::{
|
||||||
button::{Button, ButtonVariants as _},
|
button::{Button, ButtonVariants as _},
|
||||||
dock::{DockArea, DockAreaState, DockEvent, DockItem, DockPlacement},
|
dock::{DockArea, DockAreaState, DockEvent, DockItem, DockPlacement},
|
||||||
popup_menu::PopupMenuExt,
|
popup_menu::PopupMenuExt,
|
||||||
IconName, Root, Sizable, Theme, TitleBar,
|
IconName, Root, Sizable,
|
||||||
};
|
};
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
use gpui_component::{Theme, TitleBar};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
use story::{
|
use story::{
|
||||||
AccordionStory, AppState, AppTitleBar, Assets, ButtonStory, CalendarStory, DropdownStory,
|
AccordionStory, AppState, AppTitleBar, Assets, ButtonStory, CalendarStory, DropdownStory,
|
||||||
FormStory, IconStory, ImageStory, InputStory, ListStory, ModalStory, Open, PopupStory,
|
FormStory, IconStory, ImageStory, InputStory, ListStory, ModalStory, Open, PopupStory,
|
||||||
ProgressStory, Quit, ResizableStory, ScrollableStory, SidebarStory, StoryContainer,
|
ProgressStory, Quit, ResizableStory, ScrollableStory, SidebarStory, StoryContainer,
|
||||||
SwitchStory, TableStory, TextStory, TooltipStory,
|
SwitchStory, TableStory, TextStory, TooltipStory, WebViewStory,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||||
|
|
@ -365,7 +368,7 @@ impl StoryWorkspace {
|
||||||
Arc::new(StoryContainer::panel::<AccordionStory>(window, cx)),
|
Arc::new(StoryContainer::panel::<AccordionStory>(window, cx)),
|
||||||
Arc::new(StoryContainer::panel::<SidebarStory>(window, cx)),
|
Arc::new(StoryContainer::panel::<SidebarStory>(window, cx)),
|
||||||
Arc::new(StoryContainer::panel::<FormStory>(window, cx)),
|
Arc::new(StoryContainer::panel::<FormStory>(window, cx)),
|
||||||
// Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
&dock_area,
|
&dock_area,
|
||||||
|
|
@ -452,7 +455,7 @@ impl StoryWorkspace {
|
||||||
14 => Arc::new(StoryContainer::panel::<ResizableStory>(window, cx)),
|
14 => Arc::new(StoryContainer::panel::<ResizableStory>(window, cx)),
|
||||||
15 => Arc::new(StoryContainer::panel::<ScrollableStory>(window, cx)),
|
15 => Arc::new(StoryContainer::panel::<ScrollableStory>(window, cx)),
|
||||||
16 => Arc::new(StoryContainer::panel::<AccordionStory>(window, cx)),
|
16 => Arc::new(StoryContainer::panel::<AccordionStory>(window, cx)),
|
||||||
// 17 => Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
17 => Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
||||||
_ => Arc::new(StoryContainer::panel::<ButtonStory>(window, cx)),
|
_ => Arc::new(StoryContainer::panel::<ButtonStory>(window, cx)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,11 @@ use gpui_component::{
|
||||||
webview::WebView,
|
webview::WebView,
|
||||||
wry, ActiveTheme,
|
wry, ActiveTheme,
|
||||||
};
|
};
|
||||||
use raw_window_handle::HasWindowHandle;
|
|
||||||
|
pub fn init(_: &mut App) {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
gtk::init().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WebViewStory {
|
pub struct WebViewStory {
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
|
|
@ -25,6 +29,13 @@ impl super::Story for WebViewStory {
|
||||||
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
|
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
|
||||||
Self::view(window, cx)
|
Self::view(window, cx)
|
||||||
}
|
}
|
||||||
|
fn on_active(&mut self, active: bool, _window: &mut Window, cx: &mut App) {
|
||||||
|
if active {
|
||||||
|
self.webview.update(cx, |webview, _| webview.show());
|
||||||
|
} else {
|
||||||
|
self.webview.update(cx, |webview, _| webview.hide());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebViewStory {
|
impl WebViewStory {
|
||||||
|
|
@ -32,9 +43,36 @@ impl WebViewStory {
|
||||||
let focus_handle = cx.focus_handle();
|
let focus_handle = cx.focus_handle();
|
||||||
|
|
||||||
let webview = cx.new(|cx| {
|
let webview = cx.new(|cx| {
|
||||||
let webview = wry::WebViewBuilder::new()
|
let builder = wry::WebViewBuilder::new();
|
||||||
.build_as_child(&window.window_handle().expect("No window handle"))
|
#[cfg(not(any(
|
||||||
.unwrap();
|
target_os = "windows",
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "ios",
|
||||||
|
target_os = "android"
|
||||||
|
)))]
|
||||||
|
let webview = {
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use wry::WebViewBuilderExtUnix;
|
||||||
|
// borrowed from https://github.com/tauri-apps/wry/blob/dev/examples/gtk_multiwebview.rs
|
||||||
|
// doesn't work yet
|
||||||
|
// TODO: How to initialize this fixed?
|
||||||
|
let fixed = gtk::Fixed::builder().build();
|
||||||
|
fixed.show_all();
|
||||||
|
builder.build_gtk(&fixed).unwrap()
|
||||||
|
};
|
||||||
|
#[cfg(any(
|
||||||
|
target_os = "windows",
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "ios",
|
||||||
|
target_os = "android"
|
||||||
|
))]
|
||||||
|
let webview = {
|
||||||
|
use raw_window_handle::HasWindowHandle;
|
||||||
|
|
||||||
|
let window_handle = window.window_handle().expect("No window handle");
|
||||||
|
builder.build_as_child(&window_handle).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
WebView::new(webview, window, cx)
|
WebView::new(webview, window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue